From c91efea8bafe8c58f91a4cc5818a617ed45f8bfe Mon Sep 17 00:00:00 2001 From: Kirill Klenov Date: Thu, 29 Jun 2017 16:45:27 +0300 Subject: [PATCH 01/79] Update auto PEP8. --- pymode/autopep8.py | 475 +++++++++++++++++++++++++++++++++------------ pymode/lint.py | 4 +- 2 files changed, 355 insertions(+), 124 deletions(-) diff --git a/pymode/autopep8.py b/pymode/autopep8.py index 13308751..62e5832f 100644 --- a/pymode/autopep8.py +++ b/pymode/autopep8.py @@ -2,7 +2,7 @@ # Copyright (C) 2010-2011 Hideo Hattori # Copyright (C) 2011-2013 Hideo Hattori, Steven Myint -# Copyright (C) 2013-2015 Hideo Hattori, Steven Myint, Bill Wendling +# Copyright (C) 2013-2016 Hideo Hattori, Steven Myint, Bill Wendling # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,8 +30,8 @@ "fix_(source)" to this module. They should return the fixed source code. These fixes are picked up by apply_global_fixes(). -Fixes that depend on pep8 should be added as methods to FixPEP8. See the class -documentation for more information. +Fixes that depend on pycodestyle should be added as methods to FixPEP8. See the +class documentation for more information. """ @@ -57,7 +57,7 @@ import token import tokenize -import pep8 +import pycodestyle try: @@ -66,7 +66,7 @@ unicode = str -__version__ = '1.2.1a0' +__version__ = '1.3.2' CR = '\r' @@ -75,6 +75,10 @@ PYTHON_SHEBANG_REGEX = re.compile(r'^#!.*\bpython[23]?\b\s*$') +LAMBDA_REGEX = re.compile(r'([\w.]+)\s=\slambda\s*([\(\)\w,\s.]*):') +COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+([^][)(}{]+)\s+(in|is)\s') +BARE_EXCEPT_REGEX = re.compile(r'except\s*:') +STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\s.*\):') # For generating line shortening candidates. @@ -88,7 +92,7 @@ ]) -DEFAULT_IGNORE = 'E24' +DEFAULT_IGNORE = 'E24,W503' DEFAULT_INDENT_SIZE = 4 @@ -122,25 +126,28 @@ PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') -def open_with_encoding(filename, encoding=None, mode='r'): +MAX_PYTHON_FILE_DETECTION_BYTES = 1024 + + +def open_with_encoding(filename, + encoding=None, mode='r', limit_byte_check=-1): """Return opened file with a specific encoding.""" if not encoding: - encoding = detect_encoding(filename) + encoding = detect_encoding(filename, limit_byte_check=limit_byte_check) return io.open(filename, mode=mode, encoding=encoding, newline='') # Preserve line endings -def detect_encoding(filename): +def detect_encoding(filename, limit_byte_check=-1): """Return file encoding.""" try: with open(filename, 'rb') as input_file: from lib2to3.pgen2 import tokenize as lib2to3_tokenize encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0] - # Check for correctness of encoding with open_with_encoding(filename, encoding) as test_file: - test_file.read() + test_file.read(limit_byte_check) return encoding except (LookupError, SyntaxError, UnicodeDecodeError): @@ -159,14 +166,10 @@ def extended_blank_lines(logical_line, indent_level, previous_logical): """Check for missing blank lines after class declaration.""" - if previous_logical.startswith('class '): - if logical_line.startswith(('def ', 'class ', '@')): - if indent_level and not blank_lines and not blank_before: - yield (0, 'E309 expected 1 blank line after class declaration') - elif previous_logical.startswith('def '): - if blank_lines and pep8.DOCSTRING_REGEX.match(logical_line): + if previous_logical.startswith('def '): + if blank_lines and pycodestyle.DOCSTRING_REGEX.match(logical_line): yield (0, 'E303 too many blank lines ({0})'.format(blank_lines)) - elif pep8.DOCSTRING_REGEX.match(previous_logical): + elif pycodestyle.DOCSTRING_REGEX.match(previous_logical): # Missing blank line between class docstring and method declaration. if ( indent_level and @@ -176,12 +179,14 @@ def extended_blank_lines(logical_line, '(self' in logical_line ): yield (0, 'E301 expected 1 blank line, found 0') -pep8.register_check(extended_blank_lines) + + +pycodestyle.register_check(extended_blank_lines) def continued_indentation(logical_line, tokens, indent_level, indent_char, noqa): - """Override pep8's function to provide indentation information.""" + """Override pycodestyle's function to provide indentation information.""" first_row = tokens[0][2][0] nrows = 1 + tokens[-1][2][0] - first_row if noqa or nrows == 1: @@ -234,7 +239,7 @@ def continued_indentation(logical_line, tokens, indent_level, indent_char, last_indent = start # Record the initial indent. - rel_indent[row] = pep8.expand_indent(line) - indent_level + rel_indent[row] = pycodestyle.expand_indent(line) - indent_level # Identify closing bracket. close_bracket = (token_type == tokenize.OP and text in ']})') @@ -282,6 +287,8 @@ def continued_indentation(logical_line, tokens, indent_level, indent_char, error = ('E122', one_indented) elif indent[depth]: error = ('E127', indent[depth]) + elif not close_bracket and hangs[depth]: + error = ('E131', one_indented) elif hang > DEFAULT_INDENT_SIZE: error = ('E126', one_indented) else: @@ -355,13 +362,18 @@ def continued_indentation(logical_line, tokens, indent_level, indent_char, if ( indent_next and not last_line_begins_with_multiline and - pep8.expand_indent(line) == indent_level + DEFAULT_INDENT_SIZE + pycodestyle.expand_indent(line) == indent_level + DEFAULT_INDENT_SIZE ): pos = (start[0], indent[0] + 4) - yield (pos, 'E125 {0}'.format(indent_level + - 2 * DEFAULT_INDENT_SIZE)) -del pep8._checks['logical_line'][pep8.continued_indentation] -pep8.register_check(continued_indentation) + desired_indent = indent_level + 2 * DEFAULT_INDENT_SIZE + if visual_indent: + yield (pos, 'E129 {0}'.format(desired_indent)) + else: + yield (pos, 'E125 {0}'.format(desired_indent)) + + +del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation] +pycodestyle.register_check(continued_indentation) class FixPEP8(object): @@ -373,16 +385,18 @@ class FixPEP8(object): The fixer method can take either one or two arguments (in addition to self). The first argument is "result", which is the error information from - pep8. The second argument, "logical", is required only for logical-line - fixes. + pycodestyle. The second argument, "logical", is required only for + logical-line fixes. The fixer method can return the list of modified lines or None. An empty list would mean that no changes were made. None would mean that only the - line reported in the pep8 error was modified. Note that the modified line - numbers that are returned are indexed at 1. This typically would correspond - with the line number reported in the pep8 error information. + line reported in the pycodestyle error was modified. Note that the modified + line numbers that are returned are indexed at 1. This typically would + correspond with the line number reported in the pycodestyle error + information. [fixed method list] + - e111,e114,e115,e116 - e121,e122,e123,e124,e125,e126,e127,e128,e129 - e201,e202,e203 - e211 @@ -391,12 +405,15 @@ class FixPEP8(object): - e251 - e261,e262 - e271,e272,e273,e274 - - e301,e302,e303 + - e301,e302,e303,e304,e306 - e401 - e502 - - e701,e702 - - e711 + - e701,e702,e703,e704 + - e711,e712,e713,e714 + - e722 + - e731 - w291 + - w503 """ @@ -417,7 +434,7 @@ def __init__(self, filename, set() if long_line_ignore_cache is None else long_line_ignore_cache) - # Many fixers are the same even though pep8 categorizes them + # Many fixers are the same even though pycodestyle categorizes them # differently. self.fix_e115 = self.fix_e112 self.fix_e116 = self.fix_e113 @@ -444,7 +461,7 @@ def __init__(self, filename, self.fix_e272 = self.fix_e271 self.fix_e273 = self.fix_e271 self.fix_e274 = self.fix_e271 - self.fix_e309 = self.fix_e301 + self.fix_e306 = self.fix_e301 self.fix_e501 = ( self.fix_long_line_logically if options and (options.aggressive >= 2 or options.experimental) else @@ -471,7 +488,7 @@ def _fix_source(self, results): line_index = result['line'] - 1 original_line = self.source[line_index] - is_logical_fix = len(inspect.getargspec(fix).args) > 2 + is_logical_fix = len(_get_parameters(fix)) > 2 if is_logical_fix: logical = None if logical_support: @@ -501,8 +518,8 @@ def _fix_source(self, results): elif modified_lines == []: # Empty list means no fix if self.options.verbose >= 2: print( - '---> Not fixing {f} on line {l}'.format( - f=result['id'], l=result['line']), + '---> Not fixing {error} on line {line}'.format( + error=result['id'], line=result['line']), file=sys.stderr) else: # We assume one-line fix when None. completed_lines.add(result['line']) @@ -609,15 +626,27 @@ def fix_e125(self, result): return modified_lines + def fix_e131(self, result): + """Fix indentation undistinguish from the next logical line.""" + num_indent_spaces = int(result['info'].split()[1]) + line_index = result['line'] - 1 + target = self.source[line_index] + + spaces_to_add = num_indent_spaces - len(_get_indentation(target)) + + if spaces_to_add >= 0: + self.source[line_index] = (' ' * spaces_to_add + + self.source[line_index]) + else: + offset = abs(spaces_to_add) + self.source[line_index] = self.source[line_index][offset:] + def fix_e201(self, result): """Remove extraneous whitespace.""" line_index = result['line'] - 1 target = self.source[line_index] offset = result['column'] - 1 - if is_probably_part_of_multiline(target): - return [] - fixed = fix_whitespace(target, offset=offset, replacement='') @@ -644,6 +673,21 @@ def fix_e225(self, result): _get_indentation(fixed) == _get_indentation(target) ): self.source[result['line'] - 1] = fixed + error_code = result.get('id', 0) + try: + ts = generate_tokens(fixed) + except tokenize.TokenError: + return + if not check_syntax(fixed.lstrip()): + return + errors = list( + pycodestyle.missing_whitespace_around_operator(fixed, ts)) + for e in reversed(errors): + if error_code != e[1].split()[0]: + continue + offset = e[0][1] + fixed = fixed[:offset] + ' ' + fixed[offset:] + self.source[result['line'] - 1] = fixed else: return [] @@ -652,7 +696,7 @@ def fix_e231(self, result): line_index = result['line'] - 1 target = self.source[line_index] offset = result['column'] - fixed = target[:offset] + ' ' + target[offset:] + fixed = target[:offset].rstrip() + ' ' + target[offset:].lstrip() self.source[line_index] = fixed def fix_e251(self, result): @@ -660,8 +704,8 @@ def fix_e251(self, result): line_index = result['line'] - 1 target = self.source[line_index] - # This is necessary since pep8 sometimes reports columns that goes - # past the end of the physical line. This happens in cases like, + # This is necessary since pycodestyle sometimes reports columns that + # goes past the end of the physical line. This happens in cases like, # foo(bar\n=None) c = min(result['column'] - 1, len(target) - 1) @@ -700,9 +744,6 @@ def fix_e271(self, result): target = self.source[line_index] offset = result['column'] - 1 - if is_probably_part_of_multiline(target): - return [] - fixed = fix_whitespace(target, offset=offset, replacement=' ') @@ -728,8 +769,8 @@ def fix_e303(self, result): delete_linenum = int(result['info'].split('(')[1].split(')')[0]) - 2 delete_linenum = max(1, delete_linenum) - # We need to count because pep8 reports an offset line number if there - # are comments. + # We need to count because pycodestyle reports an offset line number if + # there are comments. cnt = 0 line = result['line'] - 2 modified_lines = [] @@ -748,6 +789,23 @@ def fix_e304(self, result): if not self.source[line].strip(): self.source[line] = '' + def fix_e305(self, result): + """Add missing 2 blank lines after end of function or class.""" + cr = '\n' + # check comment line + offset = result['line'] - 2 + while True: + if offset < 0: + break + line = self.source[offset].lstrip() + if not line: + break + if line[0] != '#': + break + offset -= 1 + offset += 1 + self.source[offset] = cr + self.source[offset] + def fix_e401(self, result): """Put imports on separate lines.""" line_index = result['line'] - 1 @@ -795,8 +853,8 @@ def fix_long_line_logically(self, result, logical): self.source[line_index] = '' self.source[start_line_index] = fixed return range(start_line_index + 1, end_line_index + 1) - else: - return [] + + return [] def fix_long_line_physically(self, result): """Try to make lines fit within --max-line-length characters.""" @@ -818,8 +876,8 @@ def fix_long_line_physically(self, result): if fixed: self.source[line_index] = fixed return [line_index + 1] - else: - return [] + + return [] def fix_long_line(self, target, previous_line, next_line, original): @@ -828,11 +886,14 @@ def fix_long_line(self, target, previous_line, return [] if target.lstrip().startswith('#'): - # Wrap commented lines. - return shorten_comment( - line=target, - max_line_length=self.options.max_line_length, - last_comment=not next_line.lstrip().startswith('#')) + if self.options.aggressive: + # Wrap commented lines. + return shorten_comment( + line=target, + max_line_length=self.options.max_line_length, + last_comment=not next_line.lstrip().startswith('#')) + else: + return [] fixed = get_fixed_long_line( target=target, @@ -843,11 +904,12 @@ def fix_long_line(self, target, previous_line, aggressive=self.options.aggressive, experimental=self.options.experimental, verbose=self.options.verbose) + if fixed and not code_almost_equal(original, fixed): return fixed - else: - self.long_line_ignore_cache.add(cache_entry) - return None + + self.long_line_ignore_cache.add(cache_entry) + return None def fix_e502(self, result): """Remove extraneous escape of newline.""" @@ -873,6 +935,12 @@ def fix_e702(self, result, logical): return [] # pragma: no cover logical_lines = logical[2] + # Avoid applying this when indented. + # https://docs.python.org/reference/compound_stmts.html + for line in logical_lines: + if ':' in line: + return [] + line_index = result['line'] - 1 target = self.source[line_index] @@ -891,9 +959,9 @@ def fix_e702(self, result, logical): second = (_get_indentation(logical_lines[0]) + target[offset:].lstrip(';').lstrip()) - # find inline commnet + # Find inline comment. inline_comment = None - if '# ' == target[offset:].lstrip(';').lstrip()[:2]: + if target[offset:].lstrip(';').lstrip()[:2] == '# ': inline_comment = target[offset:].lstrip(';') if inline_comment: @@ -902,6 +970,17 @@ def fix_e702(self, result, logical): self.source[line_index] = first + '\n' + second return [line_index + 1] + def fix_e704(self, result): + """Fix multiple statements on one line def""" + (line_index, _, target) = get_index_offset_contents(result, + self.source) + match = STARTSWITH_DEF_REGEX.match(target) + if match: + self.source[line_index] = '{0}\n{1}{2}'.format( + match.group(0), + _get_indentation(target) + self.indent_word, + target[match.end(0):].lstrip()) + def fix_e711(self, result): """Fix comparison with None.""" (line_index, offset, target) = get_index_offset_contents(result, @@ -970,12 +1049,47 @@ def fix_e713(self, result): (line_index, _, target) = get_index_offset_contents(result, self.source) - # Handle very easy case only. - if re.match(r'^\s*if not [\w.]+ in [\w.]+:$', target): - self.source[line_index] = re.sub(r'if not ([\w.]+) in ([\w.]+):', - r'if \1 not in \2:', - target, - count=1) + match = COMPARE_NEGATIVE_REGEX.search(target) + if match: + if match.group(3) == 'in': + pos_start = match.start(1) + self.source[line_index] = '{0}{1} {2} {3} {4}'.format( + target[:pos_start], match.group(2), match.group(1), + match.group(3), target[match.end():]) + + def fix_e714(self, result): + """Fix object identity should be 'is not' case.""" + (line_index, _, target) = get_index_offset_contents(result, + self.source) + + match = COMPARE_NEGATIVE_REGEX.search(target) + if match: + if match.group(3) == 'is': + pos_start = match.start(1) + self.source[line_index] = '{0}{1} {2} {3} {4}'.format( + target[:pos_start], match.group(2), match.group(3), + match.group(1), target[match.end():]) + + def fix_e722(self, result): + """fix bare except""" + (line_index, _, target) = get_index_offset_contents(result, + self.source) + match = BARE_EXCEPT_REGEX.search(target) + if match: + self.source[line_index] = '{0}{1}{2}'.format( + target[:result['column'] - 1], "except BaseException:", + target[match.end():]) + + def fix_e731(self, result): + """Fix do not assign a lambda expression check.""" + (line_index, _, target) = get_index_offset_contents(result, + self.source) + match = LAMBDA_REGEX.search(target) + if match: + end = match.end() + self.source[line_index] = '{0}def {1}({2}): return {3}'.format( + target[:match.start(0)], match.group(1), match.group(2), + target[end:].lstrip()) def fix_w291(self, result): """Remove trailing whitespace.""" @@ -996,6 +1110,62 @@ def fix_w391(self, _): self.source = self.source[:original_length - blank_count] return range(1, 1 + original_length) + def fix_w503(self, result): + (line_index, _, target) = get_index_offset_contents(result, + self.source) + one_string_token = target.split()[0] + try: + ts = generate_tokens(one_string_token) + except tokenize.TokenError: + return + if not _is_binary_operator(ts[0][0], one_string_token): + return + # find comment + comment_index = None + for i in range(5): + # NOTE: try to parse code in 5 times + if (line_index - i) < 0: + break + from_index = line_index - i - 1 + to_index = line_index + 1 + try: + ts = generate_tokens("".join(self.source[from_index:to_index])) + except Exception: + continue + newline_count = 0 + newline_index = [] + for i, t in enumerate(ts): + if t[0] in (tokenize.NEWLINE, tokenize.NL): + newline_index.append(i) + newline_count += 1 + if newline_count > 2: + tts = ts[newline_index[-3]:] + else: + tts = ts + old = None + for t in tts: + if tokenize.COMMENT == t[0]: + if old is None: + comment_index = 0 + else: + comment_index = old[3][1] + break + old = t + break + i = target.index(one_string_token) + self.source[line_index] = '{0}{1}'.format( + target[:i], target[i + len(one_string_token):]) + nl = find_newline(self.source[line_index - 1:line_index]) + before_line = self.source[line_index - 1] + bl = before_line.index(nl) + if comment_index: + self.source[line_index - 1] = '{0} {1} {2}'.format( + before_line[:comment_index], one_string_token, + before_line[comment_index + 1:]) + else: + self.source[line_index - 1] = '{0} {1}{2}'.format( + before_line[:bl], one_string_token, before_line[bl:]) + def get_index_offset_contents(result, source): """Return (line_index, column_offset, line_contents).""" @@ -1017,6 +1187,7 @@ def get_fixed_long_line(target, previous_line, original, indent = _get_indentation(target) source = target[len(indent):] assert source.lstrip() == source + assert not target.lstrip().startswith('#') # Check for partial multiline. tokens = list(generate_tokens(source)) @@ -1044,11 +1215,12 @@ def get_fixed_long_line(target, previous_line, original, if candidates: best_candidate = candidates[0] + # Don't allow things to get longer. if longest_line_length(best_candidate) > longest_line_length(original): return None - else: - return best_candidate + + return best_candidate def longest_line_length(code): @@ -1144,8 +1316,8 @@ def _get_logical(source_lines, result, logical_start, logical_end): def get_item(items, index, default=None): if 0 <= index < len(items): return items[index] - else: - return default + + return default def reindent(source, indent_size): @@ -1166,7 +1338,7 @@ def code_almost_equal(a, b): if len(split_a) != len(split_b): return False - for index in range(len(split_a)): + for (index, _) in enumerate(split_a): if ''.join(split_a[index].split()) != ''.join(split_b[index].split()): return False @@ -1197,7 +1369,8 @@ def fix_e265(source, aggressive=False): # pylint: disable=unused-argument for (line_number, line) in enumerate(sio.readlines(), start=1): if ( line.lstrip().startswith('#') and - line_number not in ignored_line_numbers + line_number not in ignored_line_numbers and + not pycodestyle.noqa(line) ): indentation = _get_indentation(line) line = line.lstrip() @@ -1315,8 +1488,8 @@ def _get_indentation(line): if line.strip(): non_whitespace_index = len(line) - len(line.lstrip()) return line[:non_whitespace_index] - else: - return '' + + return '' def get_diff_text(old, new, filename): @@ -1362,7 +1535,8 @@ def _priority_key(pep8_result): lowest_priority = [ # We need to shorten lines last since the logical fixer can get in a # loop, which causes us to exit early. - 'e501' + 'e501', + 'w503' ] key = pep8_result['id'].lower() try: @@ -1478,6 +1652,11 @@ def _shorten_line(tokens, source, indentation, indent_word, yield indentation + fixed +def _is_binary_operator(token_type, text): + return ((token_type == tokenize.OP or text in ['and', 'or']) and + text not in '()[]{},:.;@=%~') + + # A convenient way to handle tokens. Token = collections.namedtuple('Token', ['token_type', 'token_string', 'spos', 'epos', 'line']) @@ -1780,17 +1959,18 @@ def _split_after_delimiter(self, item, indent_amt): return last_space = None - for item in reversed(self._lines): + for current_item in reversed(self._lines): if ( last_space and - (not isinstance(item, Atom) or not item.is_colon) + (not isinstance(current_item, Atom) or + not current_item.is_colon) ): break else: last_space = None - if isinstance(item, self._Space): - last_space = item - if isinstance(item, (self._LineBreak, self._Indent)): + if isinstance(current_item, self._Space): + last_space = current_item + if isinstance(current_item, (self._LineBreak, self._Indent)): return if not last_space: @@ -2361,8 +2541,8 @@ def _shorten_line_at_tokens(tokens, source, indentation, indent_word, if check_syntax(normalize_multiline(fixed) if aggressive > 1 else fixed): return indentation + fixed - else: - return None + + return None def token_offsets(tokens): @@ -2412,8 +2592,8 @@ def normalize_multiline(line): return line + ' pass' elif line.startswith(('if ', 'elif ', 'for ', 'while ')): return line + ' pass' - else: - return line + + return line def fix_whitespace(line, offset, replacement): @@ -2423,13 +2603,13 @@ def fix_whitespace(line, offset, replacement): right = line[offset:].lstrip('\n\r \t\\') if right.startswith('#'): return line - else: - return left + replacement + right + + return left + replacement + right def _execute_pep8(pep8_options, source): - """Execute pep8 via python method calls.""" - class QuietReport(pep8.BaseReport): + """Execute pycodestyle via python method calls.""" + class QuietReport(pycodestyle.BaseReport): """Version of checker that does not print.""" @@ -2459,8 +2639,8 @@ def full_error_results(self): """ return self.__full_error_results - checker = pep8.Checker('', lines=source, - reporter=QuietReport, **pep8_options) + checker = pycodestyle.Checker('', lines=source, reporter=QuietReport, + **pep8_options) checker.check_all() return checker.report.full_error_results() @@ -2595,9 +2775,9 @@ def getline(self): def _reindent_stats(tokens): """Return list of (lineno, indentlevel) pairs. - One for each stmt and comment line. indentlevel is -1 for comment lines, as - a signal that tokenize doesn't know what to do about them; indeed, they're - our headache! + One for each stmt and comment line. indentlevel is -1 for comment + lines, as a signal that tokenize doesn't know what to do about them; + indeed, they're our headache! """ find_stmt = 1 # Next token begins a fresh stmt? @@ -2678,7 +2858,7 @@ def check_syntax(code): def filter_results(source, results, aggressive): - """Filter out spurious reports from pep8. + """Filter out spurious reports from pycodestyle. If aggressive is True, we allow possibly unsafe fixes (E711, E712). @@ -2712,11 +2892,15 @@ def filter_results(source, results, aggressive): continue if aggressive <= 0: - if issue_id.startswith(('e711', 'w6')): + if issue_id.startswith(('e711', 'e72', 'w6')): continue if aggressive <= 1: - if issue_id.startswith(('e712', 'e713')): + if issue_id.startswith(('e712', 'e713', 'e714', 'w5')): + continue + + if aggressive <= 2: + if issue_id.startswith(('e704', 'w5')): continue if r['line'] in commented_out_code_line_numbers: @@ -2768,8 +2952,8 @@ def multiline_string_lines(source, include_docstrings=False): def commented_out_code_lines(source): """Return line numbers of comments that are likely code. - Commented-out code is bad practice, but modifying it just adds even more - clutter. + Commented-out code is bad practice, but modifying it just adds even + more clutter. """ line_numbers = [] @@ -2829,8 +3013,8 @@ def shorten_comment(line, max_line_length, last_comment=False): break_long_words=False, break_on_hyphens=False) return '\n'.join(split_lines) + '\n' - else: - return line + '\n' + + return line + '\n' def normalize_line_endings(lines, newline): @@ -2970,8 +3154,7 @@ def fix_file(filename, options=None, output=None, apply_config=False): else: return diff elif options.in_place: - fp = open_with_encoding(filename, encoding=encoding, - mode='w') + fp = open_with_encoding(filename, encoding=encoding, mode='w') fp.write(fixed_source) fp.close() else: @@ -2986,7 +3169,7 @@ def global_fixes(): """Yield multiple (code, function) tuples.""" for function in list(globals().values()): if inspect.isfunction(function): - arguments = inspect.getargspec(function)[0] + arguments = _get_parameters(function) if arguments[:1] != ['source']: continue @@ -2995,11 +3178,25 @@ def global_fixes(): yield (code, function) +def _get_parameters(function): + # pylint: disable=deprecated-method + if sys.version_info >= (3, 3): + # We need to match "getargspec()", which includes "self" as the first + # value for methods. + # https://bugs.python.org/issue17481#msg209469 + if inspect.ismethod(function): + function = function.__func__ + + return list(inspect.signature(function).parameters) + else: + return inspect.getargspec(function)[0] + + def apply_global_fixes(source, options, where='global', filename=''): """Run global fixes on source code. These are fixes that only need be done once (unlike those in - FixPEP8, which are dependent on pep8). + FixPEP8, which are dependent on pycodestyle). """ if any(code_match(code, select=options.select, ignore=options.ignore) @@ -3042,6 +3239,11 @@ def extract_code_from_function(function): return code +def _get_package_version(): + packages = ["pycodestyle: {0}".format(pycodestyle.__version__)] + return ", ".join(packages) + + def create_parser(): """Return command-line parser.""" # Do import locally to be friendly to those who use autopep8 as a library @@ -3051,7 +3253,8 @@ def create_parser(): parser = argparse.ArgumentParser(description=docstring_summary(__doc__), prog='autopep8') parser.add_argument('--version', action='version', - version='%(prog)s ' + __version__) + version='%(prog)s {0} ({1})'.format( + __version__, _get_package_version())) parser.add_argument('-v', '--verbose', action='count', default=0, help='print verbose messages; ' @@ -3104,9 +3307,7 @@ def create_parser(): 'range of line numbers (e.g. 1 99); ' 'line numbers are indexed at 1') parser.add_argument('--indent-size', default=DEFAULT_INDENT_SIZE, - type=int, metavar='n', - help='number of spaces per indent level ' - '(default %(default)s)') + type=int, help=argparse.SUPPRESS) parser.add_argument('files', nargs='*', help="files to format or '-' for standard in") @@ -3163,14 +3364,14 @@ def parse_args(arguments, apply_config=False): elif not args.select: if args.aggressive: # Enable everything by default if aggressive. - args.select = ['E', 'W'] + args.select = set(['E', 'W']) else: args.ignore = _split_comma_separated(DEFAULT_IGNORE) if args.exclude: args.exclude = _split_comma_separated(args.exclude) else: - args.exclude = [] + args.exclude = set([]) if args.jobs < 1: # Do not import multiprocessing globally in case it is not supported @@ -3214,8 +3415,24 @@ def read_config(args, parser): break (parent, tail) = os.path.split(parent) - defaults = dict((k.lstrip('-').replace('-', '_'), v) - for k, v in config.items('pep8')) + defaults = dict() + option_list = dict([(o.dest, o.type or type(o.default)) + for o in parser._actions]) + + for section in ['pep8', 'pycodestyle']: + if not config.has_section(section): + continue + for (k, _) in config.items(section): + norm_opt = k.lstrip('-').replace('-', '_') + opt_type = option_list[norm_opt] + if opt_type is int: + value = config.getint(section, k) + elif opt_type is bool: + value = config.getboolean(section, k) + else: + value = config.get(section, k) + defaults[norm_opt] = value + parser.set_defaults(**defaults) except Error: # Ignore for now. @@ -3233,8 +3450,8 @@ def decode_filename(filename): """Return Unicode filename.""" if isinstance(filename, unicode): return filename - else: - return filename.decode(sys.getfilesystemencoding()) + + return filename.decode(sys.getfilesystemencoding()) def supported_fixes(): @@ -3267,7 +3484,7 @@ def supported_fixes(): def docstring_summary(docstring): """Return summary of docstring.""" - return docstring.split('\n')[0] + return docstring.split('\n')[0] if docstring else '' def line_shortening_rank(candidate, indent_word, max_line_length, @@ -3350,6 +3567,14 @@ def line_shortening_rank(candidate, indent_word, max_line_length, ): rank += 100 + # Avoid the ugliness of "something[\n" and something[index][\n. + if ( + current_line.endswith('[') and + len(current_line) > 1 and + (current_line[-2].isalnum() or current_line[-2] in ']') + ): + rank += 300 + # Also avoid the ugliness of "foo.\nbar" if current_line.endswith('.'): rank += 100 @@ -3422,7 +3647,7 @@ def standard_deviation(numbers): def has_arithmetic_operator(line): """Return True if line contains any arithmetic operators.""" - for operator in pep8.ARITHMETIC_OP: + for operator in pycodestyle.ARITHMETIC_OP: if operator in line: return True @@ -3545,8 +3770,13 @@ def is_python_file(filename): return True try: - with open_with_encoding(filename) as f: - first_line = f.readlines(1)[0] + with open_with_encoding( + filename, + limit_byte_check=MAX_PYTHON_FILE_DETECTION_BYTES) as f: + text = f.read(MAX_PYTHON_FILE_DETECTION_BYTES) + if not text: + return False + first_line = text.splitlines()[0] except (IOError, IndexError): return False @@ -3646,6 +3876,7 @@ def generate_tokens(self, text): self.last_text = text return self.last_tokens + _cached_tokenizer = CachedTokenizer() generate_tokens = _cached_tokenizer.generate_tokens diff --git a/pymode/lint.py b/pymode/lint.py index 6f317d19..da1be109 100644 --- a/pymode/lint.py +++ b/pymode/lint.py @@ -11,7 +11,7 @@ try: from pylama.lint.pylama_pylint import Linter LINTERS['pylint'] = Linter() -except Exception: # noqa +except Exception: # noqa pass @@ -50,7 +50,7 @@ def code_check(): path = os.path.relpath(env.curbuf.name, env.curdir) env.debug("Start code check: ", path) - if getattr(options, 'skip', None) and any(p.match(path) for p in options.skip): # noqa + if getattr(options, 'skip', None) and any(p.match(path) for p in options.skip): # noqa env.message('Skip code checking.') env.debug("Skipped") return env.stop() From 7f5096fe4c7ee3b248d39db2f30dd992c8db216e Mon Sep 17 00:00:00 2001 From: Kirill Klenov Date: Mon, 3 Jul 2017 16:37:10 +0300 Subject: [PATCH 02/79] Fix virtualenv. --- pymode/virtualenv.py | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/pymode/virtualenv.py b/pymode/virtualenv.py index bf8f55fc..2d03163c 100644 --- a/pymode/virtualenv.py +++ b/pymode/virtualenv.py @@ -1,4 +1,4 @@ -""" Support virtualenv in pymode. """ +"""Support virtualenv in pymode.""" import os import sys @@ -9,7 +9,7 @@ @env.catch_exceptions def enable_virtualenv(): - """ Enable virtualenv for vim. + """Enable virtualenv for vim. :return bool: @@ -25,32 +25,14 @@ def enable_virtualenv(): env.message('Virtualenv %s already enabled.' % path) return env.stop() - activate_this = os.path.join(os.path.join(path, 'bin'), 'activate_this.py') - - # Fix for windows - if not os.path.exists(activate_this): - activate_this = os.path.join( - os.path.join(path, 'Scripts'), 'activate_this.py') - - try: - with open(activate_this) as f: - source = f.read() - exec(compile( # noqa - source, activate_this, 'exec'), dict(__file__=activate_this)) - except IOError: - _activate_env_from_path(path) - + activate_env_from_path(path) env.message('Activate virtualenv: ' + path) env.let('g:pymode_virtualenv_enabled', path) return True -def _activate_env_from_path(env_path): - """ Fix when `activate_this.py` does not exist. - - For Python 3.3 and newer, a new command-line tool `pyvenv` create venv - will not provide 'activate_this.py'. - """ +def activate_env_from_path(env_path): + """Activate given virtualenv.""" prev_sys_path = list(sys.path) if sys.platform == 'win32': From c9e357cfb4697b14c976e929c9dab39d5c7669b0 Mon Sep 17 00:00:00 2001 From: Kirill Klenov Date: Mon, 3 Jul 2017 16:39:02 +0300 Subject: [PATCH 03/79] Rope ignore more. --- pymode/libs/rope/base/default_config.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pymode/libs/rope/base/default_config.py b/pymode/libs/rope/base/default_config.py index 0bf77501..3dbd3b2f 100644 --- a/pymode/libs/rope/base/default_config.py +++ b/pymode/libs/rope/base/default_config.py @@ -14,8 +14,11 @@ def set_prefs(prefs): # '.svn': matches 'pkg/.svn' and all of its children # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' - prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', - '.hg', '.svn', '_svn', '.git', '.tox'] + prefs['ignored_resources'] = [ + '*.pyc', '*~', '.ropeproject', '.hg', '.svn', '_svn', + '.git', '.tox', '.env', 'env', 'venv', 'node_modules', + 'bower_components' + ] # Specifies which files should be considered python files. It is # useful when you have scripts inside your project. Only files From 70d6bf598d5f0f2070003bc36a9a8d2a7cce8eb0 Mon Sep 17 00:00:00 2001 From: Kirill Klenov Date: Mon, 3 Jul 2017 16:46:22 +0300 Subject: [PATCH 04/79] Update pylint. --- Makefile | 5 +- pymode/libs/astroid/__init__.py | 61 +- pymode/libs/astroid/__pkginfo__.py | 59 +- pymode/libs/astroid/arguments.py | 120 +- pymode/libs/astroid/as_string.py | 173 +- pymode/libs/astroid/astpeephole.py | 28 +- pymode/libs/astroid/bases.py | 636 +- .../astroid/brain/brain_builtin_inference.py | 230 +- .../libs/astroid/brain/brain_collections.py | 43 + pymode/libs/astroid/brain/brain_dateutil.py | 6 + pymode/libs/astroid/brain/brain_fstrings.py | 61 + pymode/libs/astroid/brain/brain_functools.py | 75 + pymode/libs/astroid/brain/brain_gi.py | 18 +- pymode/libs/astroid/brain/brain_hashlib.py | 40 + pymode/libs/astroid/brain/brain_io.py | 43 + pymode/libs/astroid/brain/brain_mechanize.py | 5 + .../astroid/brain/brain_multiprocessing.py | 104 + .../astroid/brain/brain_namedtuple_enum.py | 233 + pymode/libs/astroid/brain/brain_nose.py | 24 +- pymode/libs/astroid/brain/brain_numpy.py | 22 +- .../libs/astroid/brain/brain_pkg_resources.py | 70 + pymode/libs/astroid/brain/brain_pytest.py | 6 + pymode/libs/astroid/brain/brain_qt.py | 21 +- pymode/libs/astroid/brain/brain_re.py | 34 + pymode/libs/astroid/brain/brain_six.py | 30 +- pymode/libs/astroid/brain/brain_ssl.py | 5 + pymode/libs/astroid/brain/brain_stdlib.py | 473 - pymode/libs/astroid/brain/brain_subprocess.py | 94 + pymode/libs/astroid/brain/brain_threading.py | 26 + pymode/libs/astroid/brain/brain_typing.py | 89 + pymode/libs/astroid/builder.py | 270 +- pymode/libs/astroid/context.py | 37 +- pymode/libs/astroid/decorators.py | 116 +- pymode/libs/astroid/exceptions.py | 216 +- pymode/libs/astroid/helpers.py | 173 + pymode/libs/astroid/inference.py | 719 +- .../{tests => interpreter}/__init__.py | 0 .../_import}/__init__.py | 0 .../libs/astroid/interpreter/_import/spec.py | 287 + .../libs/astroid/interpreter/_import/util.py | 12 + .../libs/astroid/interpreter/dunder_lookup.py | 81 + .../libs/astroid/interpreter/objectmodel.py | 632 + pymode/libs/astroid/manager.py | 143 +- pymode/libs/astroid/mixins.py | 42 +- pymode/libs/astroid/modutils.py | 322 +- pymode/libs/astroid/node_classes.py | 1365 +- pymode/libs/astroid/nodes.py | 32 +- pymode/libs/astroid/objects.py | 206 +- pymode/libs/astroid/protocols.py | 490 +- pymode/libs/astroid/raw_building.py | 212 +- pymode/libs/astroid/rebuilder.py | 1219 +- pymode/libs/astroid/scoped_nodes.py | 888 +- pymode/libs/astroid/test_utils.py | 208 +- pymode/libs/astroid/tests/resources.py | 72 - .../python2/data/MyPyPa-0.1.0-py2.5.egg | Bin 1222 -> 0 bytes .../python2/data/MyPyPa-0.1.0-py2.5.zip | Bin 1222 -> 0 bytes .../testdata/python2/data/SSL1/Connection1.py | 14 - .../testdata/python2/data/SSL1/__init__.py | 1 - .../tests/testdata/python2/data/__init__.py | 1 - .../testdata/python2/data/absimp/__init__.py | 5 - .../data/absimp/sidepackage/__init__.py | 3 - .../testdata/python2/data/absimp/string.py | 3 - .../tests/testdata/python2/data/absimport.py | 3 - .../tests/testdata/python2/data/all.py | 9 - .../testdata/python2/data/appl/__init__.py | 3 - .../python2/data/appl/myConnection.py | 12 - .../python2/data/clientmodule_test.py | 32 - .../testdata/python2/data/descriptor_crash.py | 11 - .../tests/testdata/python2/data/email.py | 1 - .../testdata/python2/data/find_test/module.py | 0 .../python2/data/find_test/module2.py | 0 .../python2/data/find_test/noendingnewline.py | 0 .../python2/data/find_test/nonregr.py | 0 .../tests/testdata/python2/data/format.py | 34 - .../testdata/python2/data/joined_strings.py | 1051 -- .../testdata/python2/data/lmfp/__init__.py | 2 - .../tests/testdata/python2/data/lmfp/foo.py | 6 - .../tests/testdata/python2/data/module.py | 89 - .../python2/data/module1abs/__init__.py | 4 - .../testdata/python2/data/module1abs/core.py | 1 - .../tests/testdata/python2/data/module2.py | 143 - .../testdata/python2/data/noendingnewline.py | 36 - .../tests/testdata/python2/data/nonregr.py | 57 - .../tests/testdata/python2/data/notall.py | 7 - .../testdata/python2/data/package/__init__.py | 4 - .../python2/data/package/absimport.py | 6 - .../testdata/python2/data/package/hello.py | 2 - .../import_package_subpackage_module.py | 49 - .../data/package/subpackage/__init__.py | 1 - .../python2/data/package/subpackage/module.py | 1 - .../tests/testdata/python2/data/recursion.py | 3 - .../python2/data/suppliermodule_test.py | 13 - .../python2/data/unicode_package/__init__.py | 1 - .../data/unicode_package/core/__init__.py | 0 .../python3/data/MyPyPa-0.1.0-py2.5.egg | Bin 1222 -> 0 bytes .../python3/data/MyPyPa-0.1.0-py2.5.zip | Bin 1222 -> 0 bytes .../testdata/python3/data/SSL1/Connection1.py | 14 - .../testdata/python3/data/SSL1/__init__.py | 1 - .../tests/testdata/python3/data/__init__.py | 1 - .../testdata/python3/data/absimp/__init__.py | 5 - .../data/absimp/sidepackage/__init__.py | 3 - .../testdata/python3/data/absimp/string.py | 3 - .../tests/testdata/python3/data/absimport.py | 3 - .../tests/testdata/python3/data/all.py | 9 - .../testdata/python3/data/appl/__init__.py | 3 - .../python3/data/appl/myConnection.py | 11 - .../python3/data/clientmodule_test.py | 32 - .../testdata/python3/data/descriptor_crash.py | 11 - .../tests/testdata/python3/data/email.py | 1 - .../python3/data/find_test/__init__.py | 0 .../testdata/python3/data/find_test/module.py | 0 .../python3/data/find_test/module2.py | 0 .../python3/data/find_test/noendingnewline.py | 0 .../python3/data/find_test/nonregr.py | 0 .../tests/testdata/python3/data/format.py | 34 - .../testdata/python3/data/joined_strings.py | 1051 -- .../testdata/python3/data/lmfp/__init__.py | 2 - .../tests/testdata/python3/data/lmfp/foo.py | 6 - .../tests/testdata/python3/data/module.py | 88 - .../python3/data/module1abs/__init__.py | 4 - .../testdata/python3/data/module1abs/core.py | 1 - .../tests/testdata/python3/data/module2.py | 143 - .../testdata/python3/data/noendingnewline.py | 36 - .../tests/testdata/python3/data/nonregr.py | 57 - .../tests/testdata/python3/data/notall.py | 8 - .../testdata/python3/data/package/__init__.py | 4 - .../python3/data/package/absimport.py | 6 - .../testdata/python3/data/package/hello.py | 2 - .../import_package_subpackage_module.py | 49 - .../data/package/subpackage/__init__.py | 1 - .../python3/data/package/subpackage/module.py | 1 - .../tests/testdata/python3/data/recursion.py | 3 - .../python3/data/suppliermodule_test.py | 13 - .../python3/data/unicode_package/__init__.py | 1 - .../data/unicode_package/core/__init__.py | 0 pymode/libs/astroid/tests/unittest_brain.py | 506 - pymode/libs/astroid/tests/unittest_builder.py | 774 - .../libs/astroid/tests/unittest_inference.py | 2130 --- pymode/libs/astroid/tests/unittest_lookup.py | 352 - pymode/libs/astroid/tests/unittest_manager.py | 216 - .../libs/astroid/tests/unittest_modutils.py | 269 - pymode/libs/astroid/tests/unittest_nodes.py | 764 - pymode/libs/astroid/tests/unittest_objects.py | 530 - .../libs/astroid/tests/unittest_peephole.py | 121 - .../libs/astroid/tests/unittest_protocols.py | 176 - pymode/libs/astroid/tests/unittest_python3.py | 254 - .../astroid/tests/unittest_raw_building.py | 85 - .../libs/astroid/tests/unittest_regrtest.py | 364 - .../astroid/tests/unittest_scoped_nodes.py | 1583 -- .../libs/astroid/tests/unittest_transforms.py | 245 - pymode/libs/astroid/tests/unittest_utils.py | 124 - pymode/libs/astroid/transforms.py | 26 +- pymode/libs/astroid/util.py | 145 +- pymode/libs/isort/__init__.py | 2 +- pymode/libs/isort/__main__.py | 3 + pymode/libs/isort/isort.py | 279 +- pymode/libs/isort/main.py | 51 +- pymode/libs/isort/natural.py | 2 +- pymode/libs/isort/pie_slice.py | 68 +- pymode/libs/isort/settings.py | 113 +- pymode/libs/lazy_object_proxy/__init__.py | 2 +- pymode/libs/lazy_object_proxy/cext.c | 2 +- pymode/libs/lazy_object_proxy/cext.so | Bin 36084 -> 0 bytes pymode/libs/pyflakes/test/__init__.py | 0 pymode/libs/pyflakes/test/harness.py | 72 - pymode/libs/pyflakes/test/test_api.py | 744 - pymode/libs/pyflakes/test/test_dict.py | 217 - pymode/libs/pyflakes/test/test_doctests.py | 442 - pymode/libs/pyflakes/test/test_imports.py | 1180 -- pymode/libs/pyflakes/test/test_other.py | 1871 --- ..._return_with_arguments_inside_generator.py | 34 - .../pyflakes/test/test_undefined_names.py | 806 - pymode/libs/pylint/__init__.py | 11 +- pymode/libs/pylint/__main__.py | 3 +- pymode/libs/pylint/__pkginfo__.py | 40 +- pymode/libs/pylint/checkers/__init__.py | 11 +- pymode/libs/pylint/checkers/async.py | 9 +- pymode/libs/pylint/checkers/base.py | 765 +- pymode/libs/pylint/checkers/classes.py | 378 +- .../libs/pylint/checkers/design_analysis.py | 36 +- pymode/libs/pylint/checkers/exceptions.py | 251 +- pymode/libs/pylint/checkers/format.py | 142 +- pymode/libs/pylint/checkers/imports.py | 193 +- pymode/libs/pylint/checkers/logging.py | 57 +- pymode/libs/pylint/checkers/misc.py | 11 +- pymode/libs/pylint/checkers/newstyle.py | 52 +- pymode/libs/pylint/checkers/python3.py | 309 +- pymode/libs/pylint/checkers/raw_metrics.py | 13 +- pymode/libs/pylint/checkers/refactoring.py | 715 + pymode/libs/pylint/checkers/similar.py | 5 +- pymode/libs/pylint/checkers/spelling.py | 78 +- pymode/libs/pylint/checkers/stdlib.py | 11 +- pymode/libs/pylint/checkers/strings.py | 41 +- pymode/libs/pylint/checkers/typecheck.py | 473 +- pymode/libs/pylint/checkers/utils.py | 234 +- pymode/libs/pylint/checkers/variables.py | 388 +- pymode/libs/pylint/config.py | 66 +- pymode/libs/pylint/epylint.py | 26 +- pymode/libs/pylint/exceptions.py | 15 + .../pylint/extensions/_check_docs_utils.py | 230 +- pymode/libs/pylint/extensions/bad_builtin.py | 4 +- pymode/libs/pylint/extensions/check_docs.py | 6 +- pymode/libs/pylint/extensions/check_elif.py | 6 +- .../libs/pylint/extensions/comparetozero.py | 71 + pymode/libs/pylint/extensions/docparams.py | 200 +- pymode/libs/pylint/extensions/docstyle.py | 11 +- pymode/libs/pylint/extensions/emptystring.py | 71 + pymode/libs/pylint/extensions/mccabe.py | 8 +- .../extensions/overlapping_exceptions.py | 81 + .../extensions/redefined_variable_type.py | 104 + pymode/libs/pylint/graph.py | 5 +- pymode/libs/pylint/gui.py | 521 - pymode/libs/pylint/interfaces.py | 7 +- pymode/libs/pylint/lint.py | 142 +- pymode/libs/pylint/pyreverse/__init__.py | 3 +- pymode/libs/pylint/pyreverse/diadefslib.py | 6 +- pymode/libs/pylint/pyreverse/diagrams.py | 5 +- pymode/libs/pylint/pyreverse/inspector.py | 4 +- pymode/libs/pylint/pyreverse/main.py | 14 +- pymode/libs/pylint/pyreverse/utils.py | 5 +- pymode/libs/pylint/pyreverse/vcgutils.py | 5 +- pymode/libs/pylint/pyreverse/writer.py | 5 +- pymode/libs/pylint/reporters/__init__.py | 15 +- pymode/libs/pylint/reporters/guireporter.py | 30 - pymode/libs/pylint/reporters/html.py | 102 - pymode/libs/pylint/reporters/json.py | 24 +- pymode/libs/pylint/reporters/text.py | 16 +- .../pylint/reporters/ureports/__init__.py | 4 +- .../pylint/reporters/ureports/html_writer.py | 81 - .../libs/pylint/reporters/ureports/nodes.py | 17 +- .../pylint/reporters/ureports/text_writer.py | 11 +- pymode/libs/pylint/test/data/__init__.py | 0 pymode/libs/pylint/test/data/ascript | 2 - .../libs/pylint/test/data/classes_No_Name.dot | 12 - .../pylint/test/data/clientmodule_test.py | 29 - .../pylint/test/data/packages_No_Name.dot | 8 - .../pylint/test/data/suppliermodule_test.py | 10 - .../libs/pylint/test/extensions/__init__.py | 0 .../test/extensions/data/bad_builtin.py | 4 - .../pylint/test/extensions/data/docstring.py | 48 - .../libs/pylint/test/extensions/data/elif.py | 26 - .../pylint/test/extensions/data/mccabe.py | 205 - .../test/extensions/test_bad_builtin.py | 53 - .../pylint/test/extensions/test_check_docs.py | 1174 -- .../test/extensions/test_check_docs_utils.py | 142 - .../test/extensions/test_check_mccabe.py | 72 - .../test/extensions/test_check_raise_docs.py | 391 - .../test/extensions/test_check_return_docs.py | 473 - .../pylint/test/extensions/test_docstyle.py | 67 - .../test/extensions/test_elseif_used.py | 50 - .../libs/pylint/test/functional/__init__.py | 0 .../test/functional/abstract_abc_methods.py | 17 - .../abstract_class_instantiated_in_class.py | 20 - .../abstract_class_instantiated_py2.py | 82 - .../abstract_class_instantiated_py2.rc | 2 - .../abstract_class_instantiated_py2.txt | 4 - .../abstract_class_instantiated_py3.py | 111 - .../abstract_class_instantiated_py3.rc | 2 - .../abstract_class_instantiated_py3.txt | 4 - .../abstract_class_instantiated_py34.py | 19 - .../abstract_class_instantiated_py34.rc | 2 - .../abstract_class_instantiated_py34.txt | 1 - .../test/functional/abstract_method_py2.py | 90 - .../test/functional/abstract_method_py2.rc | 2 - .../test/functional/abstract_method_py2.txt | 16 - .../test/functional/abstract_method_py3.py | 88 - .../test/functional/abstract_method_py3.rc | 2 - .../test/functional/abstract_method_py3.txt | 16 - .../access_member_before_definition.py | 40 - .../access_member_before_definition.txt | 2 - .../test/functional/access_to__name__.py | 21 - .../test/functional/access_to__name__.txt | 3 - .../functional/access_to_protected_members.py | 44 - .../access_to_protected_members.txt | 5 - .../anomalous_unicode_escape_py2.py | 20 - .../anomalous_unicode_escape_py2.rc | 2 - .../anomalous_unicode_escape_py2.txt | 3 - .../anomalous_unicode_escape_py3.py | 19 - .../anomalous_unicode_escape_py3.rc | 2 - .../anomalous_unicode_escape_py3.txt | 3 - .../libs/pylint/test/functional/arguments.py | 167 - .../libs/pylint/test/functional/arguments.txt | 26 - .../test/functional/arguments_differ.py | 138 - .../test/functional/arguments_differ.txt | 3 - .../pylint/test/functional/assert_on_tuple.py | 11 - .../test/functional/assert_on_tuple.txt | 2 - .../test/functional/assigning_non_slot.py | 133 - .../test/functional/assigning_non_slot.txt | 4 - .../pylint/test/functional/async_functions.py | 64 - .../pylint/test/functional/async_functions.rc | 2 - .../test/functional/async_functions.txt | 10 - .../attribute_defined_outside_init.py | 62 - .../attribute_defined_outside_init.txt | 2 - .../test/functional/bad_continuation.py | 191 - .../test/functional/bad_continuation.txt | 63 - .../test/functional/bad_exception_context.py | 24 - .../test/functional/bad_exception_context.rc | 2 - .../test/functional/bad_exception_context.txt | 3 - .../pylint/test/functional/bad_indentation.py | 19 - .../test/functional/bad_indentation.txt | 2 - .../test/functional/bad_inline_option.py | 5 - .../test/functional/bad_inline_option.rc | 2 - .../test/functional/bad_inline_option.txt | 1 - .../pylint/test/functional/bad_open_mode.py | 37 - .../pylint/test/functional/bad_open_mode.rc | 2 - .../pylint/test/functional/bad_open_mode.txt | 14 - .../test/functional/bad_open_mode_py3.py | 23 - .../test/functional/bad_open_mode_py3.rc | 2 - .../test/functional/bad_open_mode_py3.txt | 6 - .../test/functional/bad_reversed_sequence.py | 71 - .../test/functional/bad_reversed_sequence.txt | 8 - .../functional/bad_staticmethod_argument.py | 16 - .../functional/bad_staticmethod_argument.txt | 2 - .../pylint/test/functional/bad_whitespace.py | 3 - .../pylint/test/functional/bad_whitespace.txt | 7 - .../pylint/test/functional/bare_except.py | 6 - .../pylint/test/functional/bare_except.txt | 1 - .../test/functional/blacklisted_name.py | 4 - .../test/functional/blacklisted_name.txt | 1 - .../test/functional/boolean_datetime.py | 30 - .../test/functional/boolean_datetime.rc | 2 - .../test/functional/boolean_datetime.txt | 8 - .../test/functional/cellvar_escaping_loop.py | 130 - .../test/functional/cellvar_escaping_loop.txt | 8 - .../test/functional/class_members_py27.py | 65 - .../test/functional/class_members_py27.rc | 3 - .../test/functional/class_members_py27.txt | 6 - .../test/functional/class_members_py30.py | 63 - .../test/functional/class_members_py30.rc | 2 - .../test/functional/class_members_py30.txt | 7 - .../pylint/test/functional/class_scope.py | 22 - .../pylint/test/functional/class_scope.txt | 4 - .../test/functional/confidence_filter.py | 15 - .../test/functional/confidence_filter.rc | 3 - .../test/functional/confidence_filter.txt | 1 - .../functional/confusing_with_statement.py | 27 - .../functional/confusing_with_statement.txt | 1 - .../consider_iterating_dictionary.py | 28 - .../consider_iterating_dictionary.txt | 5 - .../functional/consider_using_enumerate.py | 43 - .../functional/consider_using_enumerate.txt | 1 - .../test/functional/continue_in_finally.py | 24 - .../test/functional/continue_in_finally.txt | 1 - .../functional/crash_missing_module_type.py | 18 - .../functional/crash_missing_module_type.txt | 0 .../pylint/test/functional/ctor_arguments.py | 104 - .../pylint/test/functional/ctor_arguments.txt | 24 - .../functional/dangerous_default_value.py | 79 - .../functional/dangerous_default_value.rc | 2 - .../functional/dangerous_default_value.txt | 14 - .../dangerous_default_value_py30.py | 79 - .../dangerous_default_value_py30.rc | 2 - .../dangerous_default_value_py30.txt | 14 - .../defined_and_used_on_same_line.py | 29 - .../test/functional/deprecated_lambda.py | 23 - .../test/functional/deprecated_lambda.rc | 2 - .../test/functional/deprecated_lambda.txt | 2 - .../test/functional/deprecated_methods_py2.py | 9 - .../test/functional/deprecated_methods_py2.rc | 2 - .../functional/deprecated_methods_py2.txt | 4 - .../test/functional/deprecated_methods_py3.py | 37 - .../test/functional/deprecated_methods_py3.rc | 2 - .../functional/deprecated_methods_py3.txt | 12 - .../test/functional/deprecated_module_py2.py | 8 - .../test/functional/deprecated_module_py2.rc | 3 - .../test/functional/deprecated_module_py2.txt | 4 - .../test/functional/deprecated_module_py3.py | 4 - .../test/functional/deprecated_module_py3.rc | 2 - .../test/functional/deprecated_module_py3.txt | 1 - .../test/functional/deprecated_module_py4.py | 4 - .../test/functional/deprecated_module_py4.rc | 4 - .../test/functional/deprecated_module_py4.txt | 2 - .../deprecated_module_uninstalled.py | 5 - .../deprecated_module_uninstalled.rc | 2 - .../deprecated_module_uninstalled.txt | 2 - .../libs/pylint/test/functional/docstrings.py | 83 - .../pylint/test/functional/docstrings.txt | 8 - .../functional/duplicate_argument_name.py | 11 - .../functional/duplicate_argument_name.txt | 3 - .../pylint/test/functional/duplicate_bases.py | 15 - .../test/functional/duplicate_bases.txt | 1 - .../functional/duplicate_dict_literal_key.py | 14 - .../functional/duplicate_dict_literal_key.txt | 1 - .../test/functional/duplicate_except.py | 12 - .../test/functional/duplicate_except.txt | 1 - .../libs/pylint/test/functional/eval_used.py | 10 - .../libs/pylint/test/functional/eval_used.txt | 4 - .../test/functional/exception_is_binary_op.py | 12 - .../functional/exception_is_binary_op.txt | 4 - .../pylint/test/functional/exec_used_py2.py | 10 - .../pylint/test/functional/exec_used_py2.rc | 2 - .../pylint/test/functional/exec_used_py2.txt | 4 - .../pylint/test/functional/exec_used_py3.py | 9 - .../pylint/test/functional/exec_used_py3.rc | 2 - .../pylint/test/functional/exec_used_py3.txt | 4 - .../functional/fallback_import_disabled.py | 10 - .../functional/fallback_import_disabled.txt | 0 .../functional/fallback_import_enabled.py | 5 - .../functional/fallback_import_enabled.rc | 2 - .../functional/fallback_import_enabled.txt | 2 - pymode/libs/pylint/test/functional/fixme.py | 18 - pymode/libs/pylint/test/functional/fixme.txt | 5 - .../pylint/test/functional/formatting.txt | 0 .../test/functional/function_redefined.py | 74 - .../test/functional/function_redefined.txt | 5 - .../pylint/test/functional/future_import.py | 3 - .../functional/future_unicode_literals.py | 6 - .../functional/future_unicode_literals.rc | 2 - .../functional/future_unicode_literals.txt | 1 - .../test/functional/generated_members.py | 13 - .../test/functional/generated_members.rc | 5 - .../test/functional/genexpr_variable_scope.py | 5 - .../functional/genexpr_variable_scope.txt | 1 - pymode/libs/pylint/test/functional/globals.py | 25 - .../libs/pylint/test/functional/globals.txt | 6 - .../pylint/test/functional/import_error.py | 27 - .../pylint/test/functional/import_error.txt | 3 - .../test/functional/inconsistent_mro.py | 9 - .../test/functional/inconsistent_mro.txt | 1 - .../test/functional/indexing_exception.py | 15 - .../test/functional/indexing_exception.rc | 5 - .../test/functional/indexing_exception.txt | 3 - .../test/functional/inherit_non_class.py | 81 - .../test/functional/inherit_non_class.txt | 9 - .../test/functional/init_is_generator.py | 5 - .../test/functional/init_is_generator.txt | 1 - .../pylint/test/functional/init_not_called.py | 64 - .../test/functional/init_not_called.txt | 6 - .../test/functional/invalid_all_object.py | 6 - .../test/functional/invalid_all_object.txt | 3 - .../functional/invalid_exceptions_caught.py | 123 - .../functional/invalid_exceptions_caught.txt | 12 - .../functional/invalid_exceptions_raised.py | 83 - .../functional/invalid_exceptions_raised.txt | 12 - .../functional/invalid_length_returned.py | 58 - .../functional/invalid_length_returned.txt | 3 - .../pylint/test/functional/invalid_name.py | 31 - .../pylint/test/functional/invalid_name.txt | 3 - .../test/functional/invalid_sequence_index.py | 224 - .../functional/invalid_sequence_index.txt | 20 - .../test/functional/invalid_slice_index.py | 60 - .../test/functional/invalid_slice_index.txt | 5 - .../invalid_star_assignment_target.py | 4 - .../invalid_star_assignment_target.rc | 2 - .../invalid_star_assignment_target.txt | 1 - .../functional/invalid_unary_operand_type.py | 51 - .../functional/invalid_unary_operand_type.rc | 2 - .../functional/invalid_unary_operand_type.txt | 14 - .../test/functional/iterable_context.py | 179 - .../test/functional/iterable_context.txt | 10 - .../test/functional/iterable_context_py2.py | 18 - .../test/functional/iterable_context_py2.rc | 3 - .../test/functional/iterable_context_py2.txt | 1 - .../test/functional/iterable_context_py3.py | 18 - .../test/functional/iterable_context_py3.rc | 3 - .../test/functional/iterable_context_py3.txt | 1 - .../pylint/test/functional/line_endings.py | 3 - .../pylint/test/functional/line_endings.rc | 2 - .../pylint/test/functional/line_endings.txt | 2 - .../pylint/test/functional/line_too_long.py | 26 - .../pylint/test/functional/line_too_long.txt | 4 - .../logging_format_interpolation.py | 25 - .../logging_format_interpolation.txt | 4 - .../test/functional/logging_not_lazy.py | 17 - .../test/functional/logging_not_lazy.txt | 3 - .../test/functional/long_lines_with_utf8.py | 7 - .../test/functional/long_lines_with_utf8.txt | 1 - .../pylint/test/functional/mapping_context.py | 97 - .../test/functional/mapping_context.txt | 2 - .../test/functional/mapping_context_py2.py | 19 - .../test/functional/mapping_context_py2.rc | 3 - .../test/functional/mapping_context_py2.txt | 1 - .../test/functional/mapping_context_py3.py | 19 - .../test/functional/mapping_context_py3.rc | 3 - .../test/functional/mapping_context_py3.txt | 1 - .../pylint/test/functional/member_checks.py | 171 - .../pylint/test/functional/member_checks.txt | 15 - .../test/functional/membership_protocol.py | 123 - .../test/functional/membership_protocol.txt | 7 - .../functional/membership_protocol_py2.py | 36 - .../functional/membership_protocol_py2.rc | 3 - .../functional/membership_protocol_py2.txt | 3 - .../functional/membership_protocol_py3.py | 36 - .../functional/membership_protocol_py3.rc | 3 - .../functional/membership_protocol_py3.txt | 3 - .../pylint/test/functional/method_hidden.py | 16 - .../pylint/test/functional/method_hidden.txt | 1 - .../test/functional/misplaced_bare_raise.py | 75 - .../test/functional/misplaced_bare_raise.txt | 7 - .../misplaced_comparison_constant.py | 36 - .../misplaced_comparison_constant.txt | 6 - .../test/functional/misplaced_future.py | 6 - .../test/functional/misplaced_future.txt | 1 - .../test/functional/missing_docstring.py | 54 - .../test/functional/missing_docstring.txt | 3 - .../test/functional/missing_final_newline.py | 4 - .../test/functional/missing_final_newline.txt | 1 - .../test/functional/missing_self_argument.py | 20 - .../test/functional/missing_self_argument.txt | 6 - .../test/functional/mixed_indentation.py | 10 - .../test/functional/mixed_indentation.txt | 2 - .../test/functional/multiple_imports.py | 2 - .../test/functional/multiple_imports.txt | 1 - .../pylint/test/functional/name_styles.py | 119 - .../pylint/test/functional/name_styles.rc | 5 - .../pylint/test/functional/name_styles.txt | 17 - .../functional/namedtuple_member_inference.py | 22 - .../namedtuple_member_inference.txt | 2 - .../pylint/test/functional/names_in__all__.py | 49 - .../test/functional/names_in__all__.txt | 6 - .../test/functional/newstyle__slots__.py | 17 - .../test/functional/newstyle__slots__.txt | 2 - .../test/functional/newstyle_properties.py | 53 - .../test/functional/newstyle_properties.txt | 2 - .../functional/no_classmethod_decorator.py | 35 - .../functional/no_classmethod_decorator.txt | 3 - .../test/functional/no_name_in_module.py | 66 - .../test/functional/no_name_in_module.txt | 16 - .../pylint/test/functional/no_self_use.py | 78 - .../pylint/test/functional/no_self_use.txt | 1 - .../pylint/test/functional/no_self_use_py3.py | 12 - .../pylint/test/functional/no_self_use_py3.rc | 2 - .../test/functional/no_self_use_py3.txt | 1 - .../functional/no_staticmethod_decorator.py | 35 - .../functional/no_staticmethod_decorator.txt | 3 - .../test/functional/non_iterator_returned.py | 95 - .../test/functional/non_iterator_returned.txt | 4 - .../test/functional/nonexistent_operator.py | 15 - .../test/functional/nonexistent_operator.txt | 6 - .../test/functional/nonlocal_and_global.py | 12 - .../test/functional/nonlocal_and_global.rc | 2 - .../test/functional/nonlocal_and_global.txt | 1 - .../functional/nonlocal_without_binding.py | 28 - .../functional/nonlocal_without_binding.rc | 2 - .../functional/nonlocal_without_binding.txt | 3 - .../functional/not_async_context_manager.py | 71 - .../functional/not_async_context_manager.rc | 2 - .../functional/not_async_context_manager.txt | 5 - .../pylint/test/functional/not_callable.py | 112 - .../pylint/test/functional/not_callable.txt | 8 - .../test/functional/not_context_manager.py | 135 - .../test/functional/not_context_manager.txt | 5 - .../pylint/test/functional/not_in_loop.py | 54 - .../pylint/test/functional/not_in_loop.txt | 8 - .../test/functional/old_division_manually.py | 2 - .../test/functional/old_division_manually.rc | 6 - .../test/functional/old_style_class_py27.py | 18 - .../test/functional/old_style_class_py27.rc | 2 - .../test/functional/old_style_class_py27.txt | 2 - .../test/functional/pygtk_enum_crash.py | 10 - .../test/functional/pygtk_enum_crash.rc | 2 - .../pylint/test/functional/pygtk_import.py | 14 - .../pylint/test/functional/pygtk_import.rc | 2 - .../functional/raising_non_exception_py3.py | 13 - .../functional/raising_non_exception_py3.rc | 2 - .../functional/raising_non_exception_py3.txt | 1 - .../test/functional/redefined_builtin.py | 10 - .../test/functional/redefined_builtin.txt | 2 - .../functional/redefined_variable_type.py | 54 - .../functional/redefined_variable_type.txt | 6 - .../functional/redundant_unittest_assert.py | 38 - .../functional/redundant_unittest_assert.txt | 6 - .../regression_no_value_for_parameter.py | 15 - .../regression_no_value_for_parameter.txt | 0 .../libs/pylint/test/functional/reimported.py | 16 - .../pylint/test/functional/reimported.txt | 4 - .../test/functional/repeated_keyword.py | 13 - .../test/functional/repeated_keyword.txt | 1 - .../pylint/test/functional/return_in_init.py | 25 - .../pylint/test/functional/return_in_init.txt | 1 - .../functional/return_outside_function.py | 2 - .../functional/return_outside_function.txt | 1 - .../functional/simplifiable_if_statement.py | 120 - .../functional/simplifiable_if_statement.txt | 4 - .../test/functional/singleton_comparison.py | 11 - .../test/functional/singleton_comparison.txt | 5 - .../pylint/test/functional/slots_checks.py | 61 - .../pylint/test/functional/slots_checks.txt | 4 - .../test/functional/socketerror_import.py | 6 - .../star_needs_assignment_target.py | 4 - .../star_needs_assignment_target.rc | 2 - .../star_needs_assignment_target.txt | 1 - .../star_needs_assignment_target_py35.py | 15 - .../star_needs_assignment_target_py35.rc | 2 - .../star_needs_assignment_target_py35.txt | 1 - .../functional/statement_without_effect.py | 65 - .../functional/statement_without_effect.txt | 60 - .../test/functional/string_formatting.py | 182 - .../test/functional/string_formatting.txt | 40 - .../functional/string_formatting_disable.py | 1 - .../functional/string_formatting_disable.rc | 3 - .../functional/string_formatting_disable.txt | 1 - .../string_formatting_failed_inference.py | 4 - .../test/functional/string_formatting_py27.py | 22 - .../test/functional/string_formatting_py27.rc | 3 - .../functional/string_formatting_py27.txt | 15 - .../pylint/test/functional/super_checks.py | 114 - .../pylint/test/functional/super_checks.txt | 19 - .../test/functional/superfluous_parens.py | 19 - .../test/functional/superfluous_parens.txt | 5 - .../functional/suspicious_str_strip_call.py | 9 - .../functional/suspicious_str_strip_call.rc | 2 - .../functional/suspicious_str_strip_call.txt | 3 - .../suspicious_str_strip_call_py3.py | 9 - .../suspicious_str_strip_call_py3.rc | 2 - .../suspicious_str_strip_call_py3.txt | 3 - .../pylint/test/functional/syntax_error.py | 1 - .../pylint/test/functional/syntax_error.rc | 2 - .../pylint/test/functional/syntax_error.txt | 1 - .../test/functional/syntax_error_jython.py | 1 - .../test/functional/syntax_error_jython.rc | 2 - .../test/functional/syntax_error_jython.txt | 1 - .../pylint/test/functional/tokenize_error.py | 6 - .../pylint/test/functional/tokenize_error.rc | 2 - .../pylint/test/functional/tokenize_error.txt | 1 - .../test/functional/tokenize_error_jython.py | 7 - .../test/functional/tokenize_error_jython.rc | 2 - .../test/functional/tokenize_error_jython.txt | 1 - .../test/functional/too_few_public_methods.py | 28 - .../functional/too_few_public_methods.txt | 1 - .../test/functional/too_many_ancestors.py | 24 - .../test/functional/too_many_ancestors.txt | 2 - .../test/functional/too_many_arguments.py | 4 - .../test/functional/too_many_arguments.txt | 1 - .../too_many_boolean_expressions.py | 20 - .../too_many_boolean_expressions.txt | 4 - .../test/functional/too_many_branches.py | 69 - .../test/functional/too_many_branches.txt | 1 - .../too_many_instance_attributes.py | 26 - .../too_many_instance_attributes.txt | 1 - .../pylint/test/functional/too_many_lines.py | 1015 -- .../pylint/test/functional/too_many_lines.txt | 1 - .../functional/too_many_lines_disabled.py | 1018 -- .../pylint/test/functional/too_many_locals.py | 60 - .../test/functional/too_many_locals.txt | 3 - .../test/functional/too_many_nested_blocks.py | 95 - .../functional/too_many_nested_blocks.txt | 2 - .../functional/too_many_public_methods.py | 79 - .../functional/too_many_public_methods.txt | 1 - .../functional/too_many_return_statements.py | 24 - .../functional/too_many_return_statements.txt | 1 - .../functional/too_many_star_expressions.py | 4 - .../functional/too_many_star_expressions.rc | 2 - .../functional/too_many_star_expressions.txt | 1 - .../test/functional/too_many_statements.py | 60 - .../test/functional/too_many_statements.txt | 1 - .../test/functional/trailing_newlines.py | 3 - .../test/functional/trailing_newlines.txt | 1 - .../test/functional/trailing_whitespaces.py | 11 - .../test/functional/trailing_whitespaces.txt | 3 - .../functional/unbalanced_tuple_unpacking.py | 108 - .../functional/unbalanced_tuple_unpacking.txt | 6 - .../unbalanced_tuple_unpacking_py30.py | 11 - .../unbalanced_tuple_unpacking_py30.rc | 2 - .../test/functional/undefined_variable.py | 177 - .../test/functional/undefined_variable.txt | 24 - .../functional/undefined_variable_py30.py | 78 - .../functional/undefined_variable_py30.rc | 2 - .../functional/undefined_variable_py30.txt | 8 - .../unexpected_special_method_signature.py | 120 - .../unexpected_special_method_signature.txt | 16 - .../test/functional/ungrouped_imports.py | 20 - .../test/functional/ungrouped_imports.txt | 5 - .../test/functional/unidiomatic_typecheck.py | 76 - .../test/functional/unidiomatic_typecheck.txt | 18 - .../test/functional/uninferable_all_object.py | 9 - .../test/functional/unnecessary_lambda.py | 51 - .../test/functional/unnecessary_lambda.txt | 7 - .../test/functional/unnecessary_pass.py | 7 - .../test/functional/unnecessary_pass.txt | 1 - .../pylint/test/functional/unneeded_not.py | 63 - .../pylint/test/functional/unneeded_not.txt | 14 - .../test/functional/unpacked_exceptions.py | 11 - .../test/functional/unpacked_exceptions.rc | 5 - .../test/functional/unpacked_exceptions.txt | 4 - .../libs/pylint/test/functional/unpacking.py | 11 - .../functional/unpacking_generalizations.py | 29 - .../functional/unpacking_generalizations.rc | 2 - .../functional/unpacking_generalizations.txt | 6 - .../test/functional/unpacking_non_sequence.py | 119 - .../functional/unpacking_non_sequence.txt | 10 - .../pylint/test/functional/unreachable.py | 22 - .../pylint/test/functional/unreachable.txt | 4 - .../functional/unrecognized_inline_option.py | 3 - .../functional/unrecognized_inline_option.txt | 1 - .../test/functional/unsubscriptable_value.py | 115 - .../test/functional/unsubscriptable_value.txt | 14 - .../functional/unsubscriptable_value_35.py | 5 - .../functional/unsubscriptable_value_35.rc | 2 - .../unsupported_binary_operation.py | 59 - .../unsupported_binary_operation.rc | 2 - .../unsupported_binary_operation.txt | 21 - .../pylint/test/functional/unused_import.py | 18 - .../pylint/test/functional/unused_import.txt | 8 - .../pylint/test/functional/unused_variable.py | 16 - .../test/functional/unused_variable.txt | 5 - .../used_before_assignment_nonlocal.py | 47 - .../used_before_assignment_nonlocal.rc | 2 - .../used_before_assignment_nonlocal.txt | 6 - .../test/functional/useless_else_on_loop.py | 55 - .../test/functional/useless_else_on_loop.txt | 5 - .../test/functional/using_constant_test.py | 140 - .../test/functional/using_constant_test.txt | 22 - .../pylint/test/functional/wildcard_import.py | 5 - .../test/functional/wildcard_import.txt | 2 - .../functional/with_used_before_assign.py | 11 - .../functional/with_used_before_assign.txt | 2 - .../test/functional/with_using_generator.py | 14 - .../test/functional/with_using_generator.txt | 1 - .../test/functional/wrong_import_order.py | 41 - .../test/functional/wrong_import_order.txt | 5 - .../test/functional/wrong_import_order2.py | 16 - .../test/functional/wrong_import_position.py | 33 - .../test/functional/wrong_import_position.txt | 4 - .../functional/wrong_import_position10.py | 17 - .../functional/wrong_import_position11.py | 4 - .../functional/wrong_import_position11.txt | 1 - .../functional/wrong_import_position12.py | 5 - .../functional/wrong_import_position12.txt | 1 - .../functional/wrong_import_position13.py | 4 - .../functional/wrong_import_position13.txt | 1 - .../functional/wrong_import_position14.py | 5 - .../functional/wrong_import_position14.txt | 1 - .../functional/wrong_import_position15.py | 9 - .../test/functional/wrong_import_position2.py | 10 - .../test/functional/wrong_import_position3.py | 3 - .../test/functional/wrong_import_position4.py | 5 - .../test/functional/wrong_import_position5.py | 4 - .../test/functional/wrong_import_position6.py | 7 - .../test/functional/wrong_import_position7.py | 9 - .../test/functional/wrong_import_position8.py | 4 - .../test/functional/wrong_import_position9.py | 9 - .../functional/yield_from_iterable_py33.py | 7 - .../functional/yield_from_iterable_py33.rc | 2 - .../functional/yield_from_iterable_py33.txt | 1 - .../functional/yield_from_outside_func.py | 4 - .../functional/yield_from_outside_func.rc | 2 - .../functional/yield_from_outside_func.txt | 1 - .../functional/yield_inside_async_function.py | 12 - .../functional/yield_inside_async_function.rc | 2 - .../yield_inside_async_function.txt | 2 - .../test/functional/yield_outside_func.py | 4 - .../test/functional/yield_outside_func.txt | 1 - pymode/libs/pylint/test/input/__init__.py | 1 - .../test/input/func_3k_removed_stuff_py_30.py | 13 - .../func_bad_assigment_to_exception_var.py | 30 - .../test/input/func_bad_cont_dictcomp_py27.py | 38 - .../test/input/func_block_disable_msg.py | 1026 -- .../func_break_or_return_in_try_finally.py | 44 - .../libs/pylint/test/input/func_bug113231.py | 24 - .../test/input/func_disable_linebased.py | 14 - .../pylint/test/input/func_dotted_ancestor.py | 11 - pymode/libs/pylint/test/input/func_e0012.py | 4 - pymode/libs/pylint/test/input/func_e0203.py | 19 - pymode/libs/pylint/test/input/func_e0204.py | 19 - pymode/libs/pylint/test/input/func_e0601.py | 9 - pymode/libs/pylint/test/input/func_e0604.py | 13 - pymode/libs/pylint/test/input/func_e12xx.py | 28 - pymode/libs/pylint/test/input/func_e13xx.py | 21 - .../pylint/test/input/func_excess_escapes.py | 30 - .../libs/pylint/test/input/func_first_arg.py | 42 - pymode/libs/pylint/test/input/func_i0011.py | 4 - pymode/libs/pylint/test/input/func_i0012.py | 4 - pymode/libs/pylint/test/input/func_i0013.py | 8 - pymode/libs/pylint/test/input/func_i0014.py | 8 - pymode/libs/pylint/test/input/func_i0020.py | 8 - pymode/libs/pylint/test/input/func_i0022.py | 22 - .../libs/pylint/test/input/func_init_vars.py | 45 - .../libs/pylint/test/input/func_kwoa_py30.py | 12 - .../func_logging_not_lazy_with_logger.py | 13 - .../input/func_loopvar_in_dict_comp_py27.py | 8 - .../pylint/test/input/func_module___dict__.py | 9 - .../func_nameerror_on_string_substitution.py | 8 - .../test/input/func_no_dummy_redefined.py | 14 - ...ror___init___return_from_inner_function.py | 12 - ...r_access_attr_before_def_false_positive.py | 98 - .../test/input/func_noerror_base_init_vars.py | 35 - .../input/func_noerror_builtin_module_test.py | 11 - .../input/func_noerror_class_attributes.py | 17 - ...oerror_classes_meth_could_be_a_function.py | 33 - ...noerror_classes_protected_member_access.py | 26 - .../test/input/func_noerror_crash_127416.py | 20 - .../input/func_noerror_decorator_scope.py | 19 - ...noerror_e1101_9588_base_attr_aug_assign.py | 38 - .../test/input/func_noerror_encoding.py | 5 - .../test/input/func_noerror_except_pass.py | 12 - .../test/input/func_noerror_exception.py | 7 - ...func_noerror_external_classmethod_crash.py | 21 - .../input/func_noerror_function_as_method.py | 18 - .../func_noerror_genexp_in_class_scope.py | 9 - .../test/input/func_noerror_inner_classes.py | 33 - .../func_noerror_lambda_use_before_assign.py | 8 - .../test/input/func_noerror_long_utf8_line.py | 8 - .../input/func_noerror_mcs_attr_access.py | 20 - .../func_noerror_new_style_class_py_30.py | 45 - .../func_noerror_no_warning_docstring.py | 42 - .../pylint/test/input/func_noerror_nonregr.py | 13 - .../func_noerror_object_as_class_attribute.py | 18 - .../input/func_noerror_overloaded_operator.py | 21 - .../func_noerror_overriden_method_varargs.py | 19 - .../func_noerror_property_affectation_py26.py | 24 - .../input/func_noerror_raise_return_self.py | 14 - .../test/input/func_noerror_static_method.py | 28 - .../input/func_noerror_yield_assign_py25.py | 21 - .../input/func_noerror_yield_return_mix.py | 7 - .../input/func_nonregr___file___global.py | 8 - .../test/input/func_return_yield_mix_py_33.py | 15 - .../input/func_too_many_returns_yields.py | 42 - .../func_typecheck_callfunc_assigment.py | 63 - .../test/input/func_unused_import_py30.py | 20 - .../input/func_unused_overridden_argument.py | 31 - .../input/func_use_for_or_listcomp_var.py | 27 - ...riables_unused_name_from_wilcard_import.py | 3 - .../pylint/test/input/func_w0122_py_30.py | 12 - pymode/libs/pylint/test/input/func_w0205.py | 24 - pymode/libs/pylint/test/input/func_w0233.py | 50 - .../pylint/test/input/func_w0332_py_30.py | 4 - pymode/libs/pylint/test/input/func_w0401.py | 9 - .../test/input/func_w0401_package/__init__.py | 2 - .../func_w0401_package/all_the_things.py | 9 - .../test/input/func_w0401_package/thing1.py | 3 - .../test/input/func_w0401_package/thing2.py | 7 - pymode/libs/pylint/test/input/func_w0404.py | 27 - pymode/libs/pylint/test/input/func_w0405.py | 31 - pymode/libs/pylint/test/input/func_w0406.py | 10 - pymode/libs/pylint/test/input/func_w0611.py | 25 - pymode/libs/pylint/test/input/func_w0612.py | 37 - pymode/libs/pylint/test/input/func_w0613.py | 42 - .../libs/pylint/test/input/func_w0623_py30.py | 16 - .../pylint/test/input/func_w0623_py_30.py | 67 - pymode/libs/pylint/test/input/func_w0631.py | 20 - pymode/libs/pylint/test/input/func_w0703.py | 9 - pymode/libs/pylint/test/input/func_w0705.py | 46 - pymode/libs/pylint/test/input/func_w0801.py | 11 - .../test/input/func_with_without_as_py25.py | 12 - .../input/ignore_except_pass_by_default.py | 6 - pymode/libs/pylint/test/input/noext | 4 - pymode/libs/pylint/test/input/similar1 | 22 - pymode/libs/pylint/test/input/similar2 | 22 - pymode/libs/pylint/test/input/syntax_error.py | 2 - pymode/libs/pylint/test/input/w0401_cycle.py | 9 - pymode/libs/pylint/test/input/w0801_same.py | 11 - .../pylint/test/messages/builtin_module.txt | 1 - .../messages/func_3k_removed_stuff_py_30.txt | 2 - .../func_bad_assigment_to_exception_var.txt | 5 - .../messages/func_bad_cont_dictcomp_py27.txt | 6 - .../test/messages/func_block_disable_msg.txt | 13 - .../func_break_or_return_in_try_finally.txt | 3 - .../pylint/test/messages/func_bug113231.txt | 2 - .../test/messages/func_disable_linebased.txt | 2 - .../messages/func_disable_linebased_py30.txt | 2 - .../test/messages/func_dotted_ancestor.txt | 1 - .../libs/pylint/test/messages/func_e0012.txt | 1 - .../libs/pylint/test/messages/func_e0203.txt | 2 - .../libs/pylint/test/messages/func_e0204.txt | 3 - .../libs/pylint/test/messages/func_e0601.txt | 1 - .../libs/pylint/test/messages/func_e0604.txt | 1 - .../libs/pylint/test/messages/func_e12xx.txt | 6 - .../libs/pylint/test/messages/func_e13xx.txt | 13 - .../pylint/test/messages/func_e13xx_py30.txt | 11 - .../test/messages/func_excess_escapes.txt | 9 - .../pylint/test/messages/func_first_arg.txt | 9 - .../libs/pylint/test/messages/func_i0011.txt | 2 - .../libs/pylint/test/messages/func_i0012.txt | 1 - .../libs/pylint/test/messages/func_i0013.txt | 1 - .../libs/pylint/test/messages/func_i0014.txt | 2 - .../libs/pylint/test/messages/func_i0020.txt | 2 - .../libs/pylint/test/messages/func_i0022.txt | 21 - .../pylint/test/messages/func_init_vars.txt | 1 - .../pylint/test/messages/func_kwoa_py30.txt | 5 - .../func_logging_not_lazy_with_logger.txt | 4 - .../func_loopvar_in_dict_comp_py27.txt | 1 - .../test/messages/func_module___dict__.txt | 1 - .../func_nameerror_on_string_substitution.txt | 2 - .../test/messages/func_no_dummy_redefined.txt | 2 - .../messages/func_nonregr___file___global.txt | 2 - .../pylint/test/messages/func_raw_escapes.txt | 3 - .../messages/func_return_yield_mix_py_33.txt | 2 - .../messages/func_too_many_returns_yields.txt | 1 - .../test/messages/func_toolonglines_py30.txt | 4 - .../func_typecheck_callfunc_assigment.txt | 3 - .../messages/func_typecheck_getattr_py30.txt | 9 - .../func_typecheck_non_callable_call.txt | 8 - .../messages/func_unicode_literal_py26.txt | 0 .../messages/func_unicode_literal_py274.txt | 1 - .../test/messages/func_unused_import_py30.txt | 1 - .../func_unused_overridden_argument.txt | 1 - .../func_use_for_or_listcomp_var_py29.txt | 3 - .../func_use_for_or_listcomp_var_py30.txt | 3 - ...iables_unused_name_from_wilcard_import.txt | 4 - .../pylint/test/messages/func_w0122_py_30.txt | 5 - .../libs/pylint/test/messages/func_w0205.txt | 2 - .../libs/pylint/test/messages/func_w0233.txt | 6 - .../libs/pylint/test/messages/func_w0312.txt | 2 - .../pylint/test/messages/func_w0332_py_30.txt | 1 - .../libs/pylint/test/messages/func_w0401.txt | 3 - .../test/messages/func_w0401_package.txt | 1 - .../libs/pylint/test/messages/func_w0404.txt | 5 - .../libs/pylint/test/messages/func_w0405.txt | 4 - .../libs/pylint/test/messages/func_w0406.txt | 1 - .../libs/pylint/test/messages/func_w0611.txt | 1 - .../libs/pylint/test/messages/func_w0612.txt | 5 - .../libs/pylint/test/messages/func_w0613.txt | 5 - .../libs/pylint/test/messages/func_w0622.txt | 2 - .../libs/pylint/test/messages/func_w0623.txt | 11 - .../pylint/test/messages/func_w0623_py30.txt | 2 - .../pylint/test/messages/func_w0623_py_30.txt | 12 - .../libs/pylint/test/messages/func_w0631.txt | 1 - .../libs/pylint/test/messages/func_w0703.txt | 1 - .../libs/pylint/test/messages/func_w0705.txt | 11 - .../libs/pylint/test/messages/func_w0801.txt | 11 - .../messages/func_with_without_as_py25.txt | 3 - .../libs/pylint/test/regrtest_data/.pylintrc | 4 - .../test/regrtest_data/absimp/__init__.py | 4 - .../test/regrtest_data/absimp/string.py | 7 - .../test/regrtest_data/application_crash.py | 12 - .../regrtest_data/bad_package/__init__.py | 2 - .../test/regrtest_data/bad_package/wrong.py | 5 - .../test/regrtest_data/classdoc_usage.py | 16 - .../test/regrtest_data/decimal_inference.py | 10 - .../test/regrtest_data/descriptor_crash.py | 20 - .../test/regrtest_data/dummy/__init__.py | 3 - .../test/regrtest_data/dummy/another.py | 3 - .../pylint/test/regrtest_data/dummy/dummy.py | 2 - .../test/regrtest_data/html_crash_420.py | 5 - pymode/libs/pylint/test/regrtest_data/huge.py | 12600 ---------------- .../test/regrtest_data/import_assign.py | 5 - .../import_package_subpackage_module.py | 49 - .../test/regrtest_data/import_something.py | 4 - pymode/libs/pylint/test/regrtest_data/meta.py | 3 - .../test/regrtest_data/module_global.py | 7 - .../test/regrtest_data/no_stdout_encoding.py | 4 - .../test/regrtest_data/numarray_import.py | 7 - .../pylint/test/regrtest_data/numarray_inf.py | 5 - .../test/regrtest_data/package/AudioTime.py | 3 - .../test/regrtest_data/package/__init__.py | 14 - .../package/subpackage/__init__.py | 1 - .../package/subpackage/module.py | 1 - .../regrtest_data/package_all/__init__.py | 3 - .../regrtest_data/package_all/notmissing.py | 2 - .../test/regrtest_data/precedence_test.py | 21 - .../test/regrtest_data/py3k_error_flag.py | 11 - .../special_attr_scope_lookup_crash.py | 3 - .../pylint/test/regrtest_data/syntax_error.py | 1 - .../try_finally_disable_msg_crash.py | 5 - .../regrtest_data/wrong_import_position.py | 11 - pymode/libs/pylint/test/test_func.py | 75 - pymode/libs/pylint/test/test_functional.py | 374 - pymode/libs/pylint/test/test_import_graph.py | 73 - pymode/libs/pylint/test/test_regr.py | 148 - pymode/libs/pylint/test/test_self.py | 356 - .../libs/pylint/test/unittest_checker_base.py | 319 - .../pylint/test/unittest_checker_classes.py | 89 - .../test/unittest_checker_exceptions.py | 59 - .../pylint/test/unittest_checker_format.py | 251 - .../pylint/test/unittest_checker_imports.py | 80 - .../pylint/test/unittest_checker_logging.py | 51 - .../libs/pylint/test/unittest_checker_misc.py | 40 - .../pylint/test/unittest_checker_python3.py | 433 - .../pylint/test/unittest_checker_similar.py | 147 - .../pylint/test/unittest_checker_spelling.py | 84 - .../pylint/test/unittest_checker_stdlib.py | 54 - .../pylint/test/unittest_checker_strings.py | 30 - .../pylint/test/unittest_checker_typecheck.py | 116 - .../pylint/test/unittest_checker_variables.py | 148 - .../pylint/test/unittest_checkers_utils.py | 92 - pymode/libs/pylint/test/unittest_config.py | 53 - pymode/libs/pylint/test/unittest_lint.py | 684 - .../pylint/test/unittest_pyreverse_diadefs.py | 161 - .../test/unittest_pyreverse_inspector.py | 126 - .../pylint/test/unittest_pyreverse_writer.py | 124 - .../pylint/test/unittest_reporters_json.py | 53 - pymode/libs/pylint/test/unittest_reporting.py | 182 - pymode/libs/pylint/test/unittest_utils.py | 98 - pymode/libs/pylint/testutils.py | 128 +- pymode/libs/pylint/utils.py | 435 +- pymode/libs/wrapt/__init__.py | 2 +- pymode/libs/wrapt/_wrappers.so | Bin 47640 -> 0 bytes pymode/libs/wrapt/arguments.py | 5 +- pymode/libs/wrapt/decorators.py | 6 +- pymode/libs/wrapt/importer.py | 2 +- pymode/libs/wrapt/wrappers.py | 38 +- 982 files changed, 11623 insertions(+), 58790 deletions(-) create mode 100644 pymode/libs/astroid/brain/brain_collections.py create mode 100644 pymode/libs/astroid/brain/brain_fstrings.py create mode 100644 pymode/libs/astroid/brain/brain_functools.py create mode 100644 pymode/libs/astroid/brain/brain_hashlib.py create mode 100644 pymode/libs/astroid/brain/brain_io.py create mode 100644 pymode/libs/astroid/brain/brain_multiprocessing.py create mode 100644 pymode/libs/astroid/brain/brain_namedtuple_enum.py create mode 100644 pymode/libs/astroid/brain/brain_pkg_resources.py create mode 100644 pymode/libs/astroid/brain/brain_re.py delete mode 100644 pymode/libs/astroid/brain/brain_stdlib.py create mode 100644 pymode/libs/astroid/brain/brain_subprocess.py create mode 100644 pymode/libs/astroid/brain/brain_threading.py create mode 100644 pymode/libs/astroid/brain/brain_typing.py create mode 100644 pymode/libs/astroid/helpers.py rename pymode/libs/astroid/{tests => interpreter}/__init__.py (100%) rename pymode/libs/astroid/{tests/testdata/python2/data/find_test => interpreter/_import}/__init__.py (100%) create mode 100644 pymode/libs/astroid/interpreter/_import/spec.py create mode 100644 pymode/libs/astroid/interpreter/_import/util.py create mode 100644 pymode/libs/astroid/interpreter/dunder_lookup.py create mode 100644 pymode/libs/astroid/interpreter/objectmodel.py delete mode 100644 pymode/libs/astroid/tests/resources.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/SSL1/Connection1.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/SSL1/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/absimp/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/absimp/string.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/absimport.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/all.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/appl/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/appl/myConnection.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/clientmodule_test.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/descriptor_crash.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/email.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/find_test/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/find_test/module2.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/find_test/noendingnewline.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/find_test/nonregr.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/format.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/joined_strings.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/lmfp/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/lmfp/foo.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/module1abs/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/module1abs/core.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/module2.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/nonregr.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/notall.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/hello.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/recursion.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/SSL1/Connection1.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/SSL1/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/absimp/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/absimp/string.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/absimport.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/all.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/appl/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/appl/myConnection.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/clientmodule_test.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/descriptor_crash.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/email.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/find_test/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/find_test/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/find_test/module2.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/find_test/noendingnewline.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/find_test/nonregr.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/format.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/joined_strings.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/lmfp/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/lmfp/foo.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/module1abs/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/module1abs/core.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/module2.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/nonregr.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/notall.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/hello.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/recursion.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py delete mode 100644 pymode/libs/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py delete mode 100644 pymode/libs/astroid/tests/unittest_brain.py delete mode 100644 pymode/libs/astroid/tests/unittest_builder.py delete mode 100644 pymode/libs/astroid/tests/unittest_inference.py delete mode 100644 pymode/libs/astroid/tests/unittest_lookup.py delete mode 100644 pymode/libs/astroid/tests/unittest_manager.py delete mode 100644 pymode/libs/astroid/tests/unittest_modutils.py delete mode 100644 pymode/libs/astroid/tests/unittest_nodes.py delete mode 100644 pymode/libs/astroid/tests/unittest_objects.py delete mode 100644 pymode/libs/astroid/tests/unittest_peephole.py delete mode 100644 pymode/libs/astroid/tests/unittest_protocols.py delete mode 100644 pymode/libs/astroid/tests/unittest_python3.py delete mode 100644 pymode/libs/astroid/tests/unittest_raw_building.py delete mode 100644 pymode/libs/astroid/tests/unittest_regrtest.py delete mode 100644 pymode/libs/astroid/tests/unittest_scoped_nodes.py delete mode 100644 pymode/libs/astroid/tests/unittest_transforms.py delete mode 100644 pymode/libs/astroid/tests/unittest_utils.py create mode 100644 pymode/libs/isort/__main__.py delete mode 100755 pymode/libs/lazy_object_proxy/cext.so delete mode 100644 pymode/libs/pyflakes/test/__init__.py delete mode 100644 pymode/libs/pyflakes/test/harness.py delete mode 100644 pymode/libs/pyflakes/test/test_api.py delete mode 100644 pymode/libs/pyflakes/test/test_dict.py delete mode 100644 pymode/libs/pyflakes/test/test_doctests.py delete mode 100644 pymode/libs/pyflakes/test/test_imports.py delete mode 100644 pymode/libs/pyflakes/test/test_other.py delete mode 100644 pymode/libs/pyflakes/test/test_return_with_arguments_inside_generator.py delete mode 100644 pymode/libs/pyflakes/test/test_undefined_names.py create mode 100644 pymode/libs/pylint/checkers/refactoring.py create mode 100644 pymode/libs/pylint/exceptions.py create mode 100644 pymode/libs/pylint/extensions/comparetozero.py create mode 100644 pymode/libs/pylint/extensions/emptystring.py create mode 100644 pymode/libs/pylint/extensions/overlapping_exceptions.py create mode 100644 pymode/libs/pylint/extensions/redefined_variable_type.py delete mode 100644 pymode/libs/pylint/gui.py delete mode 100644 pymode/libs/pylint/reporters/guireporter.py delete mode 100644 pymode/libs/pylint/reporters/html.py delete mode 100644 pymode/libs/pylint/reporters/ureports/html_writer.py delete mode 100644 pymode/libs/pylint/test/data/__init__.py delete mode 100644 pymode/libs/pylint/test/data/ascript delete mode 100644 pymode/libs/pylint/test/data/classes_No_Name.dot delete mode 100644 pymode/libs/pylint/test/data/clientmodule_test.py delete mode 100644 pymode/libs/pylint/test/data/packages_No_Name.dot delete mode 100644 pymode/libs/pylint/test/data/suppliermodule_test.py delete mode 100644 pymode/libs/pylint/test/extensions/__init__.py delete mode 100644 pymode/libs/pylint/test/extensions/data/bad_builtin.py delete mode 100644 pymode/libs/pylint/test/extensions/data/docstring.py delete mode 100644 pymode/libs/pylint/test/extensions/data/elif.py delete mode 100644 pymode/libs/pylint/test/extensions/data/mccabe.py delete mode 100644 pymode/libs/pylint/test/extensions/test_bad_builtin.py delete mode 100644 pymode/libs/pylint/test/extensions/test_check_docs.py delete mode 100644 pymode/libs/pylint/test/extensions/test_check_docs_utils.py delete mode 100644 pymode/libs/pylint/test/extensions/test_check_mccabe.py delete mode 100644 pymode/libs/pylint/test/extensions/test_check_raise_docs.py delete mode 100644 pymode/libs/pylint/test/extensions/test_check_return_docs.py delete mode 100644 pymode/libs/pylint/test/extensions/test_docstyle.py delete mode 100644 pymode/libs/pylint/test/extensions/test_elseif_used.py delete mode 100644 pymode/libs/pylint/test/functional/__init__.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_abc_methods.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_in_class.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.rc delete mode 100644 pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.txt delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py2.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py3.py delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/abstract_method_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/access_member_before_definition.py delete mode 100644 pymode/libs/pylint/test/functional/access_member_before_definition.txt delete mode 100644 pymode/libs/pylint/test/functional/access_to__name__.py delete mode 100644 pymode/libs/pylint/test/functional/access_to__name__.txt delete mode 100644 pymode/libs/pylint/test/functional/access_to_protected_members.py delete mode 100644 pymode/libs/pylint/test/functional/access_to_protected_members.txt delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.py delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.py delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/arguments.py delete mode 100644 pymode/libs/pylint/test/functional/arguments.txt delete mode 100644 pymode/libs/pylint/test/functional/arguments_differ.py delete mode 100644 pymode/libs/pylint/test/functional/arguments_differ.txt delete mode 100644 pymode/libs/pylint/test/functional/assert_on_tuple.py delete mode 100644 pymode/libs/pylint/test/functional/assert_on_tuple.txt delete mode 100644 pymode/libs/pylint/test/functional/assigning_non_slot.py delete mode 100644 pymode/libs/pylint/test/functional/assigning_non_slot.txt delete mode 100644 pymode/libs/pylint/test/functional/async_functions.py delete mode 100644 pymode/libs/pylint/test/functional/async_functions.rc delete mode 100644 pymode/libs/pylint/test/functional/async_functions.txt delete mode 100644 pymode/libs/pylint/test/functional/attribute_defined_outside_init.py delete mode 100644 pymode/libs/pylint/test/functional/attribute_defined_outside_init.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_continuation.py delete mode 100644 pymode/libs/pylint/test/functional/bad_continuation.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_exception_context.py delete mode 100644 pymode/libs/pylint/test/functional/bad_exception_context.rc delete mode 100644 pymode/libs/pylint/test/functional/bad_exception_context.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_indentation.py delete mode 100644 pymode/libs/pylint/test/functional/bad_indentation.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_inline_option.py delete mode 100644 pymode/libs/pylint/test/functional/bad_inline_option.rc delete mode 100644 pymode/libs/pylint/test/functional/bad_inline_option.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode.py delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode.rc delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode_py3.py delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/bad_open_mode_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_reversed_sequence.py delete mode 100644 pymode/libs/pylint/test/functional/bad_reversed_sequence.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_staticmethod_argument.py delete mode 100644 pymode/libs/pylint/test/functional/bad_staticmethod_argument.txt delete mode 100644 pymode/libs/pylint/test/functional/bad_whitespace.py delete mode 100644 pymode/libs/pylint/test/functional/bad_whitespace.txt delete mode 100644 pymode/libs/pylint/test/functional/bare_except.py delete mode 100644 pymode/libs/pylint/test/functional/bare_except.txt delete mode 100644 pymode/libs/pylint/test/functional/blacklisted_name.py delete mode 100644 pymode/libs/pylint/test/functional/blacklisted_name.txt delete mode 100644 pymode/libs/pylint/test/functional/boolean_datetime.py delete mode 100644 pymode/libs/pylint/test/functional/boolean_datetime.rc delete mode 100644 pymode/libs/pylint/test/functional/boolean_datetime.txt delete mode 100644 pymode/libs/pylint/test/functional/cellvar_escaping_loop.py delete mode 100644 pymode/libs/pylint/test/functional/cellvar_escaping_loop.txt delete mode 100644 pymode/libs/pylint/test/functional/class_members_py27.py delete mode 100644 pymode/libs/pylint/test/functional/class_members_py27.rc delete mode 100644 pymode/libs/pylint/test/functional/class_members_py27.txt delete mode 100644 pymode/libs/pylint/test/functional/class_members_py30.py delete mode 100644 pymode/libs/pylint/test/functional/class_members_py30.rc delete mode 100644 pymode/libs/pylint/test/functional/class_members_py30.txt delete mode 100644 pymode/libs/pylint/test/functional/class_scope.py delete mode 100644 pymode/libs/pylint/test/functional/class_scope.txt delete mode 100644 pymode/libs/pylint/test/functional/confidence_filter.py delete mode 100644 pymode/libs/pylint/test/functional/confidence_filter.rc delete mode 100644 pymode/libs/pylint/test/functional/confidence_filter.txt delete mode 100644 pymode/libs/pylint/test/functional/confusing_with_statement.py delete mode 100644 pymode/libs/pylint/test/functional/confusing_with_statement.txt delete mode 100644 pymode/libs/pylint/test/functional/consider_iterating_dictionary.py delete mode 100644 pymode/libs/pylint/test/functional/consider_iterating_dictionary.txt delete mode 100644 pymode/libs/pylint/test/functional/consider_using_enumerate.py delete mode 100644 pymode/libs/pylint/test/functional/consider_using_enumerate.txt delete mode 100644 pymode/libs/pylint/test/functional/continue_in_finally.py delete mode 100644 pymode/libs/pylint/test/functional/continue_in_finally.txt delete mode 100644 pymode/libs/pylint/test/functional/crash_missing_module_type.py delete mode 100644 pymode/libs/pylint/test/functional/crash_missing_module_type.txt delete mode 100644 pymode/libs/pylint/test/functional/ctor_arguments.py delete mode 100644 pymode/libs/pylint/test/functional/ctor_arguments.txt delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value.py delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value.rc delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value.txt delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value_py30.py delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value_py30.rc delete mode 100644 pymode/libs/pylint/test/functional/dangerous_default_value_py30.txt delete mode 100644 pymode/libs/pylint/test/functional/defined_and_used_on_same_line.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_lambda.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_lambda.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_lambda.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py2.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py3.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_methods_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py2.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py3.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py4.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py4.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_py4.txt delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_uninstalled.py delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_uninstalled.rc delete mode 100644 pymode/libs/pylint/test/functional/deprecated_module_uninstalled.txt delete mode 100644 pymode/libs/pylint/test/functional/docstrings.py delete mode 100644 pymode/libs/pylint/test/functional/docstrings.txt delete mode 100644 pymode/libs/pylint/test/functional/duplicate_argument_name.py delete mode 100644 pymode/libs/pylint/test/functional/duplicate_argument_name.txt delete mode 100644 pymode/libs/pylint/test/functional/duplicate_bases.py delete mode 100644 pymode/libs/pylint/test/functional/duplicate_bases.txt delete mode 100644 pymode/libs/pylint/test/functional/duplicate_dict_literal_key.py delete mode 100644 pymode/libs/pylint/test/functional/duplicate_dict_literal_key.txt delete mode 100644 pymode/libs/pylint/test/functional/duplicate_except.py delete mode 100644 pymode/libs/pylint/test/functional/duplicate_except.txt delete mode 100644 pymode/libs/pylint/test/functional/eval_used.py delete mode 100644 pymode/libs/pylint/test/functional/eval_used.txt delete mode 100644 pymode/libs/pylint/test/functional/exception_is_binary_op.py delete mode 100644 pymode/libs/pylint/test/functional/exception_is_binary_op.txt delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py2.py delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py3.py delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/exec_used_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/fallback_import_disabled.py delete mode 100644 pymode/libs/pylint/test/functional/fallback_import_disabled.txt delete mode 100644 pymode/libs/pylint/test/functional/fallback_import_enabled.py delete mode 100644 pymode/libs/pylint/test/functional/fallback_import_enabled.rc delete mode 100644 pymode/libs/pylint/test/functional/fallback_import_enabled.txt delete mode 100644 pymode/libs/pylint/test/functional/fixme.py delete mode 100644 pymode/libs/pylint/test/functional/fixme.txt delete mode 100644 pymode/libs/pylint/test/functional/formatting.txt delete mode 100644 pymode/libs/pylint/test/functional/function_redefined.py delete mode 100644 pymode/libs/pylint/test/functional/function_redefined.txt delete mode 100644 pymode/libs/pylint/test/functional/future_import.py delete mode 100644 pymode/libs/pylint/test/functional/future_unicode_literals.py delete mode 100644 pymode/libs/pylint/test/functional/future_unicode_literals.rc delete mode 100644 pymode/libs/pylint/test/functional/future_unicode_literals.txt delete mode 100644 pymode/libs/pylint/test/functional/generated_members.py delete mode 100644 pymode/libs/pylint/test/functional/generated_members.rc delete mode 100644 pymode/libs/pylint/test/functional/genexpr_variable_scope.py delete mode 100644 pymode/libs/pylint/test/functional/genexpr_variable_scope.txt delete mode 100644 pymode/libs/pylint/test/functional/globals.py delete mode 100644 pymode/libs/pylint/test/functional/globals.txt delete mode 100644 pymode/libs/pylint/test/functional/import_error.py delete mode 100644 pymode/libs/pylint/test/functional/import_error.txt delete mode 100644 pymode/libs/pylint/test/functional/inconsistent_mro.py delete mode 100644 pymode/libs/pylint/test/functional/inconsistent_mro.txt delete mode 100644 pymode/libs/pylint/test/functional/indexing_exception.py delete mode 100644 pymode/libs/pylint/test/functional/indexing_exception.rc delete mode 100644 pymode/libs/pylint/test/functional/indexing_exception.txt delete mode 100644 pymode/libs/pylint/test/functional/inherit_non_class.py delete mode 100644 pymode/libs/pylint/test/functional/inherit_non_class.txt delete mode 100644 pymode/libs/pylint/test/functional/init_is_generator.py delete mode 100644 pymode/libs/pylint/test/functional/init_is_generator.txt delete mode 100644 pymode/libs/pylint/test/functional/init_not_called.py delete mode 100644 pymode/libs/pylint/test/functional/init_not_called.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_all_object.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_all_object.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_exceptions_caught.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_exceptions_caught.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_exceptions_raised.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_exceptions_raised.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_length_returned.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_length_returned.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_name.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_name.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_sequence_index.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_sequence_index.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_slice_index.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_slice_index.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_star_assignment_target.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_star_assignment_target.rc delete mode 100644 pymode/libs/pylint/test/functional/invalid_star_assignment_target.txt delete mode 100644 pymode/libs/pylint/test/functional/invalid_unary_operand_type.py delete mode 100644 pymode/libs/pylint/test/functional/invalid_unary_operand_type.rc delete mode 100644 pymode/libs/pylint/test/functional/invalid_unary_operand_type.txt delete mode 100644 pymode/libs/pylint/test/functional/iterable_context.py delete mode 100644 pymode/libs/pylint/test/functional/iterable_context.txt delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py2.py delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py3.py delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/iterable_context_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/line_endings.py delete mode 100644 pymode/libs/pylint/test/functional/line_endings.rc delete mode 100644 pymode/libs/pylint/test/functional/line_endings.txt delete mode 100644 pymode/libs/pylint/test/functional/line_too_long.py delete mode 100644 pymode/libs/pylint/test/functional/line_too_long.txt delete mode 100644 pymode/libs/pylint/test/functional/logging_format_interpolation.py delete mode 100644 pymode/libs/pylint/test/functional/logging_format_interpolation.txt delete mode 100644 pymode/libs/pylint/test/functional/logging_not_lazy.py delete mode 100644 pymode/libs/pylint/test/functional/logging_not_lazy.txt delete mode 100644 pymode/libs/pylint/test/functional/long_lines_with_utf8.py delete mode 100644 pymode/libs/pylint/test/functional/long_lines_with_utf8.txt delete mode 100644 pymode/libs/pylint/test/functional/mapping_context.py delete mode 100644 pymode/libs/pylint/test/functional/mapping_context.txt delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py2.py delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py3.py delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/mapping_context_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/member_checks.py delete mode 100644 pymode/libs/pylint/test/functional/member_checks.txt delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol.py delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol.txt delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py2.py delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py2.rc delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py2.txt delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py3.py delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/membership_protocol_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/method_hidden.py delete mode 100644 pymode/libs/pylint/test/functional/method_hidden.txt delete mode 100644 pymode/libs/pylint/test/functional/misplaced_bare_raise.py delete mode 100644 pymode/libs/pylint/test/functional/misplaced_bare_raise.txt delete mode 100644 pymode/libs/pylint/test/functional/misplaced_comparison_constant.py delete mode 100644 pymode/libs/pylint/test/functional/misplaced_comparison_constant.txt delete mode 100644 pymode/libs/pylint/test/functional/misplaced_future.py delete mode 100644 pymode/libs/pylint/test/functional/misplaced_future.txt delete mode 100644 pymode/libs/pylint/test/functional/missing_docstring.py delete mode 100644 pymode/libs/pylint/test/functional/missing_docstring.txt delete mode 100644 pymode/libs/pylint/test/functional/missing_final_newline.py delete mode 100644 pymode/libs/pylint/test/functional/missing_final_newline.txt delete mode 100644 pymode/libs/pylint/test/functional/missing_self_argument.py delete mode 100644 pymode/libs/pylint/test/functional/missing_self_argument.txt delete mode 100644 pymode/libs/pylint/test/functional/mixed_indentation.py delete mode 100644 pymode/libs/pylint/test/functional/mixed_indentation.txt delete mode 100644 pymode/libs/pylint/test/functional/multiple_imports.py delete mode 100644 pymode/libs/pylint/test/functional/multiple_imports.txt delete mode 100644 pymode/libs/pylint/test/functional/name_styles.py delete mode 100644 pymode/libs/pylint/test/functional/name_styles.rc delete mode 100644 pymode/libs/pylint/test/functional/name_styles.txt delete mode 100644 pymode/libs/pylint/test/functional/namedtuple_member_inference.py delete mode 100644 pymode/libs/pylint/test/functional/namedtuple_member_inference.txt delete mode 100644 pymode/libs/pylint/test/functional/names_in__all__.py delete mode 100644 pymode/libs/pylint/test/functional/names_in__all__.txt delete mode 100644 pymode/libs/pylint/test/functional/newstyle__slots__.py delete mode 100644 pymode/libs/pylint/test/functional/newstyle__slots__.txt delete mode 100644 pymode/libs/pylint/test/functional/newstyle_properties.py delete mode 100644 pymode/libs/pylint/test/functional/newstyle_properties.txt delete mode 100644 pymode/libs/pylint/test/functional/no_classmethod_decorator.py delete mode 100644 pymode/libs/pylint/test/functional/no_classmethod_decorator.txt delete mode 100644 pymode/libs/pylint/test/functional/no_name_in_module.py delete mode 100644 pymode/libs/pylint/test/functional/no_name_in_module.txt delete mode 100644 pymode/libs/pylint/test/functional/no_self_use.py delete mode 100644 pymode/libs/pylint/test/functional/no_self_use.txt delete mode 100644 pymode/libs/pylint/test/functional/no_self_use_py3.py delete mode 100644 pymode/libs/pylint/test/functional/no_self_use_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/no_self_use_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/no_staticmethod_decorator.py delete mode 100644 pymode/libs/pylint/test/functional/no_staticmethod_decorator.txt delete mode 100644 pymode/libs/pylint/test/functional/non_iterator_returned.py delete mode 100644 pymode/libs/pylint/test/functional/non_iterator_returned.txt delete mode 100644 pymode/libs/pylint/test/functional/nonexistent_operator.py delete mode 100644 pymode/libs/pylint/test/functional/nonexistent_operator.txt delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_and_global.py delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_and_global.rc delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_and_global.txt delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_without_binding.py delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_without_binding.rc delete mode 100644 pymode/libs/pylint/test/functional/nonlocal_without_binding.txt delete mode 100644 pymode/libs/pylint/test/functional/not_async_context_manager.py delete mode 100644 pymode/libs/pylint/test/functional/not_async_context_manager.rc delete mode 100644 pymode/libs/pylint/test/functional/not_async_context_manager.txt delete mode 100644 pymode/libs/pylint/test/functional/not_callable.py delete mode 100644 pymode/libs/pylint/test/functional/not_callable.txt delete mode 100644 pymode/libs/pylint/test/functional/not_context_manager.py delete mode 100644 pymode/libs/pylint/test/functional/not_context_manager.txt delete mode 100644 pymode/libs/pylint/test/functional/not_in_loop.py delete mode 100644 pymode/libs/pylint/test/functional/not_in_loop.txt delete mode 100644 pymode/libs/pylint/test/functional/old_division_manually.py delete mode 100644 pymode/libs/pylint/test/functional/old_division_manually.rc delete mode 100644 pymode/libs/pylint/test/functional/old_style_class_py27.py delete mode 100644 pymode/libs/pylint/test/functional/old_style_class_py27.rc delete mode 100644 pymode/libs/pylint/test/functional/old_style_class_py27.txt delete mode 100644 pymode/libs/pylint/test/functional/pygtk_enum_crash.py delete mode 100644 pymode/libs/pylint/test/functional/pygtk_enum_crash.rc delete mode 100644 pymode/libs/pylint/test/functional/pygtk_import.py delete mode 100644 pymode/libs/pylint/test/functional/pygtk_import.rc delete mode 100644 pymode/libs/pylint/test/functional/raising_non_exception_py3.py delete mode 100644 pymode/libs/pylint/test/functional/raising_non_exception_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/raising_non_exception_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/redefined_builtin.py delete mode 100644 pymode/libs/pylint/test/functional/redefined_builtin.txt delete mode 100644 pymode/libs/pylint/test/functional/redefined_variable_type.py delete mode 100644 pymode/libs/pylint/test/functional/redefined_variable_type.txt delete mode 100644 pymode/libs/pylint/test/functional/redundant_unittest_assert.py delete mode 100644 pymode/libs/pylint/test/functional/redundant_unittest_assert.txt delete mode 100644 pymode/libs/pylint/test/functional/regression_no_value_for_parameter.py delete mode 100644 pymode/libs/pylint/test/functional/regression_no_value_for_parameter.txt delete mode 100644 pymode/libs/pylint/test/functional/reimported.py delete mode 100644 pymode/libs/pylint/test/functional/reimported.txt delete mode 100644 pymode/libs/pylint/test/functional/repeated_keyword.py delete mode 100644 pymode/libs/pylint/test/functional/repeated_keyword.txt delete mode 100644 pymode/libs/pylint/test/functional/return_in_init.py delete mode 100644 pymode/libs/pylint/test/functional/return_in_init.txt delete mode 100644 pymode/libs/pylint/test/functional/return_outside_function.py delete mode 100644 pymode/libs/pylint/test/functional/return_outside_function.txt delete mode 100644 pymode/libs/pylint/test/functional/simplifiable_if_statement.py delete mode 100644 pymode/libs/pylint/test/functional/simplifiable_if_statement.txt delete mode 100644 pymode/libs/pylint/test/functional/singleton_comparison.py delete mode 100644 pymode/libs/pylint/test/functional/singleton_comparison.txt delete mode 100644 pymode/libs/pylint/test/functional/slots_checks.py delete mode 100644 pymode/libs/pylint/test/functional/slots_checks.txt delete mode 100644 pymode/libs/pylint/test/functional/socketerror_import.py delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target.py delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target.rc delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target.txt delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.py delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.rc delete mode 100644 pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.txt delete mode 100644 pymode/libs/pylint/test/functional/statement_without_effect.py delete mode 100644 pymode/libs/pylint/test/functional/statement_without_effect.txt delete mode 100644 pymode/libs/pylint/test/functional/string_formatting.py delete mode 100644 pymode/libs/pylint/test/functional/string_formatting.txt delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_disable.py delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_disable.rc delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_disable.txt delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_failed_inference.py delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_py27.py delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_py27.rc delete mode 100644 pymode/libs/pylint/test/functional/string_formatting_py27.txt delete mode 100644 pymode/libs/pylint/test/functional/super_checks.py delete mode 100644 pymode/libs/pylint/test/functional/super_checks.txt delete mode 100644 pymode/libs/pylint/test/functional/superfluous_parens.py delete mode 100644 pymode/libs/pylint/test/functional/superfluous_parens.txt delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call.py delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call.rc delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call.txt delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.py delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.rc delete mode 100644 pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.txt delete mode 100644 pymode/libs/pylint/test/functional/syntax_error.py delete mode 100644 pymode/libs/pylint/test/functional/syntax_error.rc delete mode 100644 pymode/libs/pylint/test/functional/syntax_error.txt delete mode 100644 pymode/libs/pylint/test/functional/syntax_error_jython.py delete mode 100644 pymode/libs/pylint/test/functional/syntax_error_jython.rc delete mode 100644 pymode/libs/pylint/test/functional/syntax_error_jython.txt delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error.py delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error.rc delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error.txt delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error_jython.py delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error_jython.rc delete mode 100644 pymode/libs/pylint/test/functional/tokenize_error_jython.txt delete mode 100644 pymode/libs/pylint/test/functional/too_few_public_methods.py delete mode 100644 pymode/libs/pylint/test/functional/too_few_public_methods.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_ancestors.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_ancestors.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_arguments.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_arguments.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_boolean_expressions.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_boolean_expressions.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_branches.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_branches.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_instance_attributes.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_instance_attributes.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_lines.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_lines.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_lines_disabled.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_locals.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_locals.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_nested_blocks.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_nested_blocks.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_public_methods.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_public_methods.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_return_statements.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_return_statements.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_star_expressions.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_star_expressions.rc delete mode 100644 pymode/libs/pylint/test/functional/too_many_star_expressions.txt delete mode 100644 pymode/libs/pylint/test/functional/too_many_statements.py delete mode 100644 pymode/libs/pylint/test/functional/too_many_statements.txt delete mode 100644 pymode/libs/pylint/test/functional/trailing_newlines.py delete mode 100644 pymode/libs/pylint/test/functional/trailing_newlines.txt delete mode 100644 pymode/libs/pylint/test/functional/trailing_whitespaces.py delete mode 100644 pymode/libs/pylint/test/functional/trailing_whitespaces.txt delete mode 100644 pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.py delete mode 100644 pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.txt delete mode 100644 pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.py delete mode 100644 pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.rc delete mode 100644 pymode/libs/pylint/test/functional/undefined_variable.py delete mode 100644 pymode/libs/pylint/test/functional/undefined_variable.txt delete mode 100644 pymode/libs/pylint/test/functional/undefined_variable_py30.py delete mode 100644 pymode/libs/pylint/test/functional/undefined_variable_py30.rc delete mode 100644 pymode/libs/pylint/test/functional/undefined_variable_py30.txt delete mode 100644 pymode/libs/pylint/test/functional/unexpected_special_method_signature.py delete mode 100644 pymode/libs/pylint/test/functional/unexpected_special_method_signature.txt delete mode 100644 pymode/libs/pylint/test/functional/ungrouped_imports.py delete mode 100644 pymode/libs/pylint/test/functional/ungrouped_imports.txt delete mode 100644 pymode/libs/pylint/test/functional/unidiomatic_typecheck.py delete mode 100644 pymode/libs/pylint/test/functional/unidiomatic_typecheck.txt delete mode 100644 pymode/libs/pylint/test/functional/uninferable_all_object.py delete mode 100644 pymode/libs/pylint/test/functional/unnecessary_lambda.py delete mode 100644 pymode/libs/pylint/test/functional/unnecessary_lambda.txt delete mode 100644 pymode/libs/pylint/test/functional/unnecessary_pass.py delete mode 100644 pymode/libs/pylint/test/functional/unnecessary_pass.txt delete mode 100644 pymode/libs/pylint/test/functional/unneeded_not.py delete mode 100644 pymode/libs/pylint/test/functional/unneeded_not.txt delete mode 100644 pymode/libs/pylint/test/functional/unpacked_exceptions.py delete mode 100644 pymode/libs/pylint/test/functional/unpacked_exceptions.rc delete mode 100644 pymode/libs/pylint/test/functional/unpacked_exceptions.txt delete mode 100644 pymode/libs/pylint/test/functional/unpacking.py delete mode 100644 pymode/libs/pylint/test/functional/unpacking_generalizations.py delete mode 100644 pymode/libs/pylint/test/functional/unpacking_generalizations.rc delete mode 100644 pymode/libs/pylint/test/functional/unpacking_generalizations.txt delete mode 100644 pymode/libs/pylint/test/functional/unpacking_non_sequence.py delete mode 100644 pymode/libs/pylint/test/functional/unpacking_non_sequence.txt delete mode 100644 pymode/libs/pylint/test/functional/unreachable.py delete mode 100644 pymode/libs/pylint/test/functional/unreachable.txt delete mode 100644 pymode/libs/pylint/test/functional/unrecognized_inline_option.py delete mode 100644 pymode/libs/pylint/test/functional/unrecognized_inline_option.txt delete mode 100644 pymode/libs/pylint/test/functional/unsubscriptable_value.py delete mode 100644 pymode/libs/pylint/test/functional/unsubscriptable_value.txt delete mode 100644 pymode/libs/pylint/test/functional/unsubscriptable_value_35.py delete mode 100644 pymode/libs/pylint/test/functional/unsubscriptable_value_35.rc delete mode 100644 pymode/libs/pylint/test/functional/unsupported_binary_operation.py delete mode 100644 pymode/libs/pylint/test/functional/unsupported_binary_operation.rc delete mode 100644 pymode/libs/pylint/test/functional/unsupported_binary_operation.txt delete mode 100644 pymode/libs/pylint/test/functional/unused_import.py delete mode 100644 pymode/libs/pylint/test/functional/unused_import.txt delete mode 100644 pymode/libs/pylint/test/functional/unused_variable.py delete mode 100644 pymode/libs/pylint/test/functional/unused_variable.txt delete mode 100644 pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.py delete mode 100644 pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.rc delete mode 100644 pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.txt delete mode 100644 pymode/libs/pylint/test/functional/useless_else_on_loop.py delete mode 100644 pymode/libs/pylint/test/functional/useless_else_on_loop.txt delete mode 100644 pymode/libs/pylint/test/functional/using_constant_test.py delete mode 100644 pymode/libs/pylint/test/functional/using_constant_test.txt delete mode 100644 pymode/libs/pylint/test/functional/wildcard_import.py delete mode 100644 pymode/libs/pylint/test/functional/wildcard_import.txt delete mode 100644 pymode/libs/pylint/test/functional/with_used_before_assign.py delete mode 100644 pymode/libs/pylint/test/functional/with_used_before_assign.txt delete mode 100644 pymode/libs/pylint/test/functional/with_using_generator.py delete mode 100644 pymode/libs/pylint/test/functional/with_using_generator.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_order.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_order.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_order2.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position10.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position11.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position11.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position12.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position12.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position13.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position13.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position14.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position14.txt delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position15.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position2.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position3.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position4.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position5.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position6.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position7.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position8.py delete mode 100644 pymode/libs/pylint/test/functional/wrong_import_position9.py delete mode 100644 pymode/libs/pylint/test/functional/yield_from_iterable_py33.py delete mode 100644 pymode/libs/pylint/test/functional/yield_from_iterable_py33.rc delete mode 100644 pymode/libs/pylint/test/functional/yield_from_iterable_py33.txt delete mode 100644 pymode/libs/pylint/test/functional/yield_from_outside_func.py delete mode 100644 pymode/libs/pylint/test/functional/yield_from_outside_func.rc delete mode 100644 pymode/libs/pylint/test/functional/yield_from_outside_func.txt delete mode 100644 pymode/libs/pylint/test/functional/yield_inside_async_function.py delete mode 100644 pymode/libs/pylint/test/functional/yield_inside_async_function.rc delete mode 100644 pymode/libs/pylint/test/functional/yield_inside_async_function.txt delete mode 100644 pymode/libs/pylint/test/functional/yield_outside_func.py delete mode 100644 pymode/libs/pylint/test/functional/yield_outside_func.txt delete mode 100644 pymode/libs/pylint/test/input/__init__.py delete mode 100644 pymode/libs/pylint/test/input/func_3k_removed_stuff_py_30.py delete mode 100644 pymode/libs/pylint/test/input/func_bad_assigment_to_exception_var.py delete mode 100644 pymode/libs/pylint/test/input/func_bad_cont_dictcomp_py27.py delete mode 100644 pymode/libs/pylint/test/input/func_block_disable_msg.py delete mode 100644 pymode/libs/pylint/test/input/func_break_or_return_in_try_finally.py delete mode 100644 pymode/libs/pylint/test/input/func_bug113231.py delete mode 100644 pymode/libs/pylint/test/input/func_disable_linebased.py delete mode 100644 pymode/libs/pylint/test/input/func_dotted_ancestor.py delete mode 100644 pymode/libs/pylint/test/input/func_e0012.py delete mode 100644 pymode/libs/pylint/test/input/func_e0203.py delete mode 100644 pymode/libs/pylint/test/input/func_e0204.py delete mode 100644 pymode/libs/pylint/test/input/func_e0601.py delete mode 100644 pymode/libs/pylint/test/input/func_e0604.py delete mode 100644 pymode/libs/pylint/test/input/func_e12xx.py delete mode 100644 pymode/libs/pylint/test/input/func_e13xx.py delete mode 100644 pymode/libs/pylint/test/input/func_excess_escapes.py delete mode 100644 pymode/libs/pylint/test/input/func_first_arg.py delete mode 100644 pymode/libs/pylint/test/input/func_i0011.py delete mode 100644 pymode/libs/pylint/test/input/func_i0012.py delete mode 100644 pymode/libs/pylint/test/input/func_i0013.py delete mode 100644 pymode/libs/pylint/test/input/func_i0014.py delete mode 100644 pymode/libs/pylint/test/input/func_i0020.py delete mode 100644 pymode/libs/pylint/test/input/func_i0022.py delete mode 100644 pymode/libs/pylint/test/input/func_init_vars.py delete mode 100644 pymode/libs/pylint/test/input/func_kwoa_py30.py delete mode 100644 pymode/libs/pylint/test/input/func_logging_not_lazy_with_logger.py delete mode 100644 pymode/libs/pylint/test/input/func_loopvar_in_dict_comp_py27.py delete mode 100644 pymode/libs/pylint/test/input/func_module___dict__.py delete mode 100644 pymode/libs/pylint/test/input/func_nameerror_on_string_substitution.py delete mode 100644 pymode/libs/pylint/test/input/func_no_dummy_redefined.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror___init___return_from_inner_function.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_access_attr_before_def_false_positive.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_base_init_vars.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_builtin_module_test.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_class_attributes.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_classes_meth_could_be_a_function.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_classes_protected_member_access.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_crash_127416.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_decorator_scope.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_e1101_9588_base_attr_aug_assign.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_encoding.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_except_pass.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_exception.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_external_classmethod_crash.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_function_as_method.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_genexp_in_class_scope.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_inner_classes.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_lambda_use_before_assign.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_long_utf8_line.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_mcs_attr_access.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_new_style_class_py_30.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_no_warning_docstring.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_nonregr.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_object_as_class_attribute.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_overloaded_operator.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_overriden_method_varargs.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_property_affectation_py26.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_raise_return_self.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_static_method.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_yield_assign_py25.py delete mode 100644 pymode/libs/pylint/test/input/func_noerror_yield_return_mix.py delete mode 100644 pymode/libs/pylint/test/input/func_nonregr___file___global.py delete mode 100644 pymode/libs/pylint/test/input/func_return_yield_mix_py_33.py delete mode 100644 pymode/libs/pylint/test/input/func_too_many_returns_yields.py delete mode 100644 pymode/libs/pylint/test/input/func_typecheck_callfunc_assigment.py delete mode 100644 pymode/libs/pylint/test/input/func_unused_import_py30.py delete mode 100644 pymode/libs/pylint/test/input/func_unused_overridden_argument.py delete mode 100644 pymode/libs/pylint/test/input/func_use_for_or_listcomp_var.py delete mode 100644 pymode/libs/pylint/test/input/func_variables_unused_name_from_wilcard_import.py delete mode 100644 pymode/libs/pylint/test/input/func_w0122_py_30.py delete mode 100644 pymode/libs/pylint/test/input/func_w0205.py delete mode 100644 pymode/libs/pylint/test/input/func_w0233.py delete mode 100644 pymode/libs/pylint/test/input/func_w0332_py_30.py delete mode 100644 pymode/libs/pylint/test/input/func_w0401.py delete mode 100644 pymode/libs/pylint/test/input/func_w0401_package/__init__.py delete mode 100644 pymode/libs/pylint/test/input/func_w0401_package/all_the_things.py delete mode 100644 pymode/libs/pylint/test/input/func_w0401_package/thing1.py delete mode 100644 pymode/libs/pylint/test/input/func_w0401_package/thing2.py delete mode 100644 pymode/libs/pylint/test/input/func_w0404.py delete mode 100644 pymode/libs/pylint/test/input/func_w0405.py delete mode 100644 pymode/libs/pylint/test/input/func_w0406.py delete mode 100644 pymode/libs/pylint/test/input/func_w0611.py delete mode 100644 pymode/libs/pylint/test/input/func_w0612.py delete mode 100644 pymode/libs/pylint/test/input/func_w0613.py delete mode 100644 pymode/libs/pylint/test/input/func_w0623_py30.py delete mode 100644 pymode/libs/pylint/test/input/func_w0623_py_30.py delete mode 100644 pymode/libs/pylint/test/input/func_w0631.py delete mode 100644 pymode/libs/pylint/test/input/func_w0703.py delete mode 100644 pymode/libs/pylint/test/input/func_w0705.py delete mode 100644 pymode/libs/pylint/test/input/func_w0801.py delete mode 100644 pymode/libs/pylint/test/input/func_with_without_as_py25.py delete mode 100644 pymode/libs/pylint/test/input/ignore_except_pass_by_default.py delete mode 100644 pymode/libs/pylint/test/input/noext delete mode 100644 pymode/libs/pylint/test/input/similar1 delete mode 100644 pymode/libs/pylint/test/input/similar2 delete mode 100644 pymode/libs/pylint/test/input/syntax_error.py delete mode 100644 pymode/libs/pylint/test/input/w0401_cycle.py delete mode 100644 pymode/libs/pylint/test/input/w0801_same.py delete mode 100644 pymode/libs/pylint/test/messages/builtin_module.txt delete mode 100644 pymode/libs/pylint/test/messages/func_3k_removed_stuff_py_30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_bad_assigment_to_exception_var.txt delete mode 100644 pymode/libs/pylint/test/messages/func_bad_cont_dictcomp_py27.txt delete mode 100644 pymode/libs/pylint/test/messages/func_block_disable_msg.txt delete mode 100644 pymode/libs/pylint/test/messages/func_break_or_return_in_try_finally.txt delete mode 100644 pymode/libs/pylint/test/messages/func_bug113231.txt delete mode 100644 pymode/libs/pylint/test/messages/func_disable_linebased.txt delete mode 100644 pymode/libs/pylint/test/messages/func_disable_linebased_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_dotted_ancestor.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e0012.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e0203.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e0204.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e0601.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e0604.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e12xx.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e13xx.txt delete mode 100644 pymode/libs/pylint/test/messages/func_e13xx_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_excess_escapes.txt delete mode 100644 pymode/libs/pylint/test/messages/func_first_arg.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0011.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0012.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0013.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0014.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0020.txt delete mode 100644 pymode/libs/pylint/test/messages/func_i0022.txt delete mode 100644 pymode/libs/pylint/test/messages/func_init_vars.txt delete mode 100644 pymode/libs/pylint/test/messages/func_kwoa_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_logging_not_lazy_with_logger.txt delete mode 100644 pymode/libs/pylint/test/messages/func_loopvar_in_dict_comp_py27.txt delete mode 100644 pymode/libs/pylint/test/messages/func_module___dict__.txt delete mode 100644 pymode/libs/pylint/test/messages/func_nameerror_on_string_substitution.txt delete mode 100644 pymode/libs/pylint/test/messages/func_no_dummy_redefined.txt delete mode 100644 pymode/libs/pylint/test/messages/func_nonregr___file___global.txt delete mode 100644 pymode/libs/pylint/test/messages/func_raw_escapes.txt delete mode 100644 pymode/libs/pylint/test/messages/func_return_yield_mix_py_33.txt delete mode 100644 pymode/libs/pylint/test/messages/func_too_many_returns_yields.txt delete mode 100644 pymode/libs/pylint/test/messages/func_toolonglines_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_typecheck_callfunc_assigment.txt delete mode 100644 pymode/libs/pylint/test/messages/func_typecheck_getattr_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_typecheck_non_callable_call.txt delete mode 100644 pymode/libs/pylint/test/messages/func_unicode_literal_py26.txt delete mode 100644 pymode/libs/pylint/test/messages/func_unicode_literal_py274.txt delete mode 100644 pymode/libs/pylint/test/messages/func_unused_import_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_unused_overridden_argument.txt delete mode 100644 pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py29.txt delete mode 100644 pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_variables_unused_name_from_wilcard_import.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0122_py_30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0205.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0233.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0312.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0332_py_30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0401.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0401_package.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0404.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0405.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0406.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0611.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0612.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0613.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0622.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0623.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0623_py30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0623_py_30.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0631.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0703.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0705.txt delete mode 100644 pymode/libs/pylint/test/messages/func_w0801.txt delete mode 100644 pymode/libs/pylint/test/messages/func_with_without_as_py25.txt delete mode 100644 pymode/libs/pylint/test/regrtest_data/.pylintrc delete mode 100644 pymode/libs/pylint/test/regrtest_data/absimp/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/absimp/string.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/application_crash.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/bad_package/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/bad_package/wrong.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/classdoc_usage.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/decimal_inference.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/descriptor_crash.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/dummy/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/dummy/another.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/dummy/dummy.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/html_crash_420.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/huge.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/import_assign.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/import_package_subpackage_module.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/import_something.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/meta.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/module_global.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/no_stdout_encoding.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/numarray_import.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/numarray_inf.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package/AudioTime.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package/subpackage/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package/subpackage/module.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package_all/__init__.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/package_all/notmissing.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/precedence_test.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/py3k_error_flag.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/special_attr_scope_lookup_crash.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/syntax_error.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/try_finally_disable_msg_crash.py delete mode 100644 pymode/libs/pylint/test/regrtest_data/wrong_import_position.py delete mode 100644 pymode/libs/pylint/test/test_func.py delete mode 100644 pymode/libs/pylint/test/test_functional.py delete mode 100644 pymode/libs/pylint/test/test_import_graph.py delete mode 100644 pymode/libs/pylint/test/test_regr.py delete mode 100644 pymode/libs/pylint/test/test_self.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_base.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_classes.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_exceptions.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_format.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_imports.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_logging.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_misc.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_python3.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_similar.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_spelling.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_stdlib.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_strings.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_typecheck.py delete mode 100644 pymode/libs/pylint/test/unittest_checker_variables.py delete mode 100644 pymode/libs/pylint/test/unittest_checkers_utils.py delete mode 100644 pymode/libs/pylint/test/unittest_config.py delete mode 100644 pymode/libs/pylint/test/unittest_lint.py delete mode 100644 pymode/libs/pylint/test/unittest_pyreverse_diadefs.py delete mode 100644 pymode/libs/pylint/test/unittest_pyreverse_inspector.py delete mode 100644 pymode/libs/pylint/test/unittest_pyreverse_writer.py delete mode 100644 pymode/libs/pylint/test/unittest_reporters_json.py delete mode 100644 pymode/libs/pylint/test/unittest_reporting.py delete mode 100644 pymode/libs/pylint/test/unittest_utils.py delete mode 100755 pymode/libs/wrapt/_wrappers.so diff --git a/Makefile b/Makefile index dac3a287..5e5a0990 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,10 @@ pylama: @pip install --upgrade --force-reinstall --target=$(LIBS) pycodestyle @pip install --upgrade --force-reinstall --target=$(LIBS) pyflakes @pip install --upgrade --force-reinstall --target=$(LIBS) mccabe - @find $(LIBS)/*.dist-info | xargs rm -rf + @pip install --upgrade --force-reinstall --target=$(LIBS) pylint + @find $(LIBS) -name *.dist-info -type d | xargs rm -rf + @find $(LIBS) -name *.egg-info -type d | xargs rm -rf + @find $(LIBS) -name test* -type d | xargs rm -rf .PHONY: rope rope: diff --git a/pymode/libs/astroid/__init__.py b/pymode/libs/astroid/__init__.py index 175dcb5e..69b2ff0c 100644 --- a/pymode/libs/astroid/__init__.py +++ b/pymode/libs/astroid/__init__.py @@ -1,20 +1,10 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2013, 2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Python Abstract Syntax Tree New Generation The aim of this module is to provide a common base representation of @@ -39,14 +29,27 @@ * builder contains the class responsible to build astroid trees """ -__doctype__ = "restructuredtext en" +import os import sys import re from operator import attrgetter +import enum + + +_Context = enum.Enum('Context', 'Load Store Del') +Load = _Context.Load +Store = _Context.Store +Del = _Context.Del +del _Context + + +from .__pkginfo__ import version as __version__ # WARNING: internal imports order matters ! +# pylint: disable=redefined-builtin, wildcard-import + # make all exception classes accessible from astroid package from astroid.exceptions import * @@ -58,14 +61,13 @@ # more stuff available from astroid import raw_building -from astroid.bases import Instance, BoundMethod, UnboundMethod +from astroid.bases import BaseInstance, Instance, BoundMethod, UnboundMethod from astroid.node_classes import are_exclusive, unpack_infer from astroid.scoped_nodes import builtin_lookup -from astroid.builder import parse -from astroid.util import YES +from astroid.builder import parse, extract_node +from astroid.util import Uninferable, YES -# make a manager instance (borg) as well as Project and Package classes -# accessible from astroid package +# make a manager instance (borg) accessible from astroid package from astroid.manager import AstroidManager MANAGER = AstroidManager() del AstroidManager @@ -73,7 +75,7 @@ # transform utilities (filters and decorator) class AsStringRegexpPredicate(object): - """Class to be used as predicate that may be given to `register_transform` + """ClassDef to be used as predicate that may be given to `register_transform` First argument is a regular expression that will be searched against the `as_string` representation of the node onto which it's applied. @@ -92,6 +94,7 @@ def __init__(self, regexp, expression=None): def __call__(self, node): if self.expression is not None: node = attrgetter(self.expression)(node) + # pylint: disable=no-member; github.com/pycqa/astroid/126 return self.regexp.search(node.as_string()) def inference_tip(infer_function): @@ -114,8 +117,8 @@ def transform(node, infer_function=infer_function): def register_module_extender(manager, module_name, get_extension_mod): def transform(node): extension_module = get_extension_mod() - for name, objs in extension_module._locals.items(): - node._locals[name] = objs + for name, objs in extension_module.locals.items(): + node.locals[name] = objs for obj in objs: if obj.parent is extension_module: obj.parent = node @@ -124,13 +127,11 @@ def transform(node): # load brain plugins -from os import listdir -from os.path import join, dirname -BRAIN_MODULES_DIR = join(dirname(__file__), 'brain') +BRAIN_MODULES_DIR = os.path.join(os.path.dirname(__file__), 'brain') if BRAIN_MODULES_DIR not in sys.path: # add it to the end of the list so user path take precedence sys.path.append(BRAIN_MODULES_DIR) # load modules in this directory -for module in listdir(BRAIN_MODULES_DIR): +for module in os.listdir(BRAIN_MODULES_DIR): if module.endswith('.py'): __import__(module[:-3]) diff --git a/pymode/libs/astroid/__pkginfo__.py b/pymode/libs/astroid/__pkginfo__.py index 7a5acfa5..96c2dcba 100644 --- a/pymode/libs/astroid/__pkginfo__.py +++ b/pymode/libs/astroid/__pkginfo__.py @@ -1,30 +1,49 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """astroid packaging information""" + +from sys import version_info as py_version + +from pkg_resources import parse_version +from setuptools import __version__ as setuptools_version + distname = 'astroid' modname = 'astroid' -numversion = (1, 4, 9) -version = '.'.join([str(num) for num in numversion]) +version = '1.5.3' +numversion = tuple(map(int, version.split('.'))) + +extras_require = {} +install_requires = ['lazy_object_proxy', 'six', 'wrapt'] + + +def has_environment_marker_range_operators_support(): + """Code extracted from 'pytest/setup.py' + https://github.com/pytest-dev/pytest/blob/7538680c/setup.py#L31 + + The first known release to support environment marker with range operators + it is 17.1, see: https://setuptools.readthedocs.io/en/latest/history.html#id113 + """ + return parse_version(setuptools_version) >= parse_version('17.1') + + +if has_environment_marker_range_operators_support(): + extras_require[':python_version<"3.4"'] = ['enum34>=1.1.3', 'singledispatch'] + extras_require[':python_version<"3.3"'] = ['backports.functools_lru_cache'] +else: + if py_version < (3, 4): + install_requires.extend(['enum34', 'singledispatch']) + if py_version < (3, 3): + install_requires.append('backports.functools_lru_cache') -install_requires = ['six', 'lazy_object_proxy', 'wrapt'] +# pylint: disable=redefined-builtin; why license is a builtin anyway? license = 'LGPL' author = 'Python Code Quality Authority' diff --git a/pymode/libs/astroid/arguments.py b/pymode/libs/astroid/arguments.py index f05d48a3..f81ccbd6 100644 --- a/pymode/libs/astroid/arguments.py +++ b/pymode/libs/astroid/arguments.py @@ -1,20 +1,11 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + + +import six from astroid import bases from astroid import context as contextmod @@ -22,7 +13,6 @@ from astroid import nodes from astroid import util -import six class CallSite(object): @@ -44,11 +34,11 @@ def __init__(self, callcontext): self.positional_arguments = [ arg for arg in self._unpacked_args - if arg is not util.YES + if arg is not util.Uninferable ] self.keyword_arguments = { key: value for key, value in self._unpacked_kwargs.items() - if value is not util.YES + if value is not util.Uninferable } @classmethod @@ -87,29 +77,29 @@ def _unpack_keywords(self, keywords): try: inferred = next(value.infer(context=context)) except exceptions.InferenceError: - values[name] = util.YES + values[name] = util.Uninferable continue if not isinstance(inferred, nodes.Dict): # Not something we can work with. - values[name] = util.YES + values[name] = util.Uninferable continue for dict_key, dict_value in inferred.items: try: dict_key = next(dict_key.infer(context=context)) except exceptions.InferenceError: - values[name] = util.YES + values[name] = util.Uninferable continue if not isinstance(dict_key, nodes.Const): - values[name] = util.YES + values[name] = util.Uninferable continue if not isinstance(dict_key.value, six.string_types): - values[name] = util.YES + values[name] = util.Uninferable continue if dict_key.value in values: # The name is already in the dictionary - values[dict_key.value] = util.YES + values[dict_key.value] = util.Uninferable self.duplicated_keywords.add(dict_key.value) continue values[dict_key.value] = dict_value @@ -126,14 +116,14 @@ def _unpack_args(args): try: inferred = next(arg.value.infer(context=context)) except exceptions.InferenceError: - values.append(util.YES) + values.append(util.Uninferable) continue - if inferred is util.YES: - values.append(util.YES) + if inferred is util.Uninferable: + values.append(util.Uninferable) continue if not hasattr(inferred, 'elts'): - values.append(util.YES) + values.append(util.Uninferable) continue values.extend(inferred.elts) else: @@ -141,9 +131,18 @@ def _unpack_args(args): return values def infer_argument(self, funcnode, name, context): - """infer a function argument value according to the call context""" + """infer a function argument value according to the call context + + Arguments: + funcnode: The function being called. + name: The name of the argument whose value is being inferred. + context: TODO + """ if name in self.duplicated_keywords: - raise exceptions.InferenceError(name) + raise exceptions.InferenceError('The arguments passed to {func!r} ' + ' have duplicate keywords.', + call_site=self, func=funcnode, + arg=name, context=context) # Look into the keywords first, maybe it's already there. try: @@ -154,7 +153,11 @@ def infer_argument(self, funcnode, name, context): # Too many arguments given and no variable arguments. if len(self.positional_arguments) > len(funcnode.args.args): if not funcnode.args.vararg: - raise exceptions.InferenceError(name) + raise exceptions.InferenceError('Too many positional arguments ' + 'passed to {func!r} that does ' + 'not have *args.', + call_site=self, func=funcnode, + arg=name, context=context) positional = self.positional_arguments[:len(funcnode.args.args)] vararg = self.positional_arguments[len(funcnode.args.args):] @@ -183,6 +186,16 @@ def infer_argument(self, funcnode, name, context): else: # XXX can do better ? boundnode = funcnode.parent.frame() + + if isinstance(boundnode, nodes.ClassDef): + # Verify that we're accessing a method + # of the metaclass through a class, as in + # `cls.metaclass_method`. In this case, the + # first argument is always the class. + method_scope = funcnode.parent.scope() + if method_scope is boundnode.metaclass(): + return iter((boundnode, )) + if funcnode.type == 'method': if not isinstance(boundnode, bases.Instance): boundnode = bases.Instance(boundnode) @@ -204,25 +217,34 @@ def infer_argument(self, funcnode, name, context): # It wants all the keywords that were passed into # the call site. if self.has_invalid_keywords(): - raise exceptions.InferenceError - kwarg = nodes.Dict() - kwarg.lineno = funcnode.args.lineno - kwarg.col_offset = funcnode.args.col_offset - kwarg.parent = funcnode.args - items = [(nodes.const_factory(key), value) - for key, value in kwargs.items()] - kwarg.items = items + raise exceptions.InferenceError( + "Inference failed to find values for all keyword arguments " + "to {func!r}: {unpacked_kwargs!r} doesn't correspond to " + "{keyword_arguments!r}.", + keyword_arguments=self.keyword_arguments, + unpacked_kwargs=self._unpacked_kwargs, + call_site=self, func=funcnode, arg=name, context=context) + kwarg = nodes.Dict(lineno=funcnode.args.lineno, + col_offset=funcnode.args.col_offset, + parent=funcnode.args) + kwarg.postinit([(nodes.const_factory(key), value) + for key, value in kwargs.items()]) return iter((kwarg, )) elif funcnode.args.vararg == name: # It wants all the args that were passed into # the call site. if self.has_invalid_arguments(): - raise exceptions.InferenceError - args = nodes.Tuple() - args.lineno = funcnode.args.lineno - args.col_offset = funcnode.args.col_offset - args.parent = funcnode.args - args.elts = vararg + raise exceptions.InferenceError( + "Inference failed to find values for all positional " + "arguments to {func!r}: {unpacked_args!r} doesn't " + "correspond to {positional_arguments!r}.", + positional_arguments=self.positional_arguments, + unpacked_args=self._unpacked_args, + call_site=self, func=funcnode, arg=name, context=context) + args = nodes.Tuple(lineno=funcnode.args.lineno, + col_offset=funcnode.args.col_offset, + parent=funcnode.args) + args.postinit(vararg) return iter((args, )) # Check if it's a default parameter. @@ -230,4 +252,6 @@ def infer_argument(self, funcnode, name, context): return funcnode.args.default_value(name).infer(context) except exceptions.NoDefault: pass - raise exceptions.InferenceError(name) + raise exceptions.InferenceError('No value found for argument {name} to ' + '{func!r}', call_site=self, + func=funcnode, arg=name, context=context) diff --git a/pymode/libs/astroid/as_string.py b/pymode/libs/astroid/as_string.py index 2b07200c..85afdc30 100644 --- a/pymode/libs/astroid/as_string.py +++ b/pymode/libs/astroid/as_string.py @@ -1,23 +1,14 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """This module renders Astroid nodes as string: -* :func:`to_code` function return equivalent (hopefuly valid) python string +* :func:`to_code` function return equivalent (hopefully valid) python string * :func:`dump` function return an internal representation of nodes found in the tree, useful for debugging or understanding the tree structure @@ -26,54 +17,16 @@ import six -INDENT = ' ' # 4 spaces ; keep indentation variable - - -def dump(node, ids=False): - """print a nice astroid tree representation. - - :param ids: if true, we also print the ids (usefull for debugging) - """ - result = [] - _repr_tree(node, result, ids=ids) - return "\n".join(result) - -def _repr_tree(node, result, indent='', _done=None, ids=False): - """built a tree representation of a node as a list of lines""" - if _done is None: - _done = set() - if not hasattr(node, '_astroid_fields'): # not a astroid node - return - if node in _done: - result.append(indent + 'loop in tree: %s' % node) - return - _done.add(node) - node_str = str(node) - if ids: - node_str += ' . \t%x' % id(node) - result.append(indent + node_str) - indent += INDENT - for field in node._astroid_fields: - value = getattr(node, field) - if isinstance(value, (list, tuple)): - result.append(indent + field + " = [") - for child in value: - if isinstance(child, (list, tuple)): - # special case for Dict # FIXME - _repr_tree(child[0], result, indent, _done, ids) - _repr_tree(child[1], result, indent, _done, ids) - result.append(indent + ',') - else: - _repr_tree(child, result, indent, _done, ids) - result.append(indent + "]") - else: - result.append(indent + field + " = ") - _repr_tree(value, result, indent, _done, ids) + +# pylint: disable=unused-argument class AsStringVisitor(object): """Visitor to render an Astroid node as a valid python code string""" + def __init__(self, indent): + self.indent = indent + def __call__(self, node): """Makes this visitor behave as a simple function""" return node.accept(self) @@ -81,7 +34,7 @@ def __call__(self, node): def _stmt_list(self, stmts): """return a list of nodes to string""" stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if nstr]) - return INDENT + stmts.replace('\n', '\n'+INDENT) + return self.indent + stmts.replace('\n', '\n'+self.indent) ## visit_ methods ########################################### @@ -114,6 +67,15 @@ def visit_augassign(self, node): """return an astroid.AugAssign node as string""" return '%s %s %s' % (node.target.accept(self), node.op, node.value.accept(self)) + def visit_annassign(self, node): + """Return an astroid.AugAssign node as string""" + + target = node.target.accept(self) + annotation = node.annotation.accept(self) + if node.value is None: + return '%s: %s' % (target, annotation) + return '%s: %s = %s' % (target, annotation, node.value.accept(self)) + def visit_repr(self, node): """return an astroid.Repr node as string""" return '`%s`' % node.value.accept(self) @@ -145,10 +107,10 @@ def visit_call(self, node): def visit_classdef(self, node): """return an astroid.ClassDef node as string""" - decorate = node.decorators and node.decorators.accept(self) or '' + decorate = node.decorators.accept(self) if node.decorators else '' bases = ', '.join([n.accept(self) for n in node.bases]) if sys.version_info[0] == 2: - bases = bases and '(%s)' % bases or '' + bases = '(%s)' % bases if bases else '' else: metaclass = node.metaclass() if metaclass and not node.has_metaclass_hack(): @@ -157,8 +119,8 @@ def visit_classdef(self, node): else: bases = '(metaclass=%s)' % metaclass.name else: - bases = bases and '(%s)' % bases or '' - docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' + bases = '(%s)' % bases if bases else '' + docs = '\n%s"""%s"""' % (self.indent, node.doc) if node.doc else '' return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs, self._stmt_list(node.body)) @@ -205,13 +167,13 @@ def visit_dict(self, node): def _visit_dict(self, node): for key, value in node.items: - key = key.accept(self) - value = value.accept(self) - if key == '**': - # It can only be a DictUnpack node. - yield key + value - else: - yield '%s: %s' % (key, value) + key = key.accept(self) + value = value.accept(self) + if key == '**': + # It can only be a DictUnpack node. + yield key + value + else: + yield '%s: %s' % (key, value) def visit_dictunpack(self, node): return '**' @@ -279,8 +241,8 @@ def visit_importfrom(self, node): def visit_functiondef(self, node): """return an astroid.Function node as string""" - decorate = node.decorators and node.decorators.accept(self) or '' - docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' + decorate = node.decorators.accept(self) if node.decorators else '' + docs = '\n%s"""%s"""' % (self.indent, node.doc) if node.doc else '' return_annotation = '' if six.PY3 and node.returns: return_annotation = '->' + node.returns.as_string() @@ -345,7 +307,7 @@ def visit_listcomp(self, node): def visit_module(self, node): """return an astroid.Module node as string""" - docs = node.doc and '"""%s"""\n\n' % node.doc or '' + docs = '"""%s"""\n\n' % node.doc if node.doc else '' return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n' def visit_name(self, node): @@ -382,8 +344,8 @@ def visit_return(self, node): """return an astroid.Return node as string""" if node.value: return 'return %s' % node.value.accept(self) - else: - return 'return' + + return 'return' def visit_index(self, node): """return a astroid.Index node as string""" @@ -400,9 +362,9 @@ def visit_setcomp(self, node): def visit_slice(self, node): """return a astroid.Slice node as string""" - lower = node.lower and node.lower.accept(self) or '' - upper = node.upper and node.upper.accept(self) or '' - step = node.step and node.step.accept(self) or '' + lower = node.lower.accept(self) if node.lower else '' + upper = node.upper.accept(self) if node.upper else'' + step = node.step.accept(self) if node.step else '' if step: return '%s:%s:%s' % (lower, upper, step) return '%s:%s' % (lower, upper) @@ -456,18 +418,17 @@ def visit_with(self, node): # 'with' without 'as' is possible def visit_yield(self, node): """yield an ast.Yield node as string""" - yi_val = node.value and (" " + node.value.accept(self)) or "" + yi_val = (" " + node.value.accept(self)) if node.value else "" expr = 'yield' + yi_val if node.parent.is_statement: return expr - else: - return "(%s)" % (expr,) + + return "(%s)" % (expr,) def visit_starred(self, node): """return Starred node as string""" return "*" + node.value.accept(self) - # These aren't for real AST nodes, but for inference objects. def visit_frozenset(self, node): @@ -476,12 +437,12 @@ def visit_frozenset(self, node): def visit_super(self, node): return node.parent.accept(self) - def visit_yes(self, node): - return "Uninferable" + def visit_uninferable(self, node): + return str(node) -class AsStringVisitor3k(AsStringVisitor): - """AsStringVisitor3k overwrites some AsStringVisitor methods""" +class AsStringVisitor3(AsStringVisitor): + """AsStringVisitor3 overwrites some AsStringVisitor methods""" def visit_excepthandler(self, node): if node.type: @@ -509,15 +470,15 @@ def visit_raise(self, node): def visit_yieldfrom(self, node): """ Return an astroid.YieldFrom node as string. """ - yi_val = node.value and (" " + node.value.accept(self)) or "" + yi_val = (" " + node.value.accept(self)) if node.value else "" expr = 'yield from' + yi_val if node.parent.is_statement: return expr - else: - return "(%s)" % (expr,) + + return "(%s)" % (expr,) def visit_asyncfunctiondef(self, node): - function = super(AsStringVisitor3k, self).visit_functiondef(node) + function = super(AsStringVisitor3, self).visit_functiondef(node) return 'async ' + function.strip() def visit_await(self, node): @@ -529,6 +490,24 @@ def visit_asyncwith(self, node): def visit_asyncfor(self, node): return 'async %s' % self.visit_for(node) + def visit_joinedstr(self, node): + # Special treatment for constants, + # as we want to join literals not reprs + string = ''.join( + value.value if type(value).__name__ == 'Const' + else value.accept(self) + for value in node.values + ) + return "f'%s'" % string + + def visit_formattedvalue(self, node): + return '{%s}' % node.value.accept(self) + + def visit_comprehension(self, node): + """return an astroid.Comprehension node as string""" + return '%s%s' % ('async ' if node.is_async else '', + super(AsStringVisitor3, self).visit_comprehension(node)) + def _import_string(names): """return a list of (name, asname) formatted as a string""" @@ -538,11 +517,11 @@ def _import_string(names): _names.append('%s as %s' % (name, asname)) else: _names.append(name) - return ', '.join(_names) + return ', '.join(_names) if sys.version_info >= (3, 0): - AsStringVisitor = AsStringVisitor3k + AsStringVisitor = AsStringVisitor3 -# this visitor is stateless, thus it can be reused -to_code = AsStringVisitor() +# This sets the default indent to 4 spaces. +to_code = AsStringVisitor(' ') diff --git a/pymode/libs/astroid/astpeephole.py b/pymode/libs/astroid/astpeephole.py index af03462a..dde5dca1 100644 --- a/pymode/libs/astroid/astpeephole.py +++ b/pymode/libs/astroid/astpeephole.py @@ -1,20 +1,8 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Small AST optimizations.""" import _ast @@ -34,7 +22,7 @@ class ASTPeepholeOptimizer(object): """Class for applying small optimizations to generate new AST.""" - def optimize_binop(self, node): + def optimize_binop(self, node, parent=None): """Optimize BinOps with string Const nodes on the lhs. This fixes an infinite recursion crash, where multiple @@ -77,10 +65,10 @@ def optimize_binop(self, node): # If we have inconsistent types, bail out. known = type(ast_nodes[0]) - if any(type(element) is not known + if any(not isinstance(element, known) for element in ast_nodes[1:]): return value = known().join(reversed(ast_nodes)) - newnode = nodes.Const(value) + newnode = nodes.Const(value, node.lineno, node.col_offset, parent) return newnode diff --git a/pymode/libs/astroid/bases.py b/pymode/libs/astroid/bases.py index 8dfa8126..aefbaa1a 100644 --- a/pymode/libs/astroid/bases.py +++ b/pymode/libs/astroid/bases.py @@ -1,39 +1,35 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """This module contains base classes and functions for the nodes and some inference utils. """ -import functools + +import collections import sys -import warnings -import wrapt +import six from astroid import context as contextmod -from astroid import decorators as decoratorsmod from astroid import exceptions from astroid import util +objectmodel = util.lazy_import('interpreter.objectmodel') +BUILTINS = six.moves.builtins.__name__ +manager = util.lazy_import('manager') +MANAGER = manager.AstroidManager() if sys.version_info >= (3, 0): BUILTINS = 'builtins' + BOOL_SPECIAL_METHOD = '__bool__' else: BUILTINS = '__builtin__' + BOOL_SPECIAL_METHOD = '__nonzero__' PROPERTIES = {BUILTINS + '.property', 'abc.abstractproperty'} # List of possible property names. We use this list in order # to see if a method is a property or not. This should be @@ -54,7 +50,7 @@ def _is_property(meth): if PROPERTIES.intersection(meth.decoratornames()): return True stripped = {name.split(".")[-1] for name in meth.decoratornames() - if name is not util.YES} + if name is not util.Uninferable} return any(name in stripped for name in POSSIBLE_PROPERTIES) @@ -90,7 +86,7 @@ def _infer_stmts(stmts, context, frame=None): context = contextmod.InferenceContext() for stmt in stmts: - if stmt is util.YES: + if stmt is util.Uninferable: yield stmt inferred = True continue @@ -99,36 +95,64 @@ def _infer_stmts(stmts, context, frame=None): for inferred in stmt.infer(context=context): yield inferred inferred = True - except exceptions.UnresolvableName: + except exceptions.NameInferenceError: continue except exceptions.InferenceError: - yield util.YES + yield util.Uninferable inferred = True if not inferred: - raise exceptions.InferenceError(str(stmt)) + raise exceptions.InferenceError( + 'Inference failed for all members of {stmts!r}.', + stmts=stmts, frame=frame, context=context) + + +def _infer_method_result_truth(instance, method_name, context): + # Get the method from the instance and try to infer + # its return's truth value. + meth = next(instance.igetattr(method_name, context=context), None) + if meth and hasattr(meth, 'infer_call_result'): + if not meth.callable(): + return util.Uninferable + for value in meth.infer_call_result(instance, context=context): + if value is util.Uninferable: + return value + + inferred = next(value.infer(context=context)) + return inferred.bool_value() + return util.Uninferable + + +class BaseInstance(Proxy): + """An instance base class, which provides lookup methods for potential instances.""" + special_attributes = None + + def display_type(self): + return 'Instance of' -class Instance(Proxy): - """a special node representing a class instance""" def getattr(self, name, context=None, lookupclass=True): try: values = self._proxied.instance_attr(name, context) - except exceptions.NotFoundError: - if name == '__class__': - return [self._proxied] + except exceptions.AttributeInferenceError: + if self.special_attributes and name in self.special_attributes: + return [self.special_attributes.lookup(name)] + if lookupclass: - # class attributes not available through the instance - # unless they are explicitly defined - if name in ('__name__', '__bases__', '__mro__', '__subclasses__'): - return self._proxied.local_attr(name) - return self._proxied.getattr(name, context) - raise exceptions.NotFoundError(name) + # Class attributes not available through the instance + # unless they are explicitly defined. + return self._proxied.getattr(name, context, + class_context=False) + + util.reraise(exceptions.AttributeInferenceError(target=self, + attribute=name, + context=context)) # since we've no context information, return matching class members as # well if lookupclass: try: - return values + self._proxied.getattr(name, context) - except exceptions.NotFoundError: + return values + self._proxied.getattr(name, context, + class_context=False) + except exceptions.AttributeInferenceError: pass return values @@ -138,22 +162,23 @@ def igetattr(self, name, context=None): context = contextmod.InferenceContext() try: # avoid recursively inferring the same attr on the same class - context.push((self._proxied, name)) + if context.push((self._proxied, name)): + return + # XXX frame should be self._proxied, or not ? get_attr = self.getattr(name, context, lookupclass=False) - return _infer_stmts( - self._wrap_attr(get_attr, context), - context, - frame=self, - ) - except exceptions.NotFoundError: + for stmt in _infer_stmts(self._wrap_attr(get_attr, context), + context, frame=self): + yield stmt + except exceptions.AttributeInferenceError: try: - # fallback to class'igetattr since it has some logic to handle + # fallback to class.igetattr since it has some logic to handle # descriptors - return self._wrap_attr(self._proxied.igetattr(name, context), - context) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) + attrs = self._proxied.igetattr(name, context, class_context=False) + for stmt in self._wrap_attr(attrs, context): + yield stmt + except exceptions.AttributeInferenceError as error: + util.reraise(exceptions.InferenceError(**vars(error))) def _wrap_attr(self, attrs, context=None): """wrap bound methods of attrs in a InstanceMethod proxies""" @@ -182,13 +207,21 @@ def infer_call_result(self, caller, context=None): """infer what a class instance is returning when called""" inferred = False for node in self._proxied.igetattr('__call__', context): - if node is util.YES or not node.callable(): + if node is util.Uninferable or not node.callable(): continue for res in node.infer_call_result(caller, context): inferred = True yield res if not inferred: - raise exceptions.InferenceError() + raise exceptions.InferenceError(node=self, caller=caller, + context=context) + + +class Instance(BaseInstance): + """A special node representing a class instance.""" + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.InstanceModel()) def __repr__(self): return '' % (self._proxied.root().name, @@ -200,9 +233,9 @@ def __str__(self): def callable(self): try: - self._proxied.getattr('__call__') + self._proxied.getattr('__call__', class_context=False) return True - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: return False def pytype(self): @@ -211,15 +244,45 @@ def pytype(self): def display_type(self): return 'Instance of' + def bool_value(self): + """Infer the truth value for an Instance + + The truth value of an instance is determined by these conditions: + + * if it implements __bool__ on Python 3 or __nonzero__ + on Python 2, then its bool value will be determined by + calling this special method and checking its result. + * when this method is not defined, __len__() is called, if it + is defined, and the object is considered true if its result is + nonzero. If a class defines neither __len__() nor __bool__(), + all its instances are considered true. + """ + context = contextmod.InferenceContext() + context.callcontext = contextmod.CallContext(args=[]) + context.boundnode = self + + try: + result = _infer_method_result_truth(self, BOOL_SPECIAL_METHOD, context) + except (exceptions.InferenceError, exceptions.AttributeInferenceError): + # Fallback to __len__. + try: + result = _infer_method_result_truth(self, '__len__', context) + except (exceptions.AttributeInferenceError, exceptions.InferenceError): + return True + return result # TODO(cpopa): this is set in inference.py # The circular dependency hell goes deeper and deeper. - # pylint: disable=unused-argument def getitem(self, index, context=None): pass + class UnboundMethod(Proxy): """a special node representing a method not bound to an instance""" + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.UnboundMethodModel()) + def __repr__(self): frame = self._proxied.parent.frame() return '<%s %s of %s at 0x%s' % (self.__class__.__name__, @@ -230,13 +293,13 @@ def is_bound(self): return False def getattr(self, name, context=None): - if name == 'im_func': - return [self._proxied] + if name in self.special_attributes: + return [self.special_attributes.lookup(name)] return self._proxied.getattr(name, context) def igetattr(self, name, context=None): - if name == 'im_func': - return iter((self._proxied,)) + if name in self.special_attributes: + return iter((self.special_attributes.lookup(name), )) return self._proxied.igetattr(name, context) def infer_call_result(self, caller, context): @@ -245,12 +308,19 @@ def infer_call_result(self, caller, context): if (self._proxied.name == '__new__' and self._proxied.parent.frame().qname() == '%s.object' % BUILTINS): infer = caller.args[0].infer() if caller.args else [] - return ((x is util.YES and x or Instance(x)) for x in infer) + return (Instance(x) if x is not util.Uninferable else x for x in infer) return self._proxied.infer_call_result(caller, context) + def bool_value(self): + return True + class BoundMethod(UnboundMethod): """a special node representing a method bound to an instance""" + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.BoundMethodModel()) + def __init__(self, proxy, bound): UnboundMethod.__init__(self, proxy) self.bound = bound @@ -258,20 +328,109 @@ def __init__(self, proxy, bound): def is_bound(self): return True - def infer_call_result(self, caller, context=None): + def _infer_type_new_call(self, caller, context): + """Try to infer what type.__new__(mcs, name, bases, attrs) returns. + In order for such call to be valid, the metaclass needs to be + a subtype of ``type``, the name needs to be a string, the bases + needs to be a tuple of classes and the attributes a dictionary + of strings to values. + """ + from astroid import node_classes + # Verify the metaclass + mcs = next(caller.args[0].infer(context=context)) + if mcs.__class__.__name__ != 'ClassDef': + # Not a valid first argument. + return + if not mcs.is_subtype_of("%s.type" % BUILTINS): + # Not a valid metaclass. + return + + # Verify the name + name = next(caller.args[1].infer(context=context)) + if name.__class__.__name__ != 'Const': + # Not a valid name, needs to be a const. + return + if not isinstance(name.value, str): + # Needs to be a string. + return + + # Verify the bases + bases = next(caller.args[2].infer(context=context)) + if bases.__class__.__name__ != 'Tuple': + # Needs to be a tuple. + return + inferred_bases = [next(elt.infer(context=context)) + for elt in bases.elts] + if any(base.__class__.__name__ != 'ClassDef' + for base in inferred_bases): + # All the bases needs to be Classes + return + + # Verify the attributes. + attrs = next(caller.args[3].infer(context=context)) + if attrs.__class__.__name__ != 'Dict': + # Needs to be a dictionary. + return + cls_locals = collections.defaultdict(list) + for key, value in attrs.items: + key = next(key.infer(context=context)) + value = next(value.infer(context=context)) + if key.__class__.__name__ != 'Const': + # Something invalid as an attribute. + return + if not isinstance(key.value, str): + # Not a proper attribute. + return + cls_locals[key.value].append(value) + + # Build the class from now. + cls = mcs.__class__(name=name.value, lineno=caller.lineno, + col_offset=caller.col_offset, + parent=caller) + empty = node_classes.Pass() + cls.postinit(bases=bases.elts, body=[empty], decorators=[], + newstyle=True, metaclass=mcs, keywords=[]) + cls.locals = cls_locals + return cls + + def infer_call_result(self, caller, context=None): if context is None: context = contextmod.InferenceContext() context = context.clone() context.boundnode = self.bound + + if (self.bound.__class__.__name__ == 'ClassDef' + and self.bound.name == 'type' + and self.name == '__new__' + and len(caller.args) == 4 + # TODO(cpopa): this check shouldn't be needed. + and self._proxied.parent.frame().qname() == '%s.object' % BUILTINS): + + # Check if we have an ``type.__new__(mcs, name, bases, attrs)`` call. + new_cls = self._infer_type_new_call(caller, context) + if new_cls: + return iter((new_cls, )) + return super(BoundMethod, self).infer_call_result(caller, context) + def bool_value(self): + return True + -class Generator(Instance): +class Generator(BaseInstance): """a special node representing a generator. Proxied class is set once for all in raw_building. """ + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.GeneratorModel()) + + # pylint: disable=super-init-not-called + def __init__(self, parent=None): + self.parent = parent + def callable(self): return False @@ -281,356 +440,11 @@ def pytype(self): def display_type(self): return 'Generator' + def bool_value(self): + return True + def __repr__(self): return '' % (self._proxied.name, self.lineno, id(self)) def __str__(self): return 'Generator(%s)' % (self._proxied.name) - - -# decorators ################################################################## - -def path_wrapper(func): - """return the given infer function wrapped to handle the path""" - @functools.wraps(func) - def wrapped(node, context=None, _func=func, **kwargs): - """wrapper function handling context""" - if context is None: - context = contextmod.InferenceContext() - context.push(node) - yielded = set() - for res in _func(node, context, **kwargs): - # unproxy only true instance, not const, tuple, dict... - if res.__class__ is Instance: - ares = res._proxied - else: - ares = res - if ares not in yielded: - yield res - yielded.add(ares) - return wrapped - -@wrapt.decorator -def yes_if_nothing_inferred(func, instance, args, kwargs): - inferred = False - for node in func(*args, **kwargs): - inferred = True - yield node - if not inferred: - yield util.YES - -@wrapt.decorator -def raise_if_nothing_inferred(func, instance, args, kwargs): - inferred = False - for node in func(*args, **kwargs): - inferred = True - yield node - if not inferred: - raise exceptions.InferenceError() - - -# Node ###################################################################### - -class NodeNG(object): - """Base Class for all Astroid node classes. - - It represents a node of the new abstract syntax tree. - """ - is_statement = False - optional_assign = False # True for For (and for Comprehension if py <3.0) - is_function = False # True for FunctionDef nodes - # attributes below are set by the builder module or by raw factories - lineno = None - fromlineno = None - tolineno = None - col_offset = None - # parent node in the tree - parent = None - # attributes containing child node(s) redefined in most concrete classes: - _astroid_fields = () - # instance specific inference function infer(node, context) - _explicit_inference = None - - def infer(self, context=None, **kwargs): - """main interface to the interface system, return a generator on infered - values. - - If the instance has some explicit inference function set, it will be - called instead of the default interface. - """ - if self._explicit_inference is not None: - # explicit_inference is not bound, give it self explicitly - try: - return self._explicit_inference(self, context, **kwargs) - except exceptions.UseInferenceDefault: - pass - - if not context: - return self._infer(context, **kwargs) - - key = (self, context.lookupname, - context.callcontext, context.boundnode) - if key in context.inferred: - return iter(context.inferred[key]) - - return context.cache_generator(key, self._infer(context, **kwargs)) - - def _repr_name(self): - """return self.name or self.attrname or '' for nice representation""" - return getattr(self, 'name', getattr(self, 'attrname', '')) - - def __str__(self): - return '%s(%s)' % (self.__class__.__name__, self._repr_name()) - - def __repr__(self): - return '<%s(%s) l.%s [%s] at 0x%x>' % (self.__class__.__name__, - self._repr_name(), - self.fromlineno, - self.root().name, - id(self)) - - - def accept(self, visitor): - func = getattr(visitor, "visit_" + self.__class__.__name__.lower()) - return func(self) - - def get_children(self): - for field in self._astroid_fields: - attr = getattr(self, field) - if attr is None: - continue - if isinstance(attr, (list, tuple)): - for elt in attr: - yield elt - else: - yield attr - - def last_child(self): - """an optimized version of list(get_children())[-1]""" - for field in self._astroid_fields[::-1]: - attr = getattr(self, field) - if not attr: # None or empty listy / tuple - continue - if isinstance(attr, (list, tuple)): - return attr[-1] - else: - return attr - return None - - def parent_of(self, node): - """return true if i'm a parent of the given node""" - parent = node.parent - while parent is not None: - if self is parent: - return True - parent = parent.parent - return False - - def statement(self): - """return the first parent node marked as statement node""" - if self.is_statement: - return self - return self.parent.statement() - - def frame(self): - """return the first parent frame node (i.e. Module, FunctionDef or - ClassDef) - - """ - return self.parent.frame() - - def scope(self): - """return the first node defining a new scope (i.e. Module, - FunctionDef, ClassDef, Lambda but also GenExpr) - - """ - return self.parent.scope() - - def root(self): - """return the root node of the tree, (i.e. a Module)""" - if self.parent: - return self.parent.root() - return self - - def child_sequence(self, child): - """search for the right sequence where the child lies in""" - for field in self._astroid_fields: - node_or_sequence = getattr(self, field) - if node_or_sequence is child: - return [node_or_sequence] - # /!\ compiler.ast Nodes have an __iter__ walking over child nodes - if (isinstance(node_or_sequence, (tuple, list)) - and child in node_or_sequence): - return node_or_sequence - - msg = 'Could not find %s in %s\'s children' - raise exceptions.AstroidError(msg % (repr(child), repr(self))) - - def locate_child(self, child): - """return a 2-uple (child attribute name, sequence or node)""" - for field in self._astroid_fields: - node_or_sequence = getattr(self, field) - # /!\ compiler.ast Nodes have an __iter__ walking over child nodes - if child is node_or_sequence: - return field, child - if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence: - return field, node_or_sequence - msg = 'Could not find %s in %s\'s children' - raise exceptions.AstroidError(msg % (repr(child), repr(self))) - # FIXME : should we merge child_sequence and locate_child ? locate_child - # is only used in are_exclusive, child_sequence one time in pylint. - - def next_sibling(self): - """return the next sibling statement""" - return self.parent.next_sibling() - - def previous_sibling(self): - """return the previous sibling statement""" - return self.parent.previous_sibling() - - def nearest(self, nodes): - """return the node which is the nearest before this one in the - given list of nodes - """ - myroot = self.root() - mylineno = self.fromlineno - nearest = None, 0 - for node in nodes: - assert node.root() is myroot, \ - 'nodes %s and %s are not from the same module' % (self, node) - lineno = node.fromlineno - if node.fromlineno > mylineno: - break - if lineno > nearest[1]: - nearest = node, lineno - # FIXME: raise an exception if nearest is None ? - return nearest[0] - - # these are lazy because they're relatively expensive to compute for every - # single node, and they rarely get looked at - - @decoratorsmod.cachedproperty - def fromlineno(self): - if self.lineno is None: - return self._fixed_source_line() - else: - return self.lineno - - @decoratorsmod.cachedproperty - def tolineno(self): - if not self._astroid_fields: - # can't have children - lastchild = None - else: - lastchild = self.last_child() - if lastchild is None: - return self.fromlineno - else: - return lastchild.tolineno - - # TODO / FIXME: - assert self.fromlineno is not None, self - assert self.tolineno is not None, self - - def _fixed_source_line(self): - """return the line number where the given node appears - - we need this method since not all nodes have the lineno attribute - correctly set... - """ - line = self.lineno - _node = self - try: - while line is None: - _node = next(_node.get_children()) - line = _node.lineno - except StopIteration: - _node = self.parent - while _node and line is None: - line = _node.lineno - _node = _node.parent - return line - - def block_range(self, lineno): - """handle block line numbers range for non block opening statements - """ - return lineno, self.tolineno - - def set_local(self, name, stmt): - """delegate to a scoped parent handling a locals dictionary""" - self.parent.set_local(name, stmt) - - def nodes_of_class(self, klass, skip_klass=None): - """return an iterator on nodes which are instance of the given class(es) - - klass may be a class object or a tuple of class objects - """ - if isinstance(self, klass): - yield self - for child_node in self.get_children(): - if skip_klass is not None and isinstance(child_node, skip_klass): - continue - for matching in child_node.nodes_of_class(klass, skip_klass): - yield matching - - def _infer_name(self, frame, name): - # overridden for ImportFrom, Import, Global, TryExcept and Arguments - return None - - def _infer(self, context=None): - """we don't know how to resolve a statement by default""" - # this method is overridden by most concrete classes - raise exceptions.InferenceError(self.__class__.__name__) - - def inferred(self): - '''return list of inferred values for a more simple inference usage''' - return list(self.infer()) - - def infered(self): - warnings.warn('%s.infered() is deprecated and slated for removal ' - 'in astroid 2.0, use %s.inferred() instead.' - % (type(self).__name__, type(self).__name__), - PendingDeprecationWarning, stacklevel=2) - return self.inferred() - - def instanciate_class(self): - """instanciate a node if it is a ClassDef node, else return self""" - return self - - def has_base(self, node): - return False - - def callable(self): - return False - - def eq(self, value): - return False - - def as_string(self): - from astroid.as_string import to_code - return to_code(self) - - def repr_tree(self, ids=False): - from astroid.as_string import dump - return dump(self) - - -class Statement(NodeNG): - """Statement node adding a few attributes""" - is_statement = True - - def next_sibling(self): - """return the next sibling statement""" - stmts = self.parent.child_sequence(self) - index = stmts.index(self) - try: - return stmts[index +1] - except IndexError: - pass - - def previous_sibling(self): - """return the previous sibling statement""" - stmts = self.parent.child_sequence(self) - index = stmts.index(self) - if index >= 1: - return stmts[index -1] diff --git a/pymode/libs/astroid/brain/brain_builtin_inference.py b/pymode/libs/astroid/brain/brain_builtin_inference.py index ed78111f..717dc78c 100644 --- a/pymode/libs/astroid/brain/brain_builtin_inference.py +++ b/pymode/libs/astroid/brain/brain_builtin_inference.py @@ -1,16 +1,24 @@ +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for various builtins.""" -import sys from functools import partial +import sys from textwrap import dedent import six -from astroid import (MANAGER, UseInferenceDefault, - inference_tip, YES, InferenceError, UnresolvableName) +from astroid import (MANAGER, UseInferenceDefault, AttributeInferenceError, + inference_tip, InferenceError, NameInferenceError) from astroid import arguments +from astroid.builder import AstroidBuilder +from astroid import helpers from astroid import nodes from astroid import objects -from astroid.builder import AstroidBuilder +from astroid import scoped_nodes from astroid import util def _extend_str(class_node, rvalue): @@ -62,7 +70,7 @@ def ljust(self, width, fillchar=None): code = code.format(rvalue=rvalue) fake = AstroidBuilder(MANAGER).string_build(code)['whatever'] for method in fake.mymethods(): - class_node._locals[method.name] = [method] + class_node.locals[method.name] = [method] method.parent = class_node def extend_builtins(class_transforms): @@ -118,10 +126,10 @@ def _generic_inference(node, context, node_type, transform): inferred = next(arg.infer(context=context)) except (InferenceError, StopIteration): raise UseInferenceDefault() - if inferred is util.YES: + if inferred is util.Uninferable: raise UseInferenceDefault() transformed = transform(inferred) - if not transformed or transformed is util.YES: + if not transformed or transformed is util.Uninferable: raise UseInferenceDefault() return transformed @@ -146,7 +154,7 @@ def _generic_transform(arg, klass, iterables, build_elts): elts = arg.value else: return - return klass(elts=build_elts(elts)) + return klass.from_constants(elts=build_elts(elts)) def _infer_builtin(node, context, @@ -164,25 +172,31 @@ def _infer_builtin(node, context, infer_tuple = partial( _infer_builtin, klass=nodes.Tuple, - iterables=(nodes.List, nodes.Set), + iterables=(nodes.List, nodes.Set, objects.FrozenSet, + objects.DictItems, objects.DictKeys, + objects.DictValues), build_elts=tuple) infer_list = partial( _infer_builtin, klass=nodes.List, - iterables=(nodes.Tuple, nodes.Set), + iterables=(nodes.Tuple, nodes.Set, objects.FrozenSet, + objects.DictItems, objects.DictKeys, + objects.DictValues), build_elts=list) infer_set = partial( _infer_builtin, klass=nodes.Set, - iterables=(nodes.List, nodes.Tuple), + iterables=(nodes.List, nodes.Tuple, objects.FrozenSet, + objects.DictKeys), build_elts=set) infer_frozenset = partial( _infer_builtin, klass=objects.FrozenSet, - iterables=(nodes.List, nodes.Tuple, nodes.Set), + iterables=(nodes.List, nodes.Tuple, nodes.Set, objects.FrozenSet, + objects.DictKeys), build_elts=frozenset) @@ -191,7 +205,7 @@ def _get_elts(arg, context): (nodes.List, nodes.Tuple, nodes.Set)) try: inferred = next(arg.infer(context)) - except (InferenceError, UnresolvableName): + except (InferenceError, NameInferenceError): raise UseInferenceDefault() if isinstance(inferred, nodes.Dict): items = inferred.items @@ -251,19 +265,11 @@ def infer_dict(node, context=None): else: raise UseInferenceDefault() - empty = nodes.Dict() - empty.items = items - return empty - - -def _node_class(node): - klass = node.frame() - while klass is not None and not isinstance(klass, nodes.ClassDef): - if klass.parent is None: - klass = None - else: - klass = klass.parent.frame() - return klass + value = nodes.Dict(col_offset=node.col_offset, + lineno=node.lineno, + parent=node.parent) + value.postinit(items) + return value def infer_super(node, context=None): @@ -276,7 +282,7 @@ def infer_super(node, context=None): * if the super call is not inside a function (classmethod or method), then the default inference will be used. - * if the super arguments can't be infered, the default inference + * if the super arguments can't be inferred, the default inference will be used. """ if len(node.args) == 1: @@ -291,7 +297,7 @@ def infer_super(node, context=None): # Not interested in staticmethods. raise UseInferenceDefault - cls = _node_class(scope) + cls = scoped_nodes.get_wrapping_class(scope) if not len(node.args): mro_pointer = cls # In we are in a classmethod, the interpreter will fill @@ -311,7 +317,7 @@ def infer_super(node, context=None): except InferenceError: raise UseInferenceDefault - if mro_pointer is YES or mro_type is YES: + if mro_pointer is util.Uninferable or mro_type is util.Uninferable: # No way we could understand this. raise UseInferenceDefault @@ -320,17 +326,171 @@ def infer_super(node, context=None): self_class=cls, scope=scope) super_obj.parent = node - return iter([super_obj]) + return super_obj -# Builtins inference -MANAGER.register_transform(nodes.Call, - inference_tip(infer_super), - lambda n: (isinstance(n.func, nodes.Name) and - n.func.name == 'super')) +def _infer_getattr_args(node, context): + if len(node.args) not in (2, 3): + # Not a valid getattr call. + raise UseInferenceDefault + + try: + # TODO(cpopa): follow all the values of the first argument? + obj = next(node.args[0].infer(context=context)) + attr = next(node.args[1].infer(context=context)) + except InferenceError: + raise UseInferenceDefault + + if obj is util.Uninferable or attr is util.Uninferable: + # If one of the arguments is something we can't infer, + # then also make the result of the getattr call something + # which is unknown. + return util.Uninferable, util.Uninferable + + is_string = (isinstance(attr, nodes.Const) and + isinstance(attr.value, six.string_types)) + if not is_string: + raise UseInferenceDefault + + return obj, attr.value + + +def infer_getattr(node, context=None): + """Understand getattr calls + + If one of the arguments is an Uninferable object, then the + result will be an Uninferable object. Otherwise, the normal attribute + lookup will be done. + """ + obj, attr = _infer_getattr_args(node, context) + if obj is util.Uninferable or attr is util.Uninferable or not hasattr(obj, 'igetattr'): + return util.Uninferable + + try: + return next(obj.igetattr(attr, context=context)) + except (StopIteration, InferenceError, AttributeInferenceError): + if len(node.args) == 3: + # Try to infer the default and return it instead. + try: + return next(node.args[2].infer(context=context)) + except InferenceError: + raise UseInferenceDefault + + raise UseInferenceDefault + + +def infer_hasattr(node, context=None): + """Understand hasattr calls + + This always guarantees three possible outcomes for calling + hasattr: Const(False) when we are sure that the object + doesn't have the intended attribute, Const(True) when + we know that the object has the attribute and Uninferable + when we are unsure of the outcome of the function call. + """ + try: + obj, attr = _infer_getattr_args(node, context) + if obj is util.Uninferable or attr is util.Uninferable or not hasattr(obj, 'getattr'): + return util.Uninferable + obj.getattr(attr, context=context) + except UseInferenceDefault: + # Can't infer something from this function call. + return util.Uninferable + except AttributeInferenceError: + # Doesn't have it. + return nodes.Const(False) + return nodes.Const(True) + + +def infer_callable(node, context=None): + """Understand callable calls + + This follows Python's semantics, where an object + is callable if it provides an attribute __call__, + even though that attribute is something which can't be + called. + """ + if len(node.args) != 1: + # Invalid callable call. + raise UseInferenceDefault + + argument = node.args[0] + try: + inferred = next(argument.infer(context=context)) + except InferenceError: + return util.Uninferable + if inferred is util.Uninferable: + return util.Uninferable + return nodes.Const(inferred.callable()) + + +def infer_bool(node, context=None): + """Understand bool calls.""" + if len(node.args) > 1: + # Invalid bool call. + raise UseInferenceDefault + + if not node.args: + return nodes.Const(False) + + argument = node.args[0] + try: + inferred = next(argument.infer(context=context)) + except InferenceError: + return util.Uninferable + if inferred is util.Uninferable: + return util.Uninferable + + bool_value = inferred.bool_value() + if bool_value is util.Uninferable: + return util.Uninferable + return nodes.Const(bool_value) + + +def infer_type(node, context=None): + """Understand the one-argument form of *type*.""" + if len(node.args) != 1: + raise UseInferenceDefault + return helpers.object_type(node.args[0], context) + + +def infer_slice(node, context=None): + """Understand `slice` calls.""" + args = node.args + if not 0 < len(args) <= 3: + raise UseInferenceDefault + + args = list(map(helpers.safe_infer, args)) + for arg in args: + if not arg or arg is util.Uninferable: + raise UseInferenceDefault + if not isinstance(arg, nodes.Const): + raise UseInferenceDefault + if not isinstance(arg.value, (type(None), int)): + raise UseInferenceDefault + + if len(args) < 3: + # Make sure we have 3 arguments. + args.extend([None] * (3 - len(args))) + + slice_node = nodes.Slice(lineno=node.lineno, + col_offset=node.col_offset, + parent=node.parent) + slice_node.postinit(*args) + return slice_node + + +# Builtins inference +register_builtin_transform(infer_bool, 'bool') +register_builtin_transform(infer_super, 'super') +register_builtin_transform(infer_callable, 'callable') +register_builtin_transform(infer_getattr, 'getattr') +register_builtin_transform(infer_hasattr, 'hasattr') register_builtin_transform(infer_tuple, 'tuple') register_builtin_transform(infer_set, 'set') register_builtin_transform(infer_list, 'list') register_builtin_transform(infer_dict, 'dict') register_builtin_transform(infer_frozenset, 'frozenset') +register_builtin_transform(infer_type, 'type') +register_builtin_transform(infer_slice, 'slice') diff --git a/pymode/libs/astroid/brain/brain_collections.py b/pymode/libs/astroid/brain/brain_collections.py new file mode 100644 index 00000000..77343377 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_collections.py @@ -0,0 +1,43 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import astroid + + +def _collections_transform(): + return astroid.parse(''' + class defaultdict(dict): + default_factory = None + def __missing__(self, key): pass + def __getitem__(self, key): return default_factory + + class deque(object): + maxlen = 0 + def __init__(self, iterable=None, maxlen=None): + self.iterable = iterable + def append(self, x): pass + def appendleft(self, x): pass + def clear(self): pass + def count(self, x): return 0 + def extend(self, iterable): pass + def extendleft(self, iterable): pass + def pop(self): pass + def popleft(self): pass + def remove(self, value): pass + def reverse(self): pass + def rotate(self, n): pass + def __iter__(self): return self + def __reversed__(self): return self.iterable[::-1] + def __getitem__(self, index): pass + def __setitem__(self, index, value): pass + def __delitem__(self, index): pass + + def OrderedDict(dict): + def __reversed__(self): return self[::-1] + ''') + + +astroid.register_module_extender(astroid.MANAGER, 'collections', _collections_transform) + diff --git a/pymode/libs/astroid/brain/brain_dateutil.py b/pymode/libs/astroid/brain/brain_dateutil.py index d077327b..e9aafd25 100644 --- a/pymode/libs/astroid/brain/brain_dateutil.py +++ b/pymode/libs/astroid/brain/brain_dateutil.py @@ -1,3 +1,9 @@ +# Copyright (c) 2015-2016 Claudiu Popa +# Copyright (c) 2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for dateutil""" import textwrap diff --git a/pymode/libs/astroid/brain/brain_fstrings.py b/pymode/libs/astroid/brain/brain_fstrings.py new file mode 100644 index 00000000..e4c93571 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_fstrings.py @@ -0,0 +1,61 @@ +# Copyright (c) 2017 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import sys + +import astroid + + +def _clone_node_with_lineno(node, parent, lineno): + cls = node.__class__ + other_fields = node._other_fields + _astroid_fields = node._astroid_fields + init_params = { + 'lineno': lineno, + 'col_offset': node.col_offset, + 'parent': parent + } + postinit_params = { + param: getattr(node, param) + for param in _astroid_fields + } + if other_fields: + init_params.update({ + param: getattr(node, param) + for param in other_fields + }) + new_node = cls(**init_params) + if hasattr(node, 'postinit'): + new_node.postinit(**postinit_params) + return new_node + + +def _transform_formatted_value(node): + if node.value and node.value.lineno == 1: + if node.lineno != node.value.lineno: + new_node = astroid.FormattedValue( + lineno=node.lineno, + col_offset=node.col_offset, + parent=node.parent + ) + new_value = _clone_node_with_lineno( + node=node.value, + lineno=node.lineno, + parent=new_node + ) + new_node.postinit(value=new_value, + format_spec=node.format_spec) + return new_node + + +if sys.version_info[:2] >= (3, 6): + # TODO: this fix tries to *patch* http://bugs.python.org/issue29051 + # The problem is that FormattedValue.value, which is a Name node, + # has wrong line numbers, usually 1. This creates problems for pylint, + # which expects correct line numbers for things such as message control. + astroid.MANAGER.register_transform( + astroid.FormattedValue, + _transform_formatted_value) + diff --git a/pymode/libs/astroid/brain/brain_functools.py b/pymode/libs/astroid/brain/brain_functools.py new file mode 100644 index 00000000..6dcf7cd9 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_functools.py @@ -0,0 +1,75 @@ +# Copyright (c) 2016 Claudiu Popa + +"""Astroid hooks for understanding functools library module.""" + +import astroid +from astroid import BoundMethod +from astroid import extract_node +from astroid import helpers +from astroid.interpreter import objectmodel +from astroid import MANAGER + + +LRU_CACHE = 'functools.lru_cache' + + +class LruWrappedModel(objectmodel.FunctionModel): + """Special attribute model for functions decorated with functools.lru_cache. + + The said decorators patches at decoration time some functions onto + the decorated function. + """ + + @property + def py__wrapped__(self): + return self._instance + + @property + def pycache_info(self): + cache_info = extract_node(''' + from functools import _CacheInfo + _CacheInfo(0, 0, 0, 0) + ''') + class CacheInfoBoundMethod(BoundMethod): + def infer_call_result(self, caller, context=None): + yield helpers.safe_infer(cache_info) + + return CacheInfoBoundMethod(proxy=self._instance, bound=self._instance) + + @property + def pycache_clear(self): + node = extract_node('''def cache_clear(self): pass''') + return BoundMethod(proxy=node, bound=self._instance.parent.scope()) + + +def _transform_lru_cache(node, context=None): + # TODO: this is not ideal, since the node should be immutable, + # but due to https://github.com/PyCQA/astroid/issues/354, + # there's not much we can do now. + # Replacing the node would work partially, because, + # in pylint, the old node would still be available, leading + # to spurious false positives. + node.special_attributes = LruWrappedModel()(node) + return + + +def _looks_like_lru_cache(node): + """Check if the given function node is decorated with lru_cache.""" + if not node.decorators: + return False + + for decorator in node.decorators.nodes: + if not isinstance(decorator, astroid.Call): + continue + + func = helpers.safe_infer(decorator.func) + if func in (None, astroid.Uninferable): + continue + + if isinstance(func, astroid.FunctionDef) and func.qname() == LRU_CACHE: + return True + return False + + +MANAGER.register_transform(astroid.FunctionDef, _transform_lru_cache, + _looks_like_lru_cache) diff --git a/pymode/libs/astroid/brain/brain_gi.py b/pymode/libs/astroid/brain/brain_gi.py index d9fc1b45..03c19c0a 100644 --- a/pymode/libs/astroid/brain/brain_gi.py +++ b/pymode/libs/astroid/brain/brain_gi.py @@ -1,3 +1,8 @@ +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for the Python 2 GObject introspection bindings. Helps with understanding everything imported from 'gi.repository' @@ -9,7 +14,7 @@ import re import warnings -from astroid import MANAGER, AstroidBuildingException, nodes +from astroid import MANAGER, AstroidBuildingError, nodes from astroid.builder import AstroidBuilder @@ -64,7 +69,7 @@ def _gi_build_stub(parent): ret = "" if constants: - ret += "# %s contants\n\n" % parent.__name__ + ret += "# %s constants\n\n" % parent.__name__ for name in sorted(constants): if name[0].isdigit(): # GDK has some busted constant names like @@ -114,7 +119,7 @@ def _gi_build_stub(parent): def _import_gi_module(modname): # we only consider gi.repository submodules if not modname.startswith('gi.repository.'): - raise AstroidBuildingException() + raise AstroidBuildingError(modname=modname) # build astroid representation unless we already tried so if modname not in _inspected_modules: modnames = [modname] @@ -133,16 +138,17 @@ def _import_gi_module(modname): modcode = '' for m in itertools.chain(modnames, optional_modnames): try: - __import__(m) with warnings.catch_warnings(): # Just inspecting the code can raise gi deprecation # warnings, so ignore them. try: - from gi import PyGIDeprecationWarning + from gi import PyGIDeprecationWarning, PyGIWarning warnings.simplefilter("ignore", PyGIDeprecationWarning) + warnings.simplefilter("ignore", PyGIWarning) except Exception: pass + __import__(m) modcode += _gi_build_stub(sys.modules[m]) except ImportError: if m not in optional_modnames: @@ -155,7 +161,7 @@ def _import_gi_module(modname): else: astng = _inspected_modules[modname] if astng is None: - raise AstroidBuildingException('Failed to import module %r' % modname) + raise AstroidBuildingError(modname=modname) return astng def _looks_like_require_version(node): diff --git a/pymode/libs/astroid/brain/brain_hashlib.py b/pymode/libs/astroid/brain/brain_hashlib.py new file mode 100644 index 00000000..aacd1743 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_hashlib.py @@ -0,0 +1,40 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import six + +import astroid + + +def _hashlib_transform(): + template = ''' + class %(name)s(object): + def __init__(self, value=''): pass + def digest(self): + return %(digest)s + def copy(self): + return self + def update(self, value): pass + def hexdigest(self): + return '' + @property + def name(self): + return %(name)r + @property + def block_size(self): + return 1 + @property + def digest_size(self): + return 1 + ''' + algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') + classes = "".join( + template % {'name': hashfunc, 'digest': 'b""' if six.PY3 else '""'} + for hashfunc in algorithms) + return astroid.parse(classes) + + +astroid.register_module_extender(astroid.MANAGER, 'hashlib', _hashlib_transform) + diff --git a/pymode/libs/astroid/brain/brain_io.py b/pymode/libs/astroid/brain/brain_io.py new file mode 100644 index 00000000..be8d30c8 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_io.py @@ -0,0 +1,43 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +'''Astroid brain hints for some of the _io C objects.''' + +import astroid + + +BUFFERED = {'BufferedWriter', 'BufferedReader'} +TextIOWrapper = 'TextIOWrapper' +FileIO = 'FileIO' +BufferedWriter = 'BufferedWriter' + + +def _generic_io_transform(node, name, cls): + '''Transform the given name, by adding the given *class* as a member of the node.''' + + io_module = astroid.MANAGER.ast_from_module_name('_io') + attribute_object = io_module[cls] + instance = attribute_object.instantiate_class() + node.locals[name] = [instance] + + +def _transform_text_io_wrapper(node): + # This is not always correct, since it can vary with the type of the descriptor, + # being stdout, stderr or stdin. But we cannot get access to the name of the + # stream, which is why we are using the BufferedWriter class as a default + # value + return _generic_io_transform(node, name='buffer', cls=BufferedWriter) + + +def _transform_buffered(node): + return _generic_io_transform(node, name='raw', cls=FileIO) + + +astroid.MANAGER.register_transform(astroid.ClassDef, + _transform_buffered, + lambda node: node.name in BUFFERED) +astroid.MANAGER.register_transform(astroid.ClassDef, + _transform_text_io_wrapper, + lambda node: node.name == TextIOWrapper) diff --git a/pymode/libs/astroid/brain/brain_mechanize.py b/pymode/libs/astroid/brain/brain_mechanize.py index 20a253a4..afc65059 100644 --- a/pymode/libs/astroid/brain/brain_mechanize.py +++ b/pymode/libs/astroid/brain/brain_mechanize.py @@ -1,3 +1,8 @@ +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + from astroid import MANAGER, register_module_extender from astroid.builder import AstroidBuilder diff --git a/pymode/libs/astroid/brain/brain_multiprocessing.py b/pymode/libs/astroid/brain/brain_multiprocessing.py new file mode 100644 index 00000000..a19bac69 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_multiprocessing.py @@ -0,0 +1,104 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import sys + +import astroid +from astroid import exceptions + + +PY34 = sys.version_info >= (3, 4) + + +def _multiprocessing_transform(): + module = astroid.parse(''' + from multiprocessing.managers import SyncManager + def Manager(): + return SyncManager() + ''') + if not PY34: + return module + + # On Python 3.4, multiprocessing uses a getattr lookup inside contexts, + # in order to get the attributes they need. Since it's extremely + # dynamic, we use this approach to fake it. + node = astroid.parse(''' + from multiprocessing.context import DefaultContext, BaseContext + default = DefaultContext() + base = BaseContext() + ''') + try: + context = next(node['default'].infer()) + base = next(node['base'].infer()) + except exceptions.InferenceError: + return module + + for node in (context, base): + for key, value in node.locals.items(): + if key.startswith("_"): + continue + + value = value[0] + if isinstance(value, astroid.FunctionDef): + # We need to rebound this, since otherwise + # it will have an extra argument (self). + value = astroid.BoundMethod(value, node) + module[key] = value + return module + + +def _multiprocessing_managers_transform(): + return astroid.parse(''' + import array + import threading + import multiprocessing.pool as pool + + import six + + class Namespace(object): + pass + + class Value(object): + def __init__(self, typecode, value, lock=True): + self._typecode = typecode + self._value = value + def get(self): + return self._value + def set(self, value): + self._value = value + def __repr__(self): + return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value) + value = property(get, set) + + def Array(typecode, sequence, lock=True): + return array.array(typecode, sequence) + + class SyncManager(object): + Queue = JoinableQueue = six.moves.queue.Queue + Event = threading.Event + RLock = threading.RLock + BoundedSemaphore = threading.BoundedSemaphore + Condition = threading.Condition + Barrier = threading.Barrier + Pool = pool.Pool + list = list + dict = dict + Value = Value + Array = Array + Namespace = Namespace + __enter__ = lambda self: self + __exit__ = lambda *args: args + + def start(self, initializer=None, initargs=None): + pass + def shutdown(self): + pass + ''') + + +astroid.register_module_extender(astroid.MANAGER, 'multiprocessing.managers', + _multiprocessing_managers_transform) +astroid.register_module_extender(astroid.MANAGER, 'multiprocessing', + _multiprocessing_transform) diff --git a/pymode/libs/astroid/brain/brain_namedtuple_enum.py b/pymode/libs/astroid/brain/brain_namedtuple_enum.py new file mode 100644 index 00000000..b99cb761 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_namedtuple_enum.py @@ -0,0 +1,233 @@ +# Copyright (c) 2012-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +"""Astroid hooks for the Python standard library.""" + +import functools +import sys +import keyword +from textwrap import dedent + +from astroid import ( + MANAGER, UseInferenceDefault, inference_tip, + InferenceError) +from astroid import arguments +from astroid import exceptions +from astroid import nodes +from astroid.builder import AstroidBuilder, extract_node +from astroid import util + +PY3K = sys.version_info > (3, 0) +PY33 = sys.version_info >= (3, 3) +PY34 = sys.version_info >= (3, 4) + +# general function + +def infer_func_form(node, base_type, context=None, enum=False): + """Specific inference function for namedtuple or Python 3 enum. """ + def infer_first(node): + if node is util.Uninferable: + raise UseInferenceDefault + try: + value = next(node.infer(context=context)) + if value is util.Uninferable: + raise UseInferenceDefault() + else: + return value + except StopIteration: + raise InferenceError() + + # node is a Call node, class name as first argument and generated class + # attributes as second argument + if len(node.args) != 2: + # something weird here, go back to class implementation + raise UseInferenceDefault() + # namedtuple or enums list of attributes can be a list of strings or a + # whitespace-separate string + try: + name = infer_first(node.args[0]).value + names = infer_first(node.args[1]) + try: + attributes = names.value.replace(',', ' ').split() + except AttributeError: + if not enum: + attributes = [infer_first(const).value for const in names.elts] + else: + # Enums supports either iterator of (name, value) pairs + # or mappings. + # TODO: support only list, tuples and mappings. + if hasattr(names, 'items') and isinstance(names.items, list): + attributes = [infer_first(const[0]).value + for const in names.items + if isinstance(const[0], nodes.Const)] + elif hasattr(names, 'elts'): + # Enums can support either ["a", "b", "c"] + # or [("a", 1), ("b", 2), ...], but they can't + # be mixed. + if all(isinstance(const, nodes.Tuple) + for const in names.elts): + attributes = [infer_first(const.elts[0]).value + for const in names.elts + if isinstance(const, nodes.Tuple)] + else: + attributes = [infer_first(const).value + for const in names.elts] + else: + raise AttributeError + if not attributes: + raise AttributeError + except (AttributeError, exceptions.InferenceError): + raise UseInferenceDefault() + + # If we can't infer the name of the class, don't crash, up to this point + # we know it is a namedtuple anyway. + name = name or 'Uninferable' + # we want to return a Class node instance with proper attributes set + class_node = nodes.ClassDef(name, 'docstring') + class_node.parent = node.parent + # set base class=tuple + class_node.bases.append(base_type) + # XXX add __init__(*attributes) method + for attr in attributes: + fake_node = nodes.EmptyNode() + fake_node.parent = class_node + fake_node.attrname = attr + class_node.instance_attrs[attr] = [fake_node] + return class_node, name, attributes + + +def _looks_like(node, name): + func = node.func + if isinstance(func, nodes.Attribute): + return func.attrname == name + if isinstance(func, nodes.Name): + return func.name == name + return False + +_looks_like_namedtuple = functools.partial(_looks_like, name='namedtuple') +_looks_like_enum = functools.partial(_looks_like, name='Enum') + + +def infer_named_tuple(node, context=None): + """Specific inference function for namedtuple Call node""" + class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied, + context=context) + call_site = arguments.CallSite.from_call(node) + func = next(extract_node('import collections; collections.namedtuple').infer()) + try: + rename = next(call_site.infer_argument(func, 'rename', context)).bool_value() + except InferenceError: + rename = False + + if rename: + attributes = _get_renamed_namedtuple_atributes(attributes) + + field_def = (" {name} = property(lambda self: self[{index:d}], " + "doc='Alias for field number {index:d}')") + field_defs = '\n'.join(field_def.format(name=name, index=index) + for index, name in enumerate(attributes)) + fake = AstroidBuilder(MANAGER).string_build(''' +class %(name)s(tuple): + __slots__ = () + _fields = %(fields)r + def _asdict(self): + return self.__dict__ + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + return new(cls, iterable) + def _replace(self, **kwds): + return self + def __getnewargs__(self): + return tuple(self) +%(field_defs)s + ''' % {'name': name, 'fields': attributes, 'field_defs': field_defs}) + class_node.locals['_asdict'] = fake.body[0].locals['_asdict'] + class_node.locals['_make'] = fake.body[0].locals['_make'] + class_node.locals['_replace'] = fake.body[0].locals['_replace'] + class_node.locals['_fields'] = fake.body[0].locals['_fields'] + for attr in attributes: + class_node.locals[attr] = fake.body[0].locals[attr] + # we use UseInferenceDefault, we can't be a generator so return an iterator + return iter([class_node]) + + +def _get_renamed_namedtuple_atributes(field_names): + names = list(field_names) + seen = set() + for i, name in enumerate(field_names): + if (not all(c.isalnum() or c == '_' for c in name) or keyword.iskeyword(name) + or not name or name[0].isdigit() or name.startswith('_') or name in seen): + names[i] = '_%d' % i + seen.add(name) + return tuple(names) + + +def infer_enum(node, context=None): + """ Specific inference function for enum Call node. """ + enum_meta = extract_node(''' + class EnumMeta(object): + 'docstring' + def __call__(self, node): + class EnumAttribute(object): + name = '' + value = 0 + return EnumAttribute() + ''') + class_node = infer_func_form(node, enum_meta, + context=context, enum=True)[0] + return iter([class_node.instantiate_class()]) + + +def infer_enum_class(node): + """ Specific inference for enums. """ + names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum')) + for basename in node.basenames: + # TODO: doesn't handle subclasses yet. This implementation + # is a hack to support enums. + if basename not in names: + continue + if node.root().name == 'enum': + # Skip if the class is directly from enum module. + break + for local, values in node.locals.items(): + if any(not isinstance(value, nodes.AssignName) + for value in values): + continue + + stmt = values[0].statement() + if isinstance(stmt.targets[0], nodes.Tuple): + targets = stmt.targets[0].itered() + else: + targets = stmt.targets + + new_targets = [] + for target in targets: + # Replace all the assignments with our mocked class. + classdef = dedent(''' + class %(name)s(%(types)s): + @property + def value(self): + # Not the best return. + return None + @property + def name(self): + return %(name)r + ''' % {'name': target.name, 'types': ', '.join(node.basenames)}) + fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name] + fake.parent = target.parent + for method in node.mymethods(): + fake.locals[method.name] = [method] + new_targets.append(fake.instantiate_class()) + node.locals[local] = new_targets + break + return node + + +MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple), + _looks_like_namedtuple) +MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), + _looks_like_enum) +MANAGER.register_transform(nodes.ClassDef, infer_enum_class) diff --git a/pymode/libs/astroid/brain/brain_nose.py b/pymode/libs/astroid/brain/brain_nose.py index 4b077843..cc8939bd 100644 --- a/pymode/libs/astroid/brain/brain_nose.py +++ b/pymode/libs/astroid/brain/brain_nose.py @@ -1,20 +1,8 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Hooks for nose library.""" @@ -55,7 +43,7 @@ class Test(unittest.TestCase): def _nose_tools_transform(node): for method_name, method in _nose_tools_functions(): - node._locals[method_name] = [method] + node.locals[method_name] = [method] def _nose_tools_trivial_transform(): diff --git a/pymode/libs/astroid/brain/brain_numpy.py b/pymode/libs/astroid/brain/brain_numpy.py index 75f4f18f..8acfe053 100644 --- a/pymode/libs/astroid/brain/brain_numpy.py +++ b/pymode/libs/astroid/brain/brain_numpy.py @@ -1,20 +1,8 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# astroid 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 Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for numpy.""" diff --git a/pymode/libs/astroid/brain/brain_pkg_resources.py b/pymode/libs/astroid/brain/brain_pkg_resources.py new file mode 100644 index 00000000..bd60ecd3 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_pkg_resources.py @@ -0,0 +1,70 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + + +import astroid +from astroid import parse +from astroid import inference_tip +from astroid import register_module_extender +from astroid import MANAGER + + +def pkg_resources_transform(): + return parse(''' +def require(*requirements): + return pkg_resources.working_set.require(*requirements) + +def run_script(requires, script_name): + return pkg_resources.working_set.run_script(requires, script_name) + +def iter_entry_points(group, name=None): + return pkg_resources.working_set.iter_entry_points(group, name) + +def resource_exists(package_or_requirement, resource_name): + return get_provider(package_or_requirement).has_resource(resource_name) + +def resource_isdir(package_or_requirement, resource_name): + return get_provider(package_or_requirement).resource_isdir( + resource_name) + +def resource_filename(package_or_requirement, resource_name): + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name) + +def resource_stream(package_or_requirement, resource_name): + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name) + +def resource_string(package_or_requirement, resource_name): + return get_provider(package_or_requirement).get_resource_string( + self, resource_name) + +def resource_listdir(package_or_requirement, resource_name): + return get_provider(package_or_requirement).resource_listdir( + resource_name) + +def extraction_error(): + pass + +def get_cache_path(archive_name, names=()): + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name+'-tmp', *names) + return target_path + +def postprocess(tempname, filename): + pass + +def set_extraction_path(path): + pass + +def cleanup_resources(force=False): + pass + +def get_distribution(dist): + return Distribution(dist) + +''') + +register_module_extender(MANAGER, 'pkg_resources', pkg_resources_transform) diff --git a/pymode/libs/astroid/brain/brain_pytest.py b/pymode/libs/astroid/brain/brain_pytest.py index 1859b985..23e2db8e 100644 --- a/pymode/libs/astroid/brain/brain_pytest.py +++ b/pymode/libs/astroid/brain/brain_pytest.py @@ -1,3 +1,9 @@ +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for pytest.""" from __future__ import absolute_import from astroid import MANAGER, register_module_extender diff --git a/pymode/libs/astroid/brain/brain_qt.py b/pymode/libs/astroid/brain/brain_qt.py index 1a03b2be..bb1565fe 100644 --- a/pymode/libs/astroid/brain/brain_qt.py +++ b/pymode/libs/astroid/brain/brain_qt.py @@ -1,3 +1,8 @@ +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for the PyQT library.""" from astroid import MANAGER, register_module_extender @@ -7,9 +12,13 @@ def _looks_like_signal(node, signal_name='pyqtSignal'): - if '__class__' in node._instance_attrs: - cls = node._instance_attrs['__class__'][0] - return cls.name == signal_name + if '__class__' in node.instance_attrs: + try: + cls = node.instance_attrs['__class__'][0] + return cls.name == signal_name + except AttributeError: + # return False if the cls does not have a name attribute + pass return False @@ -24,9 +33,9 @@ def emit(self, *args): pass ''') signal_cls = module['pyqtSignal'] - node._instance_attrs['emit'] = signal_cls['emit'] - node._instance_attrs['disconnect'] = signal_cls['disconnect'] - node._instance_attrs['connect'] = signal_cls['connect'] + node.instance_attrs['emit'] = signal_cls['emit'] + node.instance_attrs['disconnect'] = signal_cls['disconnect'] + node.instance_attrs['connect'] = signal_cls['connect'] def pyqt4_qtcore_transform(): diff --git a/pymode/libs/astroid/brain/brain_re.py b/pymode/libs/astroid/brain/brain_re.py new file mode 100644 index 00000000..f6e1befd --- /dev/null +++ b/pymode/libs/astroid/brain/brain_re.py @@ -0,0 +1,34 @@ +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER +import sys +import astroid + +PY36 = sys.version_info >= (3, 6) + +if PY36: + # Since Python 3.6 there is the RegexFlag enum + # where every entry will be exposed via updating globals() + + def _re_transform(): + return astroid.parse(''' + import sre_compile + ASCII = sre_compile.SRE_FLAG_ASCII + IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE + LOCALE = sre_compile.SRE_FLAG_LOCALE + UNICODE = sre_compile.SRE_FLAG_UNICODE + MULTILINE = sre_compile.SRE_FLAG_MULTILINE + DOTALL = sre_compile.SRE_FLAG_DOTALL + VERBOSE = sre_compile.SRE_FLAG_VERBOSE + A = ASCII + I = IGNORECASE + L = LOCALE + U = UNICODE + M = MULTILINE + S = DOTALL + X = VERBOSE + TEMPLATE = sre_compile.SRE_FLAG_TEMPLATE + T = TEMPLATE + DEBUG = sre_compile.SRE_FLAG_DEBUG + ''') + + astroid.register_module_extender(astroid.MANAGER, 're', _re_transform) diff --git a/pymode/libs/astroid/brain/brain_six.py b/pymode/libs/astroid/brain/brain_six.py index 9596a6c8..f16a2938 100644 --- a/pymode/libs/astroid/brain/brain_six.py +++ b/pymode/libs/astroid/brain/brain_six.py @@ -1,29 +1,17 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# astroid 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 Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2014-2016 Claudiu Popa -"""Astroid hooks for six.moves.""" +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + + +"""Astroid hooks for six module.""" import sys from textwrap import dedent from astroid import MANAGER, register_module_extender from astroid.builder import AstroidBuilder -from astroid.exceptions import AstroidBuildingException, InferenceError +from astroid.exceptions import AstroidBuildingError, InferenceError from astroid import nodes @@ -113,7 +101,7 @@ class UrllibParse(object): splitquery = _urllib.splitquery splittag = _urllib.splittag splituser = _urllib.splituser - uses_fragment = _urlparse.uses_fragment + uses_fragment = _urlparse.uses_fragment uses_netloc = _urlparse.uses_netloc uses_params = _urlparse.uses_params uses_query = _urlparse.uses_query @@ -254,7 +242,7 @@ class Moves(object): def _six_fail_hook(modname): if modname != 'six.moves': - raise AstroidBuildingException + raise AstroidBuildingError(modname=modname) module = AstroidBuilder(MANAGER).string_build(_IMPORTS) module.name = 'six.moves' return module diff --git a/pymode/libs/astroid/brain/brain_ssl.py b/pymode/libs/astroid/brain/brain_ssl.py index 1cf8d1b8..78c20c99 100644 --- a/pymode/libs/astroid/brain/brain_ssl.py +++ b/pymode/libs/astroid/brain/brain_ssl.py @@ -1,3 +1,8 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Astroid hooks for the ssl library.""" from astroid import MANAGER, register_module_extender diff --git a/pymode/libs/astroid/brain/brain_stdlib.py b/pymode/libs/astroid/brain/brain_stdlib.py deleted file mode 100644 index ad395a27..00000000 --- a/pymode/libs/astroid/brain/brain_stdlib.py +++ /dev/null @@ -1,473 +0,0 @@ - -"""Astroid hooks for the Python 2 standard library. - -Currently help understanding of : - -* hashlib.md5 and hashlib.sha1 -""" - -import functools -import sys -from textwrap import dedent - -from astroid import ( - MANAGER, UseInferenceDefault, inference_tip, BoundMethod, - InferenceError, register_module_extender) -from astroid import exceptions -from astroid import nodes -from astroid.builder import AstroidBuilder -from astroid import util -from astroid import test_utils - -PY3K = sys.version_info > (3, 0) -PY33 = sys.version_info >= (3, 3) -PY34 = sys.version_info >= (3, 4) - -# general function - -def infer_func_form(node, base_type, context=None, enum=False): - """Specific inference function for namedtuple or Python 3 enum. """ - def infer_first(node): - if node is util.YES: - raise UseInferenceDefault - try: - value = next(node.infer(context=context)) - if value is util.YES: - raise UseInferenceDefault() - else: - return value - except StopIteration: - raise InferenceError() - - # node is a Call node, class name as first argument and generated class - # attributes as second argument - if len(node.args) != 2: - # something weird here, go back to class implementation - raise UseInferenceDefault() - # namedtuple or enums list of attributes can be a list of strings or a - # whitespace-separate string - try: - name = infer_first(node.args[0]).value - names = infer_first(node.args[1]) - try: - attributes = names.value.replace(',', ' ').split() - except AttributeError: - if not enum: - attributes = [infer_first(const).value for const in names.elts] - else: - # Enums supports either iterator of (name, value) pairs - # or mappings. - # TODO: support only list, tuples and mappings. - if hasattr(names, 'items') and isinstance(names.items, list): - attributes = [infer_first(const[0]).value - for const in names.items - if isinstance(const[0], nodes.Const)] - elif hasattr(names, 'elts'): - # Enums can support either ["a", "b", "c"] - # or [("a", 1), ("b", 2), ...], but they can't - # be mixed. - if all(isinstance(const, nodes.Tuple) - for const in names.elts): - attributes = [infer_first(const.elts[0]).value - for const in names.elts - if isinstance(const, nodes.Tuple)] - else: - attributes = [infer_first(const).value - for const in names.elts] - else: - raise AttributeError - if not attributes: - raise AttributeError - except (AttributeError, exceptions.InferenceError): - raise UseInferenceDefault() - - # If we can't iner the name of the class, don't crash, up to this point - # we know it is a namedtuple anyway. - name = name or 'Uninferable' - # we want to return a Class node instance with proper attributes set - class_node = nodes.ClassDef(name, 'docstring') - class_node.parent = node.parent - # set base class=tuple - class_node.bases.append(base_type) - # XXX add __init__(*attributes) method - for attr in attributes: - fake_node = nodes.EmptyNode() - fake_node.parent = class_node - fake_node.attrname = attr - class_node._instance_attrs[attr] = [fake_node] - return class_node, name, attributes - - -# module specific transformation functions ##################################### - -def hashlib_transform(): - template = ''' - -class %(name)s(object): - def __init__(self, value=''): pass - def digest(self): - return %(digest)s - def copy(self): - return self - def update(self, value): pass - def hexdigest(self): - return '' - @property - def name(self): - return %(name)r - @property - def block_size(self): - return 1 - @property - def digest_size(self): - return 1 -''' - algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') - classes = "".join( - template % {'name': hashfunc, 'digest': 'b""' if PY3K else '""'} - for hashfunc in algorithms) - return AstroidBuilder(MANAGER).string_build(classes) - - -def collections_transform(): - return AstroidBuilder(MANAGER).string_build(''' - -class defaultdict(dict): - default_factory = None - def __missing__(self, key): pass - -class deque(object): - maxlen = 0 - def __init__(self, iterable=None, maxlen=None): - self.iterable = iterable - def append(self, x): pass - def appendleft(self, x): pass - def clear(self): pass - def count(self, x): return 0 - def extend(self, iterable): pass - def extendleft(self, iterable): pass - def pop(self): pass - def popleft(self): pass - def remove(self, value): pass - def reverse(self): pass - def rotate(self, n): pass - def __iter__(self): return self - def __reversed__(self): return self.iterable[::-1] - def __getitem__(self, index): pass - def __setitem__(self, index, value): pass - def __delitem__(self, index): pass -''') - - -def pkg_resources_transform(): - return AstroidBuilder(MANAGER).string_build(''' -def require(*requirements): - return pkg_resources.working_set.require(*requirements) - -def run_script(requires, script_name): - return pkg_resources.working_set.run_script(requires, script_name) - -def iter_entry_points(group, name=None): - return pkg_resources.working_set.iter_entry_points(group, name) - -def resource_exists(package_or_requirement, resource_name): - return get_provider(package_or_requirement).has_resource(resource_name) - -def resource_isdir(package_or_requirement, resource_name): - return get_provider(package_or_requirement).resource_isdir( - resource_name) - -def resource_filename(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_filename( - self, resource_name) - -def resource_stream(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_stream( - self, resource_name) - -def resource_string(package_or_requirement, resource_name): - return get_provider(package_or_requirement).get_resource_string( - self, resource_name) - -def resource_listdir(package_or_requirement, resource_name): - return get_provider(package_or_requirement).resource_listdir( - resource_name) - -def extraction_error(): - pass - -def get_cache_path(archive_name, names=()): - extract_path = self.extraction_path or get_default_cache() - target_path = os.path.join(extract_path, archive_name+'-tmp', *names) - return target_path - -def postprocess(tempname, filename): - pass - -def set_extraction_path(path): - pass - -def cleanup_resources(force=False): - pass - -''') - - -def subprocess_transform(): - if PY3K: - communicate = (bytes('string', 'ascii'), bytes('string', 'ascii')) - communicate_signature = 'def communicate(self, input=None, timeout=None)' - init = """ - def __init__(self, args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0, restore_signals=True, - start_new_session=False, pass_fds=()): - pass - """ - else: - communicate = ('string', 'string') - communicate_signature = 'def communicate(self, input=None)' - init = """ - def __init__(self, args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - pass - """ - if PY33: - wait_signature = 'def wait(self, timeout=None)' - else: - wait_signature = 'def wait(self)' - if PY3K: - ctx_manager = ''' - def __enter__(self): return self - def __exit__(self, *args): pass - ''' - else: - ctx_manager = '' - code = dedent(''' - - class Popen(object): - returncode = pid = 0 - stdin = stdout = stderr = file() - - %(init)s - - %(communicate_signature)s: - return %(communicate)r - %(wait_signature)s: - return self.returncode - def poll(self): - return self.returncode - def send_signal(self, signal): - pass - def terminate(self): - pass - def kill(self): - pass - %(ctx_manager)s - ''' % {'init': init, - 'communicate': communicate, - 'communicate_signature': communicate_signature, - 'wait_signature': wait_signature, - 'ctx_manager': ctx_manager}) - return AstroidBuilder(MANAGER).string_build(code) - - -# namedtuple support ########################################################### - -def _looks_like(node, name): - func = node.func - if isinstance(func, nodes.Attribute): - return func.attrname == name - if isinstance(func, nodes.Name): - return func.name == name - return False - -_looks_like_namedtuple = functools.partial(_looks_like, name='namedtuple') -_looks_like_enum = functools.partial(_looks_like, name='Enum') - - -def infer_named_tuple(node, context=None): - """Specific inference function for namedtuple Call node""" - class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied, - context=context) - fake = AstroidBuilder(MANAGER).string_build(''' -class %(name)s(tuple): - _fields = %(fields)r - def _asdict(self): - return self.__dict__ - @classmethod - def _make(cls, iterable, new=tuple.__new__, len=len): - return new(cls, iterable) - def _replace(self, **kwds): - return self - ''' % {'name': name, 'fields': attributes}) - class_node._locals['_asdict'] = fake.body[0]._locals['_asdict'] - class_node._locals['_make'] = fake.body[0]._locals['_make'] - class_node._locals['_replace'] = fake.body[0]._locals['_replace'] - class_node._locals['_fields'] = fake.body[0]._locals['_fields'] - # we use UseInferenceDefault, we can't be a generator so return an iterator - return iter([class_node]) - - -def infer_enum(node, context=None): - """ Specific inference function for enum Call node. """ - enum_meta = test_utils.extract_node(''' - class EnumMeta(object): - 'docstring' - def __call__(self, node): - class EnumAttribute(object): - name = '' - value = 0 - return EnumAttribute() - ''') - class_node = infer_func_form(node, enum_meta, - context=context, enum=True)[0] - return iter([class_node.instantiate_class()]) - - -def infer_enum_class(node): - """ Specific inference for enums. """ - names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum')) - for basename in node.basenames: - # TODO: doesn't handle subclasses yet. This implementation - # is a hack to support enums. - if basename not in names: - continue - if node.root().name == 'enum': - # Skip if the class is directly from enum module. - break - for local, values in node._locals.items(): - if any(not isinstance(value, nodes.AssignName) - for value in values): - continue - - stmt = values[0].statement() - if isinstance(stmt.targets[0], nodes.Tuple): - targets = stmt.targets[0].itered() - else: - targets = stmt.targets - - new_targets = [] - for target in targets: - # Replace all the assignments with our mocked class. - classdef = dedent(''' - class %(name)s(%(types)s): - @property - def value(self): - # Not the best return. - return None - @property - def name(self): - return %(name)r - ''' % {'name': target.name, 'types': ', '.join(node.basenames)}) - fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name] - fake.parent = target.parent - for method in node.mymethods(): - fake._locals[method.name] = [method] - new_targets.append(fake.instantiate_class()) - node._locals[local] = new_targets - break - return node - -def multiprocessing_transform(): - module = AstroidBuilder(MANAGER).string_build(dedent(''' - from multiprocessing.managers import SyncManager - def Manager(): - return SyncManager() - ''')) - if not PY34: - return module - - # On Python 3.4, multiprocessing uses a getattr lookup inside contexts, - # in order to get the attributes they need. Since it's extremely - # dynamic, we use this approach to fake it. - node = AstroidBuilder(MANAGER).string_build(dedent(''' - from multiprocessing.context import DefaultContext, BaseContext - default = DefaultContext() - base = BaseContext() - ''')) - try: - context = next(node['default'].infer()) - base = next(node['base'].infer()) - except InferenceError: - return module - - for node in (context, base): - for key, value in node._locals.items(): - if key.startswith("_"): - continue - - value = value[0] - if isinstance(value, nodes.FunctionDef): - # We need to rebound this, since otherwise - # it will have an extra argument (self). - value = BoundMethod(value, node) - module[key] = value - return module - -def multiprocessing_managers_transform(): - return AstroidBuilder(MANAGER).string_build(dedent(''' - import array - import threading - import multiprocessing.pool as pool - - import six - - class Namespace(object): - pass - - class Value(object): - def __init__(self, typecode, value, lock=True): - self._typecode = typecode - self._value = value - def get(self): - return self._value - def set(self, value): - self._value = value - def __repr__(self): - return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value) - value = property(get, set) - - def Array(typecode, sequence, lock=True): - return array.array(typecode, sequence) - - class SyncManager(object): - Queue = JoinableQueue = six.moves.queue.Queue - Event = threading.Event - RLock = threading.RLock - BoundedSemaphore = threading.BoundedSemaphore - Condition = threading.Condition - Barrier = threading.Barrier - Pool = pool.Pool - list = list - dict = dict - Value = Value - Array = Array - Namespace = Namespace - __enter__ = lambda self: self - __exit__ = lambda *args: args - - def start(self, initializer=None, initargs=None): - pass - def shutdown(self): - pass - ''')) - - -MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple), - _looks_like_namedtuple) -MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), - _looks_like_enum) -MANAGER.register_transform(nodes.ClassDef, infer_enum_class) -register_module_extender(MANAGER, 'hashlib', hashlib_transform) -register_module_extender(MANAGER, 'collections', collections_transform) -register_module_extender(MANAGER, 'pkg_resources', pkg_resources_transform) -register_module_extender(MANAGER, 'subprocess', subprocess_transform) -register_module_extender(MANAGER, 'multiprocessing.managers', - multiprocessing_managers_transform) -register_module_extender(MANAGER, 'multiprocessing', multiprocessing_transform) diff --git a/pymode/libs/astroid/brain/brain_subprocess.py b/pymode/libs/astroid/brain/brain_subprocess.py new file mode 100644 index 00000000..db800e78 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_subprocess.py @@ -0,0 +1,94 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import sys +import textwrap + +import six + +import astroid + + +PY33 = sys.version_info >= (3, 3) +PY36 = sys.version_info >= (3, 6) + + +def _subprocess_transform(): + if six.PY3: + communicate = (bytes('string', 'ascii'), bytes('string', 'ascii')) + communicate_signature = 'def communicate(self, input=None, timeout=None)' + if PY36: + init = """ + def __init__(self, args, bufsize=0, executable=None, + stdin=None, stdout=None, stderr=None, + preexec_fn=None, close_fds=False, shell=False, + cwd=None, env=None, universal_newlines=False, + startupinfo=None, creationflags=0, restore_signals=True, + start_new_session=False, pass_fds=(), *, + encoding=None, errors=None): + pass + """ + else: + init = """ + def __init__(self, args, bufsize=0, executable=None, + stdin=None, stdout=None, stderr=None, + preexec_fn=None, close_fds=False, shell=False, + cwd=None, env=None, universal_newlines=False, + startupinfo=None, creationflags=0, restore_signals=True, + start_new_session=False, pass_fds=()): + pass + """ + else: + communicate = ('string', 'string') + communicate_signature = 'def communicate(self, input=None)' + init = """ + def __init__(self, args, bufsize=0, executable=None, + stdin=None, stdout=None, stderr=None, + preexec_fn=None, close_fds=False, shell=False, + cwd=None, env=None, universal_newlines=False, + startupinfo=None, creationflags=0): + pass + """ + if PY33: + wait_signature = 'def wait(self, timeout=None)' + else: + wait_signature = 'def wait(self)' + if six.PY3: + ctx_manager = ''' + def __enter__(self): return self + def __exit__(self, *args): pass + ''' + else: + ctx_manager = '' + code = textwrap.dedent(''' + class Popen(object): + returncode = pid = 0 + stdin = stdout = stderr = file() + + %(communicate_signature)s: + return %(communicate)r + %(wait_signature)s: + return self.returncode + def poll(self): + return self.returncode + def send_signal(self, signal): + pass + def terminate(self): + pass + def kill(self): + pass + %(ctx_manager)s + ''' % {'communicate': communicate, + 'communicate_signature': communicate_signature, + 'wait_signature': wait_signature, + 'ctx_manager': ctx_manager}) + + init_lines = textwrap.dedent(init).splitlines() + indented_init = '\n'.join([' ' * 4 + line for line in init_lines]) + code += indented_init + return astroid.parse(code) + + +astroid.register_module_extender(astroid.MANAGER, 'subprocess', _subprocess_transform) diff --git a/pymode/libs/astroid/brain/brain_threading.py b/pymode/libs/astroid/brain/brain_threading.py new file mode 100644 index 00000000..bbc0c612 --- /dev/null +++ b/pymode/libs/astroid/brain/brain_threading.py @@ -0,0 +1,26 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import astroid + + +def _thread_transform(): + return astroid.parse(''' + class lock(object): + def acquire(self, blocking=True): + pass + def release(self): + pass + def __enter__(self): + return True + def __exit__(self, *args): + pass + + def Lock(): + return lock() + ''') + + +astroid.register_module_extender(astroid.MANAGER, 'threading', _thread_transform) diff --git a/pymode/libs/astroid/brain/brain_typing.py b/pymode/libs/astroid/brain/brain_typing.py new file mode 100644 index 00000000..711066cb --- /dev/null +++ b/pymode/libs/astroid/brain/brain_typing.py @@ -0,0 +1,89 @@ +# Copyright (c) 2016 David Euresti + +"""Astroid hooks for typing.py support.""" +import textwrap + +from astroid import ( + MANAGER, UseInferenceDefault, extract_node, inference_tip, + nodes, InferenceError) +from astroid.nodes import List, Tuple + + +TYPING_NAMEDTUPLE_BASENAMES = { + 'NamedTuple', + 'typing.NamedTuple' +} + + +def infer_typing_namedtuple(node, context=None): + """Infer a typing.NamedTuple(...) call.""" + # This is essentially a namedtuple with different arguments + # so we extract the args and infer a named tuple. + try: + func = next(node.func.infer()) + except InferenceError: + raise UseInferenceDefault + + if func.qname() != 'typing.NamedTuple': + raise UseInferenceDefault + + if len(node.args) != 2: + raise UseInferenceDefault + + if not isinstance(node.args[1], (List, Tuple)): + raise UseInferenceDefault + + names = [] + for elt in node.args[1].elts: + if not isinstance(elt, (List, Tuple)): + raise UseInferenceDefault + if len(elt.elts) != 2: + raise UseInferenceDefault + names.append(elt.elts[0].as_string()) + + typename = node.args[0].as_string() + node = extract_node('namedtuple(%(typename)s, (%(fields)s,)) ' % + {'typename': typename, 'fields': ",".join(names)}) + return node.infer(context=context) + + +def infer_typing_namedtuple_class(node, context=None): + """Infer a subclass of typing.NamedTuple""" + + # Check if it has the corresponding bases + if not set(node.basenames) & TYPING_NAMEDTUPLE_BASENAMES: + raise UseInferenceDefault + + annassigns_fields = [ + annassign.target.name for annassign in node.body + if isinstance(annassign, nodes.AnnAssign) + ] + code = textwrap.dedent(''' + from collections import namedtuple + namedtuple({typename!r}, {fields!r}) + ''').format( + typename=node.name, + fields=",".join(annassigns_fields) + ) + node = extract_node(code) + return node.infer(context=context) + + +def looks_like_typing_namedtuple(node): + func = node.func + if isinstance(func, nodes.Attribute): + return func.attrname == 'NamedTuple' + if isinstance(func, nodes.Name): + return func.name == 'NamedTuple' + return False + + +MANAGER.register_transform( + nodes.Call, + inference_tip(infer_typing_namedtuple), + looks_like_typing_namedtuple +) +MANAGER.register_transform( + nodes.ClassDef, + inference_tip(infer_typing_namedtuple_class) +) diff --git a/pymode/libs/astroid/builder.py b/pymode/libs/astroid/builder.py index 63c156a1..afb9daf1 100644 --- a/pymode/libs/astroid/builder.py +++ b/pymode/libs/astroid/builder.py @@ -1,31 +1,22 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2015 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """The AstroidBuilder makes astroid from living object and / or from _ast The builder is not thread safe and can't be used to parse different sources at the same time. """ -from __future__ import with_statement -import _ast +import re import os import sys import textwrap +import _ast from astroid import bases from astroid import exceptions @@ -33,32 +24,34 @@ from astroid import modutils from astroid import raw_building from astroid import rebuilder +from astroid import nodes from astroid import util +# The name of the transient function that is used to +# wrap expressions to be extracted when calling +# extract_node. +_TRANSIENT_FUNCTION = '__' + +# The comment used to select a statement to be extracted +# when calling extract_node. +_STATEMENT_SELECTOR = '#@' + def _parse(string): return compile(string, "", 'exec', _ast.PyCF_ONLY_AST) if sys.version_info >= (3, 0): - # pylint: disable=no-name-in-module; We don't understand flows yet. from tokenize import detect_encoding def open_source_file(filename): with open(filename, 'rb') as byte_stream: encoding = detect_encoding(byte_stream.readline)[0] stream = open(filename, 'r', newline=None, encoding=encoding) - try: - data = stream.read() - except UnicodeError: # wrong encoding - # detect_encoding returns utf-8 if no encoding specified - msg = 'Wrong (%s) or no encoding specified' % encoding - raise exceptions.AstroidBuildingException(msg) + data = stream.read() return stream, encoding, data else: - import re - _ENCODING_RGX = re.compile(r"\s*#+.*coding[:=]\s*([-\w.]+)") def _guess_encoding(string): @@ -83,6 +76,17 @@ def open_source_file(filename): MANAGER = manager.AstroidManager() +def _can_assign_attr(node, attrname): + try: + slots = node.slots() + except NotImplementedError: + pass + else: + if slots and attrname not in set(slot.value for slot in slots): + return False + return True + + class AstroidBuilder(raw_building.InspectBuilder): """Class for building an astroid tree from source code or from a live module. @@ -92,7 +96,7 @@ class AstroidBuilder(raw_building.InspectBuilder): applied after the tree was built from source or from a live object, by default being True. """ - + # pylint: disable=redefined-outer-name def __init__(self, manager=None, apply_transforms=True): super(AstroidBuilder, self).__init__() self._manager = manager or MANAGER @@ -124,12 +128,18 @@ def file_build(self, path, modname=None): try: stream, encoding, data = open_source_file(path) except IOError as exc: - msg = 'Unable to load file %r (%s)' % (path, exc) - raise exceptions.AstroidBuildingException(msg) - except SyntaxError as exc: # py3k encoding specification error - raise exceptions.AstroidBuildingException(exc) - except LookupError as exc: # unknown encoding - raise exceptions.AstroidBuildingException(exc) + util.reraise(exceptions.AstroidBuildingError( + 'Unable to load file {path}:\n{error}', + modname=modname, path=path, error=exc)) + except (SyntaxError, LookupError) as exc: + util.reraise(exceptions.AstroidSyntaxError( + 'Python 3 encoding specification error or unknown encoding:\n' + '{error}', modname=modname, path=path, error=exc)) + except UnicodeError: # wrong encoding + # detect_encoding returns utf-8 if no encoding specified + util.reraise(exceptions.AstroidBuildingError( + 'Wrong or no encoding specified for {filename}.', + filename=path)) with stream: # get module name if necessary if modname is None: @@ -144,7 +154,7 @@ def file_build(self, path, modname=None): def string_build(self, data, modname='', path=None): """Build astroid from source code string.""" module = self._data_build(data, modname, path) - module.source_code = data.encode('utf-8') + module.file_bytes = data.encode('utf-8') return self._post_build(module, 'utf-8') def _post_build(self, module, encoding): @@ -155,7 +165,7 @@ def _post_build(self, module, encoding): for from_node in module._import_from_nodes: if from_node.modname == '__future__': for symbol, _ in from_node.names: - module._future_imports.add(symbol) + module.future_imports.add(symbol) self.add_from_names_to_locals(from_node) # handle delayed assattr nodes for delayed in module._delayed_assattr: @@ -171,7 +181,9 @@ def _data_build(self, data, modname, path): try: node = _parse(data + '\n') except (TypeError, ValueError, SyntaxError) as exc: - raise exceptions.AstroidBuildingException(exc) + util.reraise(exceptions.AstroidSyntaxError( + 'Parsing Python code failed:\n{error}', + source=data, modname=modname, path=path, error=exc)) if path is not None: node_file = os.path.abspath(path) else: @@ -180,7 +192,7 @@ def _data_build(self, data, modname, path): modname = modname[:-9] package = True else: - package = path and path.find('__init__.py') > -1 or False + package = path is not None and os.path.splitext(os.path.basename(path))[0] == '__init__' builder = rebuilder.TreeRebuilder(self._manager) module = builder.visit_module(node, modname, node_file, package) module._import_from_nodes = builder._import_from_nodes @@ -200,14 +212,14 @@ def sort_locals(my_list): if name == '*': try: imported = node.do_import_module() - except exceptions.InferenceError: + except exceptions.AstroidBuildingError: continue - for name in imported._public_names(): + for name in imported.public_names(): node.parent.set_local(name, node) - sort_locals(node.parent.scope()._locals[name]) + sort_locals(node.parent.scope().locals[name]) else: node.parent.set_local(asname or name, node) - sort_locals(node.parent.scope()._locals[asname or name]) + sort_locals(node.parent.scope().locals[asname or name]) def delayed_assattr(self, node): """Visit a AssAttr node @@ -217,20 +229,22 @@ def delayed_assattr(self, node): try: frame = node.frame() for inferred in node.expr.infer(): - if inferred is util.YES: + if inferred is util.Uninferable: continue try: if inferred.__class__ is bases.Instance: inferred = inferred._proxied - iattrs = inferred._instance_attrs + iattrs = inferred.instance_attrs + if not _can_assign_attr(inferred, node.attrname): + continue elif isinstance(inferred, bases.Instance): # Const, Tuple, ... we may be wrong, may be not, but # anyway we don't want to pollute builtin's namespace continue elif inferred.is_function: - iattrs = inferred._instance_attrs + iattrs = inferred.instance_attrs else: - iattrs = inferred._locals + iattrs = inferred.locals except AttributeError: # XXX log error continue @@ -239,7 +253,7 @@ def delayed_assattr(self, node): continue # get assign in __init__ first XXX useful ? if (frame.name == '__init__' and values and - not values[0].frame().name == '__init__'): + values[0].frame().name != '__init__'): values.insert(0, node) else: values.append(node) @@ -247,6 +261,10 @@ def delayed_assattr(self, node): pass +def build_namespace_package_module(name, path): + return nodes.Module(name, doc='', path=path, package=True) + + def parse(code, module_name='', path=None, apply_transforms=True): """Parses a source string in order to obtain an astroid AST from it @@ -261,3 +279,159 @@ def parse(code, module_name='', path=None, apply_transforms=True): builder = AstroidBuilder(manager=MANAGER, apply_transforms=apply_transforms) return builder.string_build(code, modname=module_name, path=path) + + +def _extract_expressions(node): + """Find expressions in a call to _TRANSIENT_FUNCTION and extract them. + + The function walks the AST recursively to search for expressions that + are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an + expression, it completely removes the function call node from the tree, + replacing it by the wrapped expression inside the parent. + + :param node: An astroid node. + :type node: astroid.bases.NodeNG + :yields: The sequence of wrapped expressions on the modified tree + expression can be found. + """ + if (isinstance(node, nodes.Call) + and isinstance(node.func, nodes.Name) + and node.func.name == _TRANSIENT_FUNCTION): + real_expr = node.args[0] + real_expr.parent = node.parent + # Search for node in all _astng_fields (the fields checked when + # get_children is called) of its parent. Some of those fields may + # be lists or tuples, in which case the elements need to be checked. + # When we find it, replace it by real_expr, so that the AST looks + # like no call to _TRANSIENT_FUNCTION ever took place. + for name in node.parent._astroid_fields: + child = getattr(node.parent, name) + if isinstance(child, (list, tuple)): + for idx, compound_child in enumerate(child): + if compound_child is node: + child[idx] = real_expr + elif child is node: + setattr(node.parent, name, real_expr) + yield real_expr + else: + for child in node.get_children(): + for result in _extract_expressions(child): + yield result + + +def _find_statement_by_line(node, line): + """Extracts the statement on a specific line from an AST. + + If the line number of node matches line, it will be returned; + otherwise its children are iterated and the function is called + recursively. + + :param node: An astroid node. + :type node: astroid.bases.NodeNG + :param line: The line number of the statement to extract. + :type line: int + :returns: The statement on the line, or None if no statement for the line + can be found. + :rtype: astroid.bases.NodeNG or None + """ + if isinstance(node, (nodes.ClassDef, nodes.FunctionDef)): + # This is an inaccuracy in the AST: the nodes that can be + # decorated do not carry explicit information on which line + # the actual definition (class/def), but .fromline seems to + # be close enough. + node_line = node.fromlineno + else: + node_line = node.lineno + + if node_line == line: + return node + + for child in node.get_children(): + result = _find_statement_by_line(child, line) + if result: + return result + + return None + + +def extract_node(code, module_name=''): + """Parses some Python code as a module and extracts a designated AST node. + + Statements: + To extract one or more statement nodes, append #@ to the end of the line + + Examples: + >>> def x(): + >>> def y(): + >>> return 1 #@ + + The return statement will be extracted. + + >>> class X(object): + >>> def meth(self): #@ + >>> pass + + The function object 'meth' will be extracted. + + Expressions: + To extract arbitrary expressions, surround them with the fake + function call __(...). After parsing, the surrounded expression + will be returned and the whole AST (accessible via the returned + node's parent attribute) will look like the function call was + never there in the first place. + + Examples: + >>> a = __(1) + + The const node will be extracted. + + >>> def x(d=__(foo.bar)): pass + + The node containing the default argument will be extracted. + + >>> def foo(a, b): + >>> return 0 < __(len(a)) < b + + The node containing the function call 'len' will be extracted. + + If no statements or expressions are selected, the last toplevel + statement will be returned. + + If the selected statement is a discard statement, (i.e. an expression + turned into a statement), the wrapped expression is returned instead. + + For convenience, singleton lists are unpacked. + + :param str code: A piece of Python code that is parsed as + a module. Will be passed through textwrap.dedent first. + :param str module_name: The name of the module. + :returns: The designated node from the parse tree, or a list of nodes. + :rtype: astroid.bases.NodeNG, or a list of nodes. + """ + def _extract(node): + if isinstance(node, nodes.Expr): + return node.value + + return node + + requested_lines = [] + for idx, line in enumerate(code.splitlines()): + if line.strip().endswith(_STATEMENT_SELECTOR): + requested_lines.append(idx + 1) + + tree = parse(code, module_name=module_name) + extracted = [] + if requested_lines: + for line in requested_lines: + extracted.append(_find_statement_by_line(tree, line)) + + # Modifies the tree. + extracted.extend(_extract_expressions(tree)) + + if not extracted: + extracted.append(tree.body[-1]) + + extracted = [_extract(node) for node in extracted] + if len(extracted) == 1: + return extracted[0] + return extracted diff --git a/pymode/libs/astroid/context.py b/pymode/libs/astroid/context.py index 284dfa18..627bae5d 100644 --- a/pymode/libs/astroid/context.py +++ b/pymode/libs/astroid/context.py @@ -1,24 +1,13 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER """Various context related utilities, including inference and call contexts.""" import contextlib +import pprint class InferenceContext(object): @@ -34,8 +23,10 @@ def __init__(self, path=None, inferred=None): def push(self, node): name = self.lookupname if (node, name) in self.path: - raise StopIteration() + return True + self.path.add((node, name)) + return False def clone(self): # XXX copy lookupname/callcontext ? @@ -59,6 +50,12 @@ def restore_path(self): yield self.path = path + def __str__(self): + state = ('%s=%s' % (field, pprint.pformat(getattr(self, field), + width=80 - len(field))) + for field in self.__slots__) + return '%s(%s)' % (type(self).__name__, ',\n '.join(state)) + class CallContext(object): """Holds information for a call site.""" @@ -77,5 +74,5 @@ def __init__(self, args, keywords=None): def copy_context(context): if context is not None: return context.clone() - else: - return InferenceContext() + + return InferenceContext() diff --git a/pymode/libs/astroid/decorators.py b/pymode/libs/astroid/decorators.py index a446536c..a59cab22 100644 --- a/pymode/libs/astroid/decorators.py +++ b/pymode/libs/astroid/decorators.py @@ -1,28 +1,20 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -# -# The code in this file was originally part of logilab-common, licensed under -# the same license. +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER """ A few useful function/method decorators.""" +import functools + import wrapt +from astroid import context as contextmod +from astroid import exceptions +from astroid import util + @wrapt.decorator def cached(func, instance, args, kwargs): @@ -57,8 +49,8 @@ def __init__(self, wrapped): try: wrapped.__name__ except AttributeError: - raise TypeError('%s must have a __name__ attribute' % - wrapped) + util.reraise(TypeError('%s must have a __name__ attribute' + % wrapped)) self.wrapped = wrapped @property @@ -73,3 +65,83 @@ def __get__(self, inst, objtype=None): val = self.wrapped(inst) setattr(inst, self.wrapped.__name__, val) return val + + +def path_wrapper(func): + """return the given infer function wrapped to handle the path""" + # TODO: switch this to wrapt after the monkey-patching is fixed (ceridwen) + @functools.wraps(func) + def wrapped(node, context=None, _func=func, **kwargs): + """wrapper function handling context""" + if context is None: + context = contextmod.InferenceContext() + if context.push(node): + return + + yielded = set() + generator = _func(node, context, **kwargs) + try: + while True: + res = next(generator) + # unproxy only true instance, not const, tuple, dict... + if res.__class__.__name__ == 'Instance': + ares = res._proxied + else: + ares = res + if ares not in yielded: + yield res + yielded.add(ares) + except StopIteration as error: + # Explicit StopIteration to return error information, see + # comment in raise_if_nothing_inferred. + if error.args: + raise StopIteration(error.args[0]) + else: + raise StopIteration + + return wrapped + + +@wrapt.decorator +def yes_if_nothing_inferred(func, instance, args, kwargs): + inferred = False + for node in func(*args, **kwargs): + inferred = True + yield node + if not inferred: + yield util.Uninferable + + +@wrapt.decorator +def raise_if_nothing_inferred(func, instance, args, kwargs): + '''All generators wrapped with raise_if_nothing_inferred *must* + explicitly raise StopIteration with information to create an + appropriate structured InferenceError. + + ''' + # TODO: Explicitly raising StopIteration in a generator will cause + # a RuntimeError in Python >=3.7, as per + # http://legacy.python.org/dev/peps/pep-0479/ . Before 3.7 is + # released, this code will need to use one of four possible + # solutions: a decorator that restores the current behavior as + # described in + # http://legacy.python.org/dev/peps/pep-0479/#sub-proposal-decorator-to-explicitly-request-current-behaviour + # , dynamic imports or exec to generate different code for + # different versions, drop support for all Python versions <3.3, + # or refactoring to change how these decorators work. In any + # event, after dropping support for Python <3.3 this code should + # be refactored to use `yield from`. + inferred = False + try: + generator = func(*args, **kwargs) + while True: + yield next(generator) + inferred = True + except StopIteration as error: + if not inferred: + if error.args: + # pylint: disable=not-a-mapping + raise exceptions.InferenceError(**error.args[0]) + else: + raise exceptions.InferenceError( + 'StopIteration raised without any error information.') diff --git a/pymode/libs/astroid/exceptions.py b/pymode/libs/astroid/exceptions.py index 47f2fe50..8b3f2522 100644 --- a/pymode/libs/astroid/exceptions.py +++ b/pymode/libs/astroid/exceptions.py @@ -1,37 +1,118 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""this module contains exceptions used in the astroid library +# Copyright (c) 2007, 2009-2010, 2013 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER +"""this module contains exceptions used in the astroid library """ +from astroid import util -__doctype__ = "restructuredtext en" class AstroidError(Exception): - """base exception class for all astroid related exceptions""" + """base exception class for all astroid related exceptions + + AstroidError and its subclasses are structured, intended to hold + objects representing state when the exception is thrown. Field + values are passed to the constructor as keyword-only arguments. + Each subclass has its own set of standard fields, but use your + best judgment to decide whether a specific exception instance + needs more or fewer fields for debugging. Field values may be + used to lazily generate the error message: self.message.format() + will be called with the field names and values supplied as keyword + arguments. + """ + def __init__(self, message='', **kws): + super(AstroidError, self).__init__(message) + self.message = message + for key, value in kws.items(): + setattr(self, key, value) + + def __str__(self): + return self.message.format(**vars(self)) + + +class AstroidBuildingError(AstroidError): + """exception class when we are unable to build an astroid representation + + Standard attributes: + modname: Name of the module that AST construction failed for. + error: Exception raised during construction. + """ + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='Failed to import module {modname}.', **kws): + super(AstroidBuildingError, self).__init__(message, **kws) + + +class AstroidImportError(AstroidBuildingError): + """Exception class used when a module can't be imported by astroid.""" + + +class TooManyLevelsError(AstroidImportError): + """Exception class which is raised when a relative import was beyond the top-level. + + Standard attributes: + level: The level which was attempted. + name: the name of the module on which the relative import was attempted. + """ + level = None + name = None + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='Relative import with too many levels ' + '({level}) for module {name!r}', **kws): + super(TooManyLevelsError, self).__init__(message, **kws) + + +class AstroidSyntaxError(AstroidBuildingError): + """Exception class used when a module can't be parsed.""" + + +class NoDefault(AstroidError): + """raised by function's `default_value` method when an argument has + no default value + + Standard attributes: + func: Function node. + name: Name of argument without a default. + """ + func = None + name = None + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='{func!r} has no default for {name!r}.', **kws): + super(NoDefault, self).__init__(message, **kws) -class AstroidBuildingException(AstroidError): - """exception class when we are unable to build an astroid representation""" class ResolveError(AstroidError): - """base class of astroid resolution/inference error""" + """Base class of astroid resolution/inference error. + + ResolveError is not intended to be raised. + + Standard attributes: + context: InferenceContext object. + """ + context = None + class MroError(ResolveError): - """Error raised when there is a problem with method resolution of a class.""" + """Error raised when there is a problem with method resolution of a class. + + Standard attributes: + mros: A sequence of sequences containing ClassDef nodes. + cls: ClassDef node whose MRO resolution failed. + context: InferenceContext object. + """ + mros = () + cls = None + + def __str__(self): + mro_names = ", ".join("({})".format(", ".join(b.name for b in m)) + for m in self.mros) + return self.message.format(mros=mro_names, cls=self.cls) class DuplicateBasesError(MroError): @@ -43,29 +124,92 @@ class InconsistentMroError(MroError): class SuperError(ResolveError): - """Error raised when there is a problem with a super call.""" + """Error raised when there is a problem with a super call. -class SuperArgumentTypeError(SuperError): - """Error raised when the super arguments are invalid.""" + Standard attributes: + super_: The Super instance that raised the exception. + context: InferenceContext object. + """ + super_ = None + def __str__(self): + return self.message.format(**vars(self.super_)) -class NotFoundError(ResolveError): - """raised when we are unable to resolve a name""" class InferenceError(ResolveError): - """raised when we are unable to infer a node""" + """raised when we are unable to infer a node + + Standard attributes: + node: The node inference was called on. + context: InferenceContext object. + """ + node = None + context = None + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='Inference failed for {node!r}.', **kws): + super(InferenceError, self).__init__(message, **kws) + + +# Why does this inherit from InferenceError rather than ResolveError? +# Changing it causes some inference tests to fail. +class NameInferenceError(InferenceError): + """Raised when a name lookup fails, corresponds to NameError. + + Standard attributes: + name: The name for which lookup failed, as a string. + scope: The node representing the scope in which the lookup occurred. + context: InferenceContext object. + """ + name = None + scope = None + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='{name!r} not found in {scope!r}.', **kws): + super(NameInferenceError, self).__init__(message, **kws) + + +class AttributeInferenceError(ResolveError): + """Raised when an attribute lookup fails, corresponds to AttributeError. + + Standard attributes: + target: The node for which lookup failed. + attribute: The attribute for which lookup failed, as a string. + context: InferenceContext object. + """ + target = None + attribute = None + + # pylint: disable=useless-super-delegation; https://github.com/PyCQA/pylint/issues/1085 + def __init__(self, message='{attribute!r} not found on {target!r}.', **kws): + super(AttributeInferenceError, self).__init__(message, **kws) + class UseInferenceDefault(Exception): """exception to be raised in custom inference function to indicate that it should go back to the default behaviour """ -class UnresolvableName(InferenceError): - """raised when we are unable to resolve a name""" -class NoDefault(AstroidError): - """raised by function's `default_value` method when an argument has - no default value - """ +class _NonDeducibleTypeHierarchy(Exception): + """Raised when is_subtype / is_supertype can't deduce the relation between two types.""" + + +class AstroidIndexError(AstroidError): + """Raised when an Indexable / Mapping does not have an index / key.""" + + +class AstroidTypeError(AstroidError): + """Raised when a TypeError would be expected in Python code.""" + + +# Backwards-compatibility aliases +OperationError = util.BadOperationMessage +UnaryOperationError = util.BadUnaryOperationMessage +BinaryOperationError = util.BadBinaryOperationMessage +SuperArgumentTypeError = SuperError +UnresolvableName = NameInferenceError +NotFoundError = AttributeInferenceError +AstroidBuildingException = AstroidBuildingError diff --git a/pymode/libs/astroid/helpers.py b/pymode/libs/astroid/helpers.py new file mode 100644 index 00000000..62da56ea --- /dev/null +++ b/pymode/libs/astroid/helpers.py @@ -0,0 +1,173 @@ +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + + +""" +Various helper utilities. +""" + +import six + +from astroid import bases +from astroid import context as contextmod +from astroid import exceptions +from astroid import manager +from astroid import nodes +from astroid import raw_building +from astroid import scoped_nodes +from astroid import util + + +BUILTINS = six.moves.builtins.__name__ + + +def _build_proxy_class(cls_name, builtins): + proxy = raw_building.build_class(cls_name) + proxy.parent = builtins + return proxy + + +def _function_type(function, builtins): + if isinstance(function, scoped_nodes.Lambda): + if function.root().name == BUILTINS: + cls_name = 'builtin_function_or_method' + else: + cls_name = 'function' + elif isinstance(function, bases.BoundMethod): + if six.PY2: + cls_name = 'instancemethod' + else: + cls_name = 'method' + elif isinstance(function, bases.UnboundMethod): + if six.PY2: + cls_name = 'instancemethod' + else: + cls_name = 'function' + return _build_proxy_class(cls_name, builtins) + + +def _object_type(node, context=None): + astroid_manager = manager.AstroidManager() + builtins = astroid_manager.astroid_cache[BUILTINS] + context = context or contextmod.InferenceContext() + + for inferred in node.infer(context=context): + if isinstance(inferred, scoped_nodes.ClassDef): + if inferred.newstyle: + metaclass = inferred.metaclass() + if metaclass: + yield metaclass + continue + yield builtins.getattr('type')[0] + elif isinstance(inferred, (scoped_nodes.Lambda, bases.UnboundMethod)): + yield _function_type(inferred, builtins) + elif isinstance(inferred, scoped_nodes.Module): + yield _build_proxy_class('module', builtins) + else: + yield inferred._proxied + + +def object_type(node, context=None): + """Obtain the type of the given node + + This is used to implement the ``type`` builtin, which means that it's + used for inferring type calls, as well as used in a couple of other places + in the inference. + The node will be inferred first, so this function can support all + sorts of objects, as long as they support inference. + """ + + try: + types = set(_object_type(node, context)) + except exceptions.InferenceError: + return util.Uninferable + if len(types) > 1 or not types: + return util.Uninferable + return list(types)[0] + + +def safe_infer(node, context=None): + """Return the inferred value for the given node. + + Return None if inference failed or if there is some ambiguity (more than + one node has been inferred). + """ + try: + inferit = node.infer(context=context) + value = next(inferit) + except exceptions.InferenceError: + return + try: + next(inferit) + return # None if there is ambiguity on the inferred node + except exceptions.InferenceError: + return # there is some kind of ambiguity + except StopIteration: + return value + + +def has_known_bases(klass, context=None): + """Return true if all base classes of a class could be inferred.""" + try: + return klass._all_bases_known + except AttributeError: + pass + for base in klass.bases: + result = safe_infer(base, context=context) + # TODO: check for A->B->A->B pattern in class structure too? + if (not isinstance(result, scoped_nodes.ClassDef) or + result is klass or + not has_known_bases(result, context=context)): + klass._all_bases_known = False + return False + klass._all_bases_known = True + return True + + +def _type_check(type1, type2): + if not all(map(has_known_bases, (type1, type2))): + raise exceptions._NonDeducibleTypeHierarchy + + if not all([type1.newstyle, type2.newstyle]): + return False + try: + return type1 in type2.mro()[:-1] + except exceptions.MroError: + # The MRO is invalid. + raise exceptions._NonDeducibleTypeHierarchy + + +def is_subtype(type1, type2): + """Check if *type1* is a subtype of *typ2*.""" + return _type_check(type2, type1) + + +def is_supertype(type1, type2): + """Check if *type2* is a supertype of *type1*.""" + return _type_check(type1, type2) + + +def class_instance_as_index(node): + """Get the value as an index for the given instance. + + If an instance provides an __index__ method, then it can + be used in some scenarios where an integer is expected, + for instance when multiplying or subscripting a list. + """ + context = contextmod.InferenceContext() + context.callcontext = contextmod.CallContext(args=[node]) + + try: + for inferred in node.igetattr('__index__', context=context): + if not isinstance(inferred, bases.BoundMethod): + continue + + for result in inferred.infer_call_result(node, context=context): + if (isinstance(result, nodes.Const) + and isinstance(result.value, int)): + return result + except exceptions.InferenceError: + pass diff --git a/pymode/libs/astroid/inference.py b/pymode/libs/astroid/inference.py index ddd43561..f77ad19a 100644 --- a/pymode/libs/astroid/inference.py +++ b/pymode/libs/astroid/inference.py @@ -1,30 +1,26 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """this module contains a set of functions to handle inference on astroid trees """ -from __future__ import print_function +import functools +import itertools +import operator from astroid import bases from astroid import context as contextmod from astroid import exceptions +from astroid import decorators +from astroid import helpers from astroid import manager from astroid import nodes +from astroid.interpreter import dunder_lookup from astroid import protocols from astroid import util @@ -46,10 +42,77 @@ def infer_end(self, context=None): nodes.FunctionDef._infer = infer_end nodes.Lambda._infer = infer_end nodes.Const._infer = infer_end -nodes.List._infer = infer_end -nodes.Tuple._infer = infer_end -nodes.Dict._infer = infer_end -nodes.Set._infer = infer_end +nodes.Slice._infer = infer_end + + +def infer_seq(self, context=None): + if not any(isinstance(e, nodes.Starred) for e in self.elts): + yield self + else: + values = _infer_seq(self, context) + new_seq = type(self)(self.lineno, self.col_offset, self.parent) + new_seq.postinit(values) + yield new_seq + + +def _infer_seq(node, context=None): + """Infer all values based on _BaseContainer.elts""" + values = [] + + for elt in node.elts: + if isinstance(elt, nodes.Starred): + starred = helpers.safe_infer(elt.value, context) + if starred in (None, util.Uninferable): + raise exceptions.InferenceError(node=node, + context=context) + if not hasattr(starred, 'elts'): + raise exceptions.InferenceError(node=node, + context=context) + values.extend(_infer_seq(starred)) + else: + values.append(elt) + return values + + +nodes.List._infer = infer_seq +nodes.Tuple._infer = infer_seq +nodes.Set._infer = infer_seq + + +def infer_map(self, context=None): + if not any(isinstance(k, nodes.DictUnpack) for k, _ in self.items): + yield self + else: + items = _infer_map(self, context) + new_seq = type(self)(self.lineno, self.col_offset, self.parent) + new_seq.postinit(list(items.items())) + yield new_seq + + +def _infer_map(node, context): + """Infer all values based on Dict.items""" + values = {} + for name, value in node.items: + if isinstance(name, nodes.DictUnpack): + double_starred = helpers.safe_infer(value, context) + if double_starred in (None, util.Uninferable): + raise exceptions.InferenceError + if not isinstance(double_starred, nodes.Dict): + raise exceptions.InferenceError(node=node, + context=context) + values.update(_infer_map(double_starred, context)) + else: + key = helpers.safe_infer(name, context=context) + value = helpers.safe_infer(value, context=context) + if key is None or value is None: + raise exceptions.InferenceError(node=node, + context=context) + values[key] = value + return values + + +nodes.Dict._infer = infer_map + def _higher_function_scope(node): """ Search for the first function which encloses the given @@ -81,16 +144,18 @@ def infer_name(self, context=None): _, stmts = parent_function.lookup(self.name) if not stmts: - raise exceptions.UnresolvableName(self.name) + raise exceptions.NameInferenceError(name=self.name, + scope=self.scope(), + context=context) context = context.clone() context.lookupname = self.name return bases._infer_stmts(stmts, context, frame) -nodes.Name._infer = bases.path_wrapper(infer_name) +nodes.Name._infer = decorators.path_wrapper(infer_name) nodes.AssignName.infer_lhs = infer_name # won't work with a path wrapper -@bases.path_wrapper -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred +@decorators.path_wrapper def infer_call(self, context=None): """infer a Call node by trying to guess what the function returns""" callcontext = context.clone() @@ -98,7 +163,7 @@ def infer_call(self, context=None): keywords=self.keywords) callcontext.boundnode = None for callee in self.func.infer(context): - if callee is util.YES: + if callee is util.Uninferable: yield callee continue try: @@ -108,19 +173,28 @@ def infer_call(self, context=None): except exceptions.InferenceError: ## XXX log error ? continue + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, context=context)) nodes.Call._infer = infer_call -@bases.path_wrapper +@decorators.path_wrapper def infer_import(self, context=None, asname=True): """infer an Import node: return the imported module/object""" name = context.lookupname if name is None: - raise exceptions.InferenceError() - if asname: - yield self.do_import_module(self.real_name(name)) - else: - yield self.do_import_module(name) + raise exceptions.InferenceError(node=self, context=context) + + try: + if asname: + yield self.do_import_module(self.real_name(name)) + else: + yield self.do_import_module(name) + except exceptions.AstroidBuildingError as exc: + util.reraise(exceptions.InferenceError(node=self, error=exc, + context=context)) + nodes.Import._infer = infer_import @@ -131,59 +205,89 @@ def infer_name_module(self, name): nodes.Import.infer_name_module = infer_name_module -@bases.path_wrapper +@decorators.path_wrapper def infer_import_from(self, context=None, asname=True): """infer a ImportFrom node: return the imported module/object""" name = context.lookupname if name is None: - raise exceptions.InferenceError() + raise exceptions.InferenceError(node=self, context=context) if asname: name = self.real_name(name) - module = self.do_import_module() + + try: + module = self.do_import_module() + except exceptions.AstroidBuildingError as exc: + util.reraise(exceptions.InferenceError(node=self, error=exc, + context=context)) + try: context = contextmod.copy_context(context) context.lookupname = name stmts = module.getattr(name, ignore_locals=module is self.root()) return bases._infer_stmts(stmts, context) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) + except exceptions.AttributeInferenceError as error: + util.reraise(exceptions.InferenceError( + error.message, target=self, attribute=name, context=context)) nodes.ImportFrom._infer = infer_import_from -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred def infer_attribute(self, context=None): """infer an Attribute node by using getattr on the associated object""" for owner in self.expr.infer(context): - if owner is util.YES: + if owner is util.Uninferable: yield owner continue + + if context and context.boundnode: + # This handles the situation where the attribute is accessed through a subclass + # of a base class and the attribute is defined at the base class's level, + # by taking in consideration a redefinition in the subclass. + if (isinstance(owner, bases.Instance) + and isinstance(context.boundnode, bases.Instance)): + try: + if helpers.is_subtype(helpers.object_type(context.boundnode), + helpers.object_type(owner)): + owner = context.boundnode + except exceptions._NonDeducibleTypeHierarchy: + # Can't determine anything useful. + pass + try: context.boundnode = owner for obj in owner.igetattr(self.attrname, context): yield obj context.boundnode = None - except (exceptions.NotFoundError, exceptions.InferenceError): + except (exceptions.AttributeInferenceError, exceptions.InferenceError): context.boundnode = None except AttributeError: # XXX method / function context.boundnode = None -nodes.Attribute._infer = bases.path_wrapper(infer_attribute) + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, context=context)) +nodes.Attribute._infer = decorators.path_wrapper(infer_attribute) nodes.AssignAttr.infer_lhs = infer_attribute # # won't work with a path wrapper -@bases.path_wrapper +@decorators.path_wrapper def infer_global(self, context=None): if context.lookupname is None: - raise exceptions.InferenceError() + raise exceptions.InferenceError(node=self, context=context) try: return bases._infer_stmts(self.root().getattr(context.lookupname), context) - except exceptions.NotFoundError: - raise exceptions.InferenceError() + except exceptions.AttributeInferenceError as error: + util.reraise(exceptions.InferenceError( + error.message, target=self, attribute=context.lookupname, + context=context)) nodes.Global._infer = infer_global -@bases.raise_if_nothing_inferred +_SUBSCRIPT_SENTINEL = object() + + +@decorators.raise_if_nothing_inferred def infer_subscript(self, context=None): """Inference for subscripts @@ -194,100 +298,461 @@ def infer_subscript(self, context=None): """ value = next(self.value.infer(context)) - if value is util.YES: - yield util.YES + if value is util.Uninferable: + yield util.Uninferable return index = next(self.slice.infer(context)) - if index is util.YES: - yield util.YES + if index is util.Uninferable: + yield util.Uninferable return - if isinstance(index, nodes.Const): - try: - assigned = value.getitem(index.value, context) - except AttributeError: - raise exceptions.InferenceError() - except (IndexError, TypeError): - yield util.YES - return - - # Prevent inferring if the infered subscript - # is the same as the original subscripted object. - if self is assigned or assigned is util.YES: - yield util.YES - return - for infered in assigned.infer(context): - yield infered + # Try to deduce the index value. + index_value = _SUBSCRIPT_SENTINEL + if value.__class__ == bases.Instance: + index_value = index else: - raise exceptions.InferenceError() -nodes.Subscript._infer = bases.path_wrapper(infer_subscript) + if index.__class__ == bases.Instance: + instance_as_index = helpers.class_instance_as_index(index) + if instance_as_index: + index_value = instance_as_index + else: + index_value = index + if index_value is _SUBSCRIPT_SENTINEL: + raise exceptions.InferenceError(node=self, context=context) + + try: + assigned = value.getitem(index_value, context) + except (exceptions.AstroidTypeError, + exceptions.AstroidIndexError, + exceptions.AttributeInferenceError, + AttributeError) as exc: + util.reraise(exceptions.InferenceError(node=self, error=exc, + context=context)) + + # Prevent inferring if the inferred subscript + # is the same as the original subscripted object. + if self is assigned or assigned is util.Uninferable: + yield util.Uninferable + return + for inferred in assigned.infer(context): + yield inferred + + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, context=context)) + +nodes.Subscript._infer = decorators.path_wrapper(infer_subscript) nodes.Subscript.infer_lhs = infer_subscript -@bases.raise_if_nothing_inferred -def infer_unaryop(self, context=None): + +@decorators.raise_if_nothing_inferred +@decorators.path_wrapper +def _infer_boolop(self, context=None): + """Infer a boolean operation (and / or / not). + + The function will calculate the boolean operation + for all pairs generated through inference for each component + node. + """ + values = self.values + if self.op == 'or': + predicate = operator.truth + else: + predicate = operator.not_ + + try: + values = [value.infer(context=context) for value in values] + except exceptions.InferenceError: + yield util.Uninferable + return + + for pair in itertools.product(*values): + if any(item is util.Uninferable for item in pair): + # Can't infer the final result, just yield Uninferable. + yield util.Uninferable + continue + + bool_values = [item.bool_value() for item in pair] + if any(item is util.Uninferable for item in bool_values): + # Can't infer the final result, just yield Uninferable. + yield util.Uninferable + continue + + # Since the boolean operations are short circuited operations, + # this code yields the first value for which the predicate is True + # and if no value respected the predicate, then the last value will + # be returned (or Uninferable if there was no last value). + # This is conforming to the semantics of `and` and `or`: + # 1 and 0 -> 1 + # 0 and 1 -> 0 + # 1 or 0 -> 1 + # 0 or 1 -> 1 + value = util.Uninferable + for value, bool_value in zip(pair, bool_values): + if predicate(bool_value): + yield value + break + else: + yield value + + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, context=context)) + +nodes.BoolOp._infer = _infer_boolop + + +# UnaryOp, BinOp and AugAssign inferences + +def _filter_operation_errors(self, infer_callable, context, error): + for result in infer_callable(self, context): + if isinstance(result, error): + # For the sake of .infer(), we don't care about operation + # errors, which is the job of pylint. So return something + # which shows that we can't infer the result. + yield util.Uninferable + else: + yield result + + +def _infer_unaryop(self, context=None): + """Infer what an UnaryOp should return when evaluated.""" for operand in self.operand.infer(context): try: yield operand.infer_unary_op(self.op) - except TypeError: - continue - except AttributeError: + except TypeError as exc: + # The operand doesn't support this operation. + yield util.BadUnaryOperationMessage(operand, self.op, exc) + except AttributeError as exc: meth = protocols.UNARY_OP_METHOD[self.op] if meth is None: - yield util.YES + # `not node`. Determine node's boolean + # value and negate its result, unless it is + # Uninferable, which will be returned as is. + bool_value = operand.bool_value() + if bool_value is not util.Uninferable: + yield nodes.const_factory(not bool_value) + else: + yield util.Uninferable else: + if not isinstance(operand, (bases.Instance, nodes.ClassDef)): + # The operation was used on something which + # doesn't support it. + yield util.BadUnaryOperationMessage(operand, self.op, exc) + continue + try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand.getattr(meth) - yield operand - except GeneratorExit: - raise - except: - yield util.YES -nodes.UnaryOp._infer = bases.path_wrapper(infer_unaryop) - -def _infer_binop(binop, operand1, operand2, context, failures=None): - if operand1 is util.YES: - yield operand1 - return - try: - for valnode in operand1.infer_binary_op(binop, operand2, context): - yield valnode - except AttributeError: + try: + methods = dunder_lookup.lookup(operand, meth) + except exceptions.AttributeInferenceError: + yield util.BadUnaryOperationMessage(operand, self.op, exc) + continue + + meth = methods[0] + inferred = next(meth.infer(context=context)) + if inferred is util.Uninferable or not inferred.callable(): + continue + + context = contextmod.copy_context(context) + context.callcontext = contextmod.CallContext(args=[operand]) + call_results = inferred.infer_call_result(self, context=context) + result = next(call_results, None) + if result is None: + # Failed to infer, return the same type. + yield operand + else: + yield result + except exceptions.AttributeInferenceError as exc: + # The unary operation special method was not found. + yield util.BadUnaryOperationMessage(operand, self.op, exc) + except exceptions.InferenceError: + yield util.Uninferable + + +@decorators.raise_if_nothing_inferred +@decorators.path_wrapper +def infer_unaryop(self, context=None): + """Infer what an UnaryOp should return when evaluated.""" + for inferred in _filter_operation_errors(self, _infer_unaryop, context, + util.BadUnaryOperationMessage): + yield inferred + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, context=context)) + +nodes.UnaryOp._infer_unaryop = _infer_unaryop +nodes.UnaryOp._infer = infer_unaryop + + +def _is_not_implemented(const): + """Check if the given const node is NotImplemented.""" + return isinstance(const, nodes.Const) and const.value is NotImplemented + + +def _invoke_binop_inference(instance, opnode, op, other, context, method_name): + """Invoke binary operation inference on the given instance.""" + methods = dunder_lookup.lookup(instance, method_name) + method = methods[0] + inferred = next(method.infer(context=context)) + return instance.infer_binary_op(opnode, op, other, context, inferred) + + +def _aug_op(instance, opnode, op, other, context, reverse=False): + """Get an inference callable for an augmented binary operation.""" + method_name = protocols.AUGMENTED_OP_METHOD[op] + return functools.partial(_invoke_binop_inference, + instance=instance, + op=op, opnode=opnode, other=other, + context=context, + method_name=method_name) + + +def _bin_op(instance, opnode, op, other, context, reverse=False): + """Get an inference callable for a normal binary operation. + + If *reverse* is True, then the reflected method will be used instead. + """ + if reverse: + method_name = protocols.REFLECTED_BIN_OP_METHOD[op] + else: + method_name = protocols.BIN_OP_METHOD[op] + return functools.partial(_invoke_binop_inference, + instance=instance, + op=op, opnode=opnode, other=other, + context=context, + method_name=method_name) + + +def _get_binop_contexts(context, left, right): + """Get contexts for binary operations. + + This will return two inferrence contexts, the first one + for x.__op__(y), the other one for y.__rop__(x), where + only the arguments are inversed. + """ + # The order is important, since the first one should be + # left.__op__(right). + for arg in (right, left): + new_context = context.clone() + new_context.callcontext = contextmod.CallContext(args=[arg]) + new_context.boundnode = None + yield new_context + + +def _same_type(type1, type2): + """Check if type1 is the same as type2.""" + return type1.qname() == type2.qname() + + +def _get_binop_flow(left, left_type, binary_opnode, right, right_type, + context, reverse_context): + """Get the flow for binary operations. + + The rules are a bit messy: + + * if left and right have the same type, then only one + method will be called, left.__op__(right) + * if left and right are unrelated typewise, then first + left.__op__(right) is tried and if this does not exist + or returns NotImplemented, then right.__rop__(left) is tried. + * if left is a subtype of right, then only left.__op__(right) + is tried. + * if left is a supertype of right, then right.__rop__(left) + is first tried and then left.__op__(right) + """ + op = binary_opnode.op + if _same_type(left_type, right_type): + methods = [_bin_op(left, binary_opnode, op, right, context)] + elif helpers.is_subtype(left_type, right_type): + methods = [_bin_op(left, binary_opnode, op, right, context)] + elif helpers.is_supertype(left_type, right_type): + methods = [_bin_op(right, binary_opnode, op, left, reverse_context, reverse=True), + _bin_op(left, binary_opnode, op, right, context)] + else: + methods = [_bin_op(left, binary_opnode, op, right, context), + _bin_op(right, binary_opnode, op, left, reverse_context, reverse=True)] + return methods + + +def _get_aug_flow(left, left_type, aug_opnode, right, right_type, + context, reverse_context): + """Get the flow for augmented binary operations. + + The rules are a bit messy: + + * if left and right have the same type, then left.__augop__(right) + is first tried and then left.__op__(right). + * if left and right are unrelated typewise, then + left.__augop__(right) is tried, then left.__op__(right) + is tried and then right.__rop__(left) is tried. + * if left is a subtype of right, then left.__augop__(right) + is tried and then left.__op__(right). + * if left is a supertype of right, then left.__augop__(right) + is tried, then right.__rop__(left) and then + left.__op__(right) + """ + bin_op = aug_opnode.op.strip("=") + aug_op = aug_opnode.op + if _same_type(left_type, right_type): + methods = [_aug_op(left, aug_opnode, aug_op, right, context), + _bin_op(left, aug_opnode, bin_op, right, context)] + elif helpers.is_subtype(left_type, right_type): + methods = [_aug_op(left, aug_opnode, aug_op, right, context), + _bin_op(left, aug_opnode, bin_op, right, context)] + elif helpers.is_supertype(left_type, right_type): + methods = [_aug_op(left, aug_opnode, aug_op, right, context), + _bin_op(right, aug_opnode, bin_op, left, reverse_context, reverse=True), + _bin_op(left, aug_opnode, bin_op, right, context)] + else: + methods = [_aug_op(left, aug_opnode, aug_op, right, context), + _bin_op(left, aug_opnode, bin_op, right, context), + _bin_op(right, aug_opnode, bin_op, left, reverse_context, reverse=True)] + return methods + + +def _infer_binary_operation(left, right, binary_opnode, context, flow_factory): + """Infer a binary operation between a left operand and a right operand + + This is used by both normal binary operations and augmented binary + operations, the only difference is the flow factory used. + """ + + context, reverse_context = _get_binop_contexts(context, left, right) + left_type = helpers.object_type(left) + right_type = helpers.object_type(right) + methods = flow_factory(left, left_type, binary_opnode, right, right_type, + context, reverse_context) + for method in methods: try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand1.getattr(protocols.BIN_OP_METHOD[operator]) - yield operand1 - except: - if failures is None: - yield util.YES - else: - failures.append(operand1) + results = list(method()) + except AttributeError: + continue + except exceptions.AttributeInferenceError: + continue + except exceptions.InferenceError: + yield util.Uninferable + return + else: + if any(result is util.Uninferable for result in results): + yield util.Uninferable + return + + # TODO(cpopa): since the inference engine might return + # more values than are actually possible, we decide + # to return util.Uninferable if we have union types. + if all(map(_is_not_implemented, results)): + continue + not_implemented = sum(1 for result in results + if _is_not_implemented(result)) + if not_implemented and not_implemented != len(results): + # Can't decide yet what this is, not yet though. + yield util.Uninferable + return + + for result in results: + yield result + return + # TODO(cpopa): yield a BadBinaryOperationMessage here, + # since the operation is not supported + yield util.BadBinaryOperationMessage(left_type, binary_opnode.op, right_type) + + +def _infer_binop(self, context): + """Binary operation inferrence logic.""" + if context is None: + context = contextmod.InferenceContext() + left = self.left + right = self.right + + # we use two separate contexts for evaluating lhs and rhs because + # 1. evaluating lhs may leave some undesired entries in context.path + # which may not let us infer right value of rhs + lhs_context = context.clone() + rhs_context = context.clone() + + for lhs in left.infer(context=lhs_context): + if lhs is util.Uninferable: + # Don't know how to process this. + yield util.Uninferable + return + + for rhs in right.infer(context=rhs_context): + if rhs is util.Uninferable: + # Don't know how to process this. + yield util.Uninferable + return -@bases.yes_if_nothing_inferred + try: + for result in _infer_binary_operation(lhs, rhs, self, + context, _get_binop_flow): + yield result + except exceptions._NonDeducibleTypeHierarchy: + yield util.Uninferable + + +@decorators.yes_if_nothing_inferred +@decorators.path_wrapper def infer_binop(self, context=None): - failures = [] - for lhs in self.left.infer(context): - for val in _infer_binop(self, lhs, self.right, context, failures): - yield val - for lhs in failures: - for rhs in self.right.infer(context): - for val in _infer_binop(self, rhs, lhs, context): - yield val -nodes.BinOp._infer = bases.path_wrapper(infer_binop) + return _filter_operation_errors(self, _infer_binop, context, + util.BadBinaryOperationMessage) + +nodes.BinOp._infer_binop = _infer_binop +nodes.BinOp._infer = infer_binop + + +def _infer_augassign(self, context=None): + """Inference logic for augmented binary operations.""" + if context is None: + context = contextmod.InferenceContext() + + for lhs in self.target.infer_lhs(context=context): + if lhs is util.Uninferable: + # Don't know how to process this. + yield util.Uninferable + return + + # TODO(cpopa): if we have A() * A(), trying to infer + # the rhs with the same context will result in an + # inference error, so we create another context for it. + # This is a bug which should be fixed in InferenceContext at some point. + rhs_context = context.clone() + rhs_context.path = set() + for rhs in self.value.infer(context=rhs_context): + if rhs is util.Uninferable: + # Don't know how to process this. + yield util.Uninferable + return + + try: + results = _infer_binary_operation(lhs, rhs, self, context, _get_aug_flow) + except exceptions._NonDeducibleTypeHierarchy: + yield util.Uninferable + else: + for result in results: + yield result + + +@decorators.path_wrapper +def infer_augassign(self, context=None): + return _filter_operation_errors(self, _infer_augassign, context, + util.BadBinaryOperationMessage) + +nodes.AugAssign._infer_augassign = _infer_augassign +nodes.AugAssign._infer = infer_augassign + +# End of binary operation inference. def infer_arguments(self, context=None): name = context.lookupname if name is None: - raise exceptions.InferenceError() + raise exceptions.InferenceError(node=self, context=context) return protocols._arguments_infer_argname(self, name, context) nodes.Arguments._infer = infer_arguments -@bases.path_wrapper +@decorators.path_wrapper def infer_assign(self, context=None): """infer a AssignName/AssignAttr: need to inspect the RHS part of the assign node @@ -301,31 +766,20 @@ def infer_assign(self, context=None): nodes.AssignName._infer = infer_assign nodes.AssignAttr._infer = infer_assign -def infer_augassign(self, context=None): - failures = [] - for lhs in self.target.infer_lhs(context): - for val in _infer_binop(self, lhs, self.value, context, failures): - yield val - for lhs in failures: - for rhs in self.value.infer(context): - for val in _infer_binop(self, rhs, lhs, context): - yield val -nodes.AugAssign._infer = bases.path_wrapper(infer_augassign) - # no infer method on DelName and DelAttr (expected InferenceError) -@bases.path_wrapper +@decorators.path_wrapper def infer_empty_node(self, context=None): if not self.has_underlying_object(): - yield util.YES + yield util.Uninferable else: try: for inferred in MANAGER.infer_ast_from_something(self.object, context=context): yield inferred except exceptions.AstroidError: - yield util.YES + yield util.Uninferable nodes.EmptyNode._infer = infer_empty_node @@ -337,7 +791,6 @@ def infer_index(self, context=None): # will be solved. def instance_getitem(self, index, context=None): # Rewrap index to Const for this case - index = nodes.Const(index) if context: new_context = context.clone() else: @@ -349,11 +802,15 @@ def instance_getitem(self, index, context=None): method = next(self.igetattr('__getitem__', context=context)) if not isinstance(method, bases.BoundMethod): - raise exceptions.InferenceError + raise exceptions.InferenceError( + 'Could not find __getitem__ for {node!r}.', + node=self, context=context) try: return next(method.infer_call_result(self, new_context)) except StopIteration: - raise exceptions.InferenceError + util.reraise(exceptions.InferenceError( + message='Inference for {node!r}[{index!s}] failed.', + node=self, index=index, context=context)) bases.Instance.getitem = instance_getitem diff --git a/pymode/libs/astroid/tests/__init__.py b/pymode/libs/astroid/interpreter/__init__.py similarity index 100% rename from pymode/libs/astroid/tests/__init__.py rename to pymode/libs/astroid/interpreter/__init__.py diff --git a/pymode/libs/astroid/tests/testdata/python2/data/find_test/__init__.py b/pymode/libs/astroid/interpreter/_import/__init__.py similarity index 100% rename from pymode/libs/astroid/tests/testdata/python2/data/find_test/__init__.py rename to pymode/libs/astroid/interpreter/_import/__init__.py diff --git a/pymode/libs/astroid/interpreter/_import/spec.py b/pymode/libs/astroid/interpreter/_import/spec.py new file mode 100644 index 00000000..1edd23d6 --- /dev/null +++ b/pymode/libs/astroid/interpreter/_import/spec.py @@ -0,0 +1,287 @@ +# Copyright (c) 2016 Claudiu Popa + +import abc +import collections +import enum +import imp +import os +import sys +import zipimport +try: + import importlib.machinery + _HAS_MACHINERY = True +except ImportError: + _HAS_MACHINERY = False + +try: + from functools import lru_cache +except ImportError: + from backports.functools_lru_cache import lru_cache + +from . import util + +ModuleType = enum.Enum('ModuleType', 'C_BUILTIN C_EXTENSION PKG_DIRECTORY ' + 'PY_CODERESOURCE PY_COMPILED PY_FROZEN PY_RESOURCE ' + 'PY_SOURCE PY_ZIPMODULE PY_NAMESPACE') +_ImpTypes = {imp.C_BUILTIN: ModuleType.C_BUILTIN, + imp.C_EXTENSION: ModuleType.C_EXTENSION, + imp.PKG_DIRECTORY: ModuleType.PKG_DIRECTORY, + imp.PY_COMPILED: ModuleType.PY_COMPILED, + imp.PY_FROZEN: ModuleType.PY_FROZEN, + imp.PY_SOURCE: ModuleType.PY_SOURCE, + } +if hasattr(imp, 'PY_RESOURCE'): + _ImpTypes[imp.PY_RESOURCE] = ModuleType.PY_RESOURCE +if hasattr(imp, 'PY_CODERESOURCE'): + _ImpTypes[imp.PY_CODERESOURCE] = ModuleType.PY_CODERESOURCE + +def _imp_type_to_module_type(imp_type): + return _ImpTypes[imp_type] + +_ModuleSpec = collections.namedtuple('_ModuleSpec', 'name type location ' + 'origin submodule_search_locations') + +class ModuleSpec(_ModuleSpec): + """Defines a class similar to PEP 420's ModuleSpec + + A module spec defines a name of a module, its type, location + and where submodules can be found, if the module is a package. + """ + + def __new__(cls, name, module_type, location=None, origin=None, + submodule_search_locations=None): + return _ModuleSpec.__new__(cls, name=name, type=module_type, + location=location, origin=origin, + submodule_search_locations=submodule_search_locations) + + +class Finder(object): + """A finder is a class which knows how to find a particular module.""" + + def __init__(self, path=None): + self._path = path or sys.path + + @abc.abstractmethod + def find_module(self, modname, module_parts, processed, submodule_path): + """Find the given module + + Each finder is responsible for each protocol of finding, as long as + they all return a ModuleSpec. + + :param str modname: The module which needs to be searched. + :param list module_parts: It should be a list of strings, + where each part contributes to the module's + namespace. + :param list processed: What parts from the module parts were processed + so far. + :param list submodule_path: A list of paths where the module + can be looked into. + :returns: A ModuleSpec, describing how and where the module was found, + None, otherwise. + """ + + def contribute_to_path(self, spec, processed): + """Get a list of extra paths where this finder can search.""" + + +class ImpFinder(Finder): + """A finder based on the imp module.""" + + def find_module(self, modname, module_parts, processed, submodule_path): + if submodule_path is not None: + submodule_path = list(submodule_path) + try: + stream, mp_filename, mp_desc = imp.find_module(modname, submodule_path) + except ImportError: + return None + + # Close resources. + if stream: + stream.close() + + return ModuleSpec(name=modname, location=mp_filename, + module_type=_imp_type_to_module_type(mp_desc[2])) + + def contribute_to_path(self, spec, processed): + if spec.location is None: + # Builtin. + return None + + if _is_setuptools_namespace(spec.location): + # extend_path is called, search sys.path for module/packages + # of this name see pkgutil.extend_path documentation + path = [os.path.join(p, *processed) for p in sys.path + if os.path.isdir(os.path.join(p, *processed))] + else: + path = [spec.location] + return path + + +class ExplicitNamespacePackageFinder(ImpFinder): + """A finder for the explicit namespace packages, generated through pkg_resources.""" + + def find_module(self, modname, module_parts, processed, submodule_path): + if util.is_namespace(modname) and modname in sys.modules: + submodule_path = sys.modules[modname].__path__ + return ModuleSpec(name=modname, location='', + origin='namespace', + module_type=ModuleType.PY_NAMESPACE, + submodule_search_locations=submodule_path) + + + def contribute_to_path(self, spec, processed): + return spec.submodule_search_locations + + +class ZipFinder(Finder): + """Finder that knows how to find a module inside zip files.""" + + def __init__(self, path): + super(ZipFinder, self).__init__(path) + self._zipimporters = _precache_zipimporters(path) + + def find_module(self, modname, module_parts, processed, submodule_path): + try: + file_type, filename, path = _search_zip(module_parts, self._zipimporters) + except ImportError: + return None + + return ModuleSpec(name=modname, location=filename, + origin='egg', module_type=file_type, + submodule_search_locations=path) + + +class PathSpecFinder(Finder): + """Finder based on importlib.machinery.PathFinder.""" + + def find_module(self, modname, module_parts, processed, submodule_path): + spec = importlib.machinery.PathFinder.find_spec(modname, path=submodule_path) + if spec: + location = spec.origin if spec.origin != 'namespace' else None + module_type = ModuleType.PY_NAMESPACE if spec.origin == 'namespace' else None + spec = ModuleSpec(name=spec.name, location=location, + origin=spec.origin, module_type=module_type, + submodule_search_locations=list(spec.submodule_search_locations + or [])) + return spec + + def contribute_to_path(self, spec, processed): + if spec.type == ModuleType.PY_NAMESPACE: + return spec.submodule_search_locations + return None + + +_SPEC_FINDERS = ( + ImpFinder, + ZipFinder, +) +if _HAS_MACHINERY and sys.version_info[:2] > (3, 3): + _SPEC_FINDERS += (PathSpecFinder, ) +_SPEC_FINDERS += (ExplicitNamespacePackageFinder, ) + + +def _is_setuptools_namespace(location): + try: + with open(os.path.join(location, '__init__.py'), 'rb') as stream: + data = stream.read(4096) + except IOError: + pass + else: + extend_path = b'pkgutil' in data and b'extend_path' in data + declare_namespace = ( + b"pkg_resources" in data + and b"declare_namespace(__name__)" in data) + return extend_path or declare_namespace + + +@lru_cache() +def _cached_set_diff(left, right): + result = set(left) + result.difference_update(right) + return result + + +def _precache_zipimporters(path=None): + pic = sys.path_importer_cache + + # When measured, despite having the same complexity (O(n)), + # converting to tuples and then caching the conversion to sets + # and the set difference is faster than converting to sets + # and then only caching the set difference. + + req_paths = tuple(path or sys.path) + cached_paths = tuple(pic) + new_paths = _cached_set_diff(req_paths, cached_paths) + for entry_path in new_paths: + try: + pic[entry_path] = zipimport.zipimporter(entry_path) + except zipimport.ZipImportError: + continue + return pic + + +def _search_zip(modpath, pic): + for filepath, importer in list(pic.items()): + if importer is not None: + found = importer.find_module(modpath[0]) + if found: + if not importer.find_module(os.path.sep.join(modpath)): + raise ImportError('No module named %s in %s/%s' % ( + '.'.join(modpath[1:]), filepath, modpath)) + #import code; code.interact(local=locals()) + return (ModuleType.PY_ZIPMODULE, + os.path.abspath(filepath) + os.path.sep + os.path.sep.join(modpath), + filepath) + raise ImportError('No module named %s' % '.'.join(modpath)) + + +def _find_spec_with_path(search_path, modname, module_parts, processed, submodule_path): + finders = [finder(search_path) for finder in _SPEC_FINDERS] + for finder in finders: + spec = finder.find_module(modname, module_parts, processed, submodule_path) + if spec is None: + continue + return finder, spec + + raise ImportError('No module named %s' % '.'.join(module_parts)) + + +def find_spec(modpath, path=None): + """Find a spec for the given module. + + :type modpath: list or tuple + :param modpath: + split module's name (i.e name of a module or package split + on '.'), with leading empty strings for explicit relative import + + :type path: list or None + :param path: + optional list of path where the module or package should be + searched (use sys.path if nothing or None is given) + + :rtype: ModuleSpec + :return: A module spec, which describes how the module was + found and where. + """ + _path = path or sys.path + + # Need a copy for not mutating the argument. + modpath = modpath[:] + + submodule_path = None + module_parts = modpath[:] + processed = [] + + while modpath: + modname = modpath.pop(0) + finder, spec = _find_spec_with_path(_path, modname, + module_parts, processed, + submodule_path or path) + processed.append(modname) + if modpath: + submodule_path = finder.contribute_to_path(spec, processed) + + if spec.type == ModuleType.PKG_DIRECTORY: + spec = spec._replace(submodule_search_locations=submodule_path) + + return spec diff --git a/pymode/libs/astroid/interpreter/_import/util.py b/pymode/libs/astroid/interpreter/_import/util.py new file mode 100644 index 00000000..79ff4e0a --- /dev/null +++ b/pymode/libs/astroid/interpreter/_import/util.py @@ -0,0 +1,12 @@ +# Copyright (c) 2016 Claudiu Popa + +try: + import pkg_resources +except ImportError: + pkg_resources = None + + +def is_namespace(modname): + # pylint: disable=no-member; astroid issue #290, modifying globals at runtime. + return (pkg_resources is not None + and modname in pkg_resources._namespace_packages) diff --git a/pymode/libs/astroid/interpreter/dunder_lookup.py b/pymode/libs/astroid/interpreter/dunder_lookup.py new file mode 100644 index 00000000..424ed01f --- /dev/null +++ b/pymode/libs/astroid/interpreter/dunder_lookup.py @@ -0,0 +1,81 @@ +# Copyright (c) 2016 Claudiu Popa +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +"""Contains logic for retrieving special methods. + +This implementation does not rely on the dot attribute access +logic, found in ``.getattr()``. The difference between these two +is that the dunder methods are looked with the type slots +(you can find more about these here +http://lucumr.pocoo.org/2014/8/16/the-python-i-would-like-to-see/) +As such, the lookup for the special methods is actually simpler than +the dot attribute access. +""" +import itertools + +import astroid +from astroid import exceptions + + +def _lookup_in_mro(node, name): + attrs = node.locals.get(name, []) + + nodes = itertools.chain.from_iterable( + ancestor.locals.get(name, []) + for ancestor in node.ancestors(recurs=True) + ) + values = list(itertools.chain(attrs, nodes)) + if not values: + raise exceptions.AttributeInferenceError( + attribute=name, + target=node + ) + + return values + + +def lookup(node, name): + """Lookup the given special method name in the given *node* + + If the special method was found, then a list of attributes + will be returned. Otherwise, `astroid.AttributeInferenceError` + is going to be raised. + """ + if isinstance(node, (astroid.List, + astroid.Tuple, + astroid.Const, + astroid.Dict, + astroid.Set)): + return _builtin_lookup(node, name) + elif isinstance(node, astroid.Instance): + return _lookup_in_mro(node, name) + elif isinstance(node, astroid.ClassDef): + return _class_lookup(node, name) + + raise exceptions.AttributeInferenceError( + attribute=name, + target=node + ) + + +def _class_lookup(node, name): + metaclass = node.metaclass() + if metaclass is None: + raise exceptions.AttributeInferenceError( + attribute=name, + target=node + ) + + return _lookup_in_mro(metaclass, name) + + +def _builtin_lookup(node, name): + values = node.locals.get(name, []) + if not values: + raise exceptions.AttributeInferenceError( + attribute=name, + target=node + ) + + return values diff --git a/pymode/libs/astroid/interpreter/objectmodel.py b/pymode/libs/astroid/interpreter/objectmodel.py new file mode 100644 index 00000000..067095cc --- /dev/null +++ b/pymode/libs/astroid/interpreter/objectmodel.py @@ -0,0 +1,632 @@ +# Copyright (c) 2016 Claudiu Popa +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER +""" +Data object model, as per https://docs.python.org/3/reference/datamodel.html. + +This module describes, at least partially, a data object model for some +of astroid's nodes. The model contains special attributes that nodes such +as functions, classes, modules etc have, such as __doc__, __class__, +__module__ etc, being used when doing attribute lookups over nodes. + +For instance, inferring `obj.__class__` will first trigger an inference +of the `obj` variable. If it was succesfully inferred, then an attribute +`__class__ will be looked for in the inferred object. This is the part +where the data model occurs. The model is attached to those nodes +and the lookup mechanism will try to see if attributes such as +`__class__` are defined by the model or not. If they are defined, +the model will be requested to return the corresponding value of that +attribute. Thus the model can be viewed as a special part of the lookup +mechanism. +""" + +try: + from functools import lru_cache +except ImportError: + from backports.functools_lru_cache import lru_cache + +import itertools +import pprint +import os +import types + +import six + +import astroid +from astroid import context as contextmod +from astroid import exceptions +from astroid import node_classes + + +def _dunder_dict(instance, attributes): + obj = node_classes.Dict(parent=instance) + + # Convert the keys to node strings + keys = [node_classes.Const(value=value, parent=obj) + for value in list(attributes.keys())] + + # The original attribute has a list of elements for each key, + # but that is not useful for retrieving the special attribute's value. + # In this case, we're picking the last value from each list. + values = [elem[-1] for elem in attributes.values()] + + obj.postinit(list(zip(keys, values))) + return obj + + +class ObjectModel(object): + + def __init__(self): + self._instance = None + + def __repr__(self): + result = [] + cname = type(self).__name__ + string = '%(cname)s(%(fields)s)' + alignment = len(cname) + 1 + for field in sorted(self.attributes()): + width = 80 - len(field) - alignment + lines = pprint.pformat(field, indent=2, + width=width).splitlines(True) + + inner = [lines[0]] + for line in lines[1:]: + inner.append(' ' * alignment + line) + result.append(field) + + return string % {'cname': cname, + 'fields': (',\n' + ' ' * alignment).join(result)} + + def __call__(self, instance): + self._instance = instance + return self + + def __get__(self, instance, cls=None): + # ObjectModel needs to be a descriptor so that just doing + # `special_attributes = SomeObjectModel` should be enough in the body of a node. + # But at the same time, node.special_attributes should return an object + # which can be used for manipulating the special attributes. That's the reason + # we pass the instance through which it got accessed to ObjectModel.__call__, + # returning itself afterwards, so we can still have access to the + # underlying data model and to the instance for which it got accessed. + return self(instance) + + def __contains__(self, name): + return name in self.attributes() + + @lru_cache(maxsize=None) + def attributes(self): + """Get the attributes which are exported by this object model.""" + return [obj[2:] for obj in dir(self) if obj.startswith('py')] + + def lookup(self, name): + """Look up the given *name* in the current model + + It should return an AST or an interpreter object, + but if the name is not found, then an AttributeInferenceError will be raised. + """ + + if name in self.attributes(): + return getattr(self, "py" + name) + raise exceptions.AttributeInferenceError(target=self._instance, attribute=name) + + +class ModuleModel(ObjectModel): + + def _builtins(self): + builtins = astroid.MANAGER.astroid_cache[six.moves.builtins.__name__] + return builtins.special_attributes.lookup('__dict__') + + if six.PY3: + @property + def pybuiltins(self): + return self._builtins() + + else: + @property + def py__builtin__(self): + return self._builtins() + + # __path__ is a standard attribute on *packages* not + # non-package modules. The only mention of it in the + # official 2.7 documentation I can find is in the + # tutorial. + + @property + def py__path__(self): + if not self._instance.package: + raise exceptions.AttributeInferenceError(target=self._instance, + attribute='__path__') + + path = os.path.dirname(self._instance.file) + path_obj = node_classes.Const(value=path, parent=self._instance) + + container = node_classes.List(parent=self._instance) + container.postinit([path_obj]) + + return container + + @property + def py__name__(self): + return node_classes.Const(value=self._instance.name, + parent=self._instance) + + @property + def py__doc__(self): + return node_classes.Const(value=self._instance.doc, + parent=self._instance) + + @property + def py__file__(self): + return node_classes.Const(value=self._instance.file, + parent=self._instance) + + @property + def py__dict__(self): + return _dunder_dict(self._instance, self._instance.globals) + + # __package__ isn't mentioned anywhere outside a PEP: + # https://www.python.org/dev/peps/pep-0366/ + @property + def py__package__(self): + if not self._instance.package: + value = '' + else: + value = self._instance.name + + return node_classes.Const(value=value, parent=self._instance) + + # These are related to the Python 3 implementation of the + # import system, + # https://docs.python.org/3/reference/import.html#import-related-module-attributes + + @property + def py__spec__(self): + # No handling for now. + return node_classes.Unknown() + + @property + def py__loader__(self): + # No handling for now. + return node_classes.Unknown() + + @property + def py__cached__(self): + # No handling for now. + return node_classes.Unknown() + + +class FunctionModel(ObjectModel): + + @property + def py__name__(self): + return node_classes.Const(value=self._instance.name, + parent=self._instance) + + @property + def py__doc__(self): + return node_classes.Const(value=self._instance.doc, + parent=self._instance) + + @property + def py__qualname__(self): + return node_classes.Const(value=self._instance.qname(), + parent=self._instance) + + @property + def py__defaults__(self): + func = self._instance + if not func.args.defaults: + return node_classes.Const(value=None, parent=func) + + defaults_obj = node_classes.Tuple(parent=func) + defaults_obj.postinit(func.args.defaults) + return defaults_obj + + @property + def py__annotations__(self): + obj = node_classes.Dict(parent=self._instance) + + if not self._instance.returns: + returns = None + else: + returns = self._instance.returns + + args = self._instance.args + pair_annotations = itertools.chain( + six.moves.zip(args.args, args.annotations), + six.moves.zip(args.kwonlyargs, args.kwonlyargs_annotations) + ) + + annotations = { + arg.name: annotation + for (arg, annotation) in pair_annotations + if annotation + } + if args.varargannotation: + annotations[args.vararg] = args.varargannotation + if args.kwargannotation: + annotations[args.kwarg] = args.kwargannotation + if returns: + annotations['return'] = returns + + items = [(node_classes.Const(key, parent=obj), value) + for (key, value) in annotations.items()] + + obj.postinit(items) + return obj + + @property + def py__dict__(self): + return node_classes.Dict(parent=self._instance) + + py__globals__ = py__dict__ + + @property + def py__kwdefaults__(self): + + def _default_args(args, parent): + for arg in args.kwonlyargs: + try: + default = args.default_value(arg.name) + except exceptions.NoDefault: + continue + + name = node_classes.Const(arg.name, parent=parent) + yield name, default + + args = self._instance.args + obj = node_classes.Dict(parent=self._instance) + defaults = dict(_default_args(args, obj)) + + obj.postinit(list(defaults.items())) + return obj + + @property + def py__module__(self): + return node_classes.Const(self._instance.root().qname()) + + @property + def py__get__(self): + from astroid import bases + + func = self._instance + + class DescriptorBoundMethod(bases.BoundMethod): + """Bound method which knows how to understand calling descriptor binding.""" + def infer_call_result(self, caller, context=None): + if len(caller.args) != 2: + raise exceptions.InferenceError( + "Invalid arguments for descriptor binding", + target=self, context=context) + + context = contextmod.copy_context(context) + cls = next(caller.args[0].infer(context=context)) + + # Rebuild the original value, but with the parent set as the + # class where it will be bound. + new_func = func.__class__(name=func.name, doc=func.doc, + lineno=func.lineno, col_offset=func.col_offset, + parent=cls) + # pylint: disable=no-member + new_func.postinit(func.args, func.body, + func.decorators, func.returns) + + # Build a proper bound method that points to our newly built function. + proxy = bases.UnboundMethod(new_func) + yield bases.BoundMethod(proxy=proxy, bound=cls) + + return DescriptorBoundMethod(proxy=self._instance, bound=self._instance) + + # These are here just for completion. + @property + def py__ne__(self): + return node_classes.Unknown() + + py__subclasshook__ = py__ne__ + py__str__ = py__ne__ + py__sizeof__ = py__ne__ + py__setattr__ = py__ne__ + py__repr__ = py__ne__ + py__reduce__ = py__ne__ + py__reduce_ex__ = py__ne__ + py__new__ = py__ne__ + py__lt__ = py__ne__ + py__eq__ = py__ne__ + py__gt__ = py__ne__ + py__format__ = py__ne__ + py__delattr__ = py__ne__ + py__getattribute__ = py__ne__ + py__hash__ = py__ne__ + py__init__ = py__ne__ + py__dir__ = py__ne__ + py__call__ = py__ne__ + py__class__ = py__ne__ + py__closure__ = py__ne__ + py__code__ = py__ne__ + + if six.PY2: + pyfunc_name = py__name__ + pyfunc_doc = py__doc__ + pyfunc_globals = py__globals__ + pyfunc_dict = py__dict__ + pyfunc_defaults = py__defaults__ + pyfunc_code = py__code__ + pyfunc_closure = py__closure__ + + +class ClassModel(ObjectModel): + + @property + def py__module__(self): + return node_classes.Const(self._instance.root().qname()) + + @property + def py__name__(self): + return node_classes.Const(self._instance.name) + + @property + def py__qualname__(self): + return node_classes.Const(self._instance.qname()) + + @property + def py__doc__(self): + return node_classes.Const(self._instance.doc) + + @property + def py__mro__(self): + if not self._instance.newstyle: + raise exceptions.AttributeInferenceError(target=self._instance, + attribute='__mro__') + + mro = self._instance.mro() + obj = node_classes.Tuple(parent=self._instance) + obj.postinit(mro) + return obj + + @property + def pymro(self): + if not self._instance.newstyle: + raise exceptions.AttributeInferenceError(target=self._instance, + attribute='mro') + + from astroid import bases + + other_self = self + + # Cls.mro is a method and we need to return one in order to have a proper inference. + # The method we're returning is capable of inferring the underlying MRO though. + class MroBoundMethod(bases.BoundMethod): + def infer_call_result(self, caller, context=None): + yield other_self.py__mro__ + + implicit_metaclass = self._instance.implicit_metaclass() + mro_method = implicit_metaclass.locals['mro'][0] + return MroBoundMethod(proxy=mro_method, bound=implicit_metaclass) + + @property + def py__bases__(self): + obj = node_classes.Tuple() + context = contextmod.InferenceContext() + elts = list(self._instance._inferred_bases(context)) + obj.postinit(elts=elts) + return obj + + @property + def py__class__(self): + from astroid import helpers + return helpers.object_type(self._instance) + + @property + def py__subclasses__(self): + """Get the subclasses of the underlying class + + This looks only in the current module for retrieving the subclasses, + thus it might miss a couple of them. + """ + from astroid import bases + from astroid import scoped_nodes + + if not self._instance.newstyle: + raise exceptions.AttributeInferenceError(target=self._instance, + attribute='__subclasses__') + + qname = self._instance.qname() + root = self._instance.root() + classes = [cls for cls in root.nodes_of_class(scoped_nodes.ClassDef) + if cls != self._instance and cls.is_subtype_of(qname)] + + obj = node_classes.List(parent=self._instance) + obj.postinit(classes) + + class SubclassesBoundMethod(bases.BoundMethod): + def infer_call_result(self, caller, context=None): + yield obj + + implicit_metaclass = self._instance.implicit_metaclass() + subclasses_method = implicit_metaclass.locals['__subclasses__'][0] + return SubclassesBoundMethod(proxy=subclasses_method, + bound=implicit_metaclass) + + @property + def py__dict__(self): + return node_classes.Dict(parent=self._instance) + + +class SuperModel(ObjectModel): + + @property + def py__thisclass__(self): + return self._instance.mro_pointer + + @property + def py__self_class__(self): + return self._instance._self_class + + @property + def py__self__(self): + return self._instance.type + + @property + def py__class__(self): + return self._instance._proxied + + +class UnboundMethodModel(ObjectModel): + + @property + def py__class__(self): + from astroid import helpers + return helpers.object_type(self._instance) + + @property + def py__func__(self): + return self._instance._proxied + + @property + def py__self__(self): + return node_classes.Const(value=None, parent=self._instance) + + pyim_func = py__func__ + pyim_class = py__class__ + pyim_self = py__self__ + + +class BoundMethodModel(FunctionModel): + + @property + def py__func__(self): + return self._instance._proxied._proxied + + @property + def py__self__(self): + return self._instance.bound + + +class GeneratorModel(FunctionModel): + + def __new__(cls, *args, **kwargs): + # Append the values from the GeneratorType unto this object. + ret = super(GeneratorModel, cls).__new__(cls, *args, **kwargs) + generator = astroid.MANAGER.astroid_cache[six.moves.builtins.__name__]['generator'] + for name, values in generator.locals.items(): + print(name, values) + method = values[0] + patched = lambda cls, meth=method: meth + + setattr(type(ret), 'py' + name, property(patched)) + + return ret + + @property + def py__name__(self): + return node_classes.Const(value=self._instance.parent.name, + parent=self._instance) + + @property + def py__doc__(self): + return node_classes.Const(value=self._instance.parent.doc, + parent=self._instance) + + +class InstanceModel(ObjectModel): + + @property + def py__class__(self): + return self._instance._proxied + + @property + def py__module__(self): + return node_classes.Const(self._instance.root().qname()) + + @property + def py__doc__(self): + return node_classes.Const(self._instance.doc) + + @property + def py__dict__(self): + return _dunder_dict(self._instance, self._instance.instance_attrs) + + +class ExceptionInstanceModel(InstanceModel): + + @property + def pyargs(self): + message = node_classes.Const('') + args = node_classes.Tuple(parent=self._instance) + args.postinit((message, )) + return args + + if six.PY3: + # It's available only on Python 3. + + @property + def py__traceback__(self): + builtins = astroid.MANAGER.astroid_cache[six.moves.builtins.__name__] + traceback_type = builtins[types.TracebackType.__name__] + return traceback_type.instantiate_class() + + if six.PY2: + # It's available only on Python 2. + + @property + def pymessage(self): + return node_classes.Const('') + + +class DictModel(ObjectModel): + + @property + def py__class__(self): + return self._instance._proxied + + def _generic_dict_attribute(self, obj, name): + """Generate a bound method that can infer the given *obj*.""" + + class DictMethodBoundMethod(astroid.BoundMethod): + def infer_call_result(self, caller, context=None): + yield obj + + meth = next(self._instance._proxied.igetattr(name)) + return DictMethodBoundMethod(proxy=meth, bound=self._instance) + + @property + def pyitems(self): + elems = [] + obj = node_classes.List(parent=self._instance) + for key, value in self._instance.items: + elem = node_classes.Tuple(parent=obj) + elem.postinit((key, value)) + elems.append(elem) + obj.postinit(elts=elems) + + if six.PY3: + from astroid import objects + obj = objects.DictItems(obj) + + return self._generic_dict_attribute(obj, 'items') + + @property + def pykeys(self): + keys = [key for (key, _) in self._instance.items] + obj = node_classes.List(parent=self._instance) + obj.postinit(elts=keys) + + if six.PY3: + from astroid import objects + obj = objects.DictKeys(obj) + + return self._generic_dict_attribute(obj, 'keys') + + @property + def pyvalues(self): + + values = [value for (_, value) in self._instance.items] + obj = node_classes.List(parent=self._instance) + obj.postinit(values) + + if six.PY3: + from astroid import objects + obj = objects.DictValues(obj) + + return self._generic_dict_attribute(obj, 'values') diff --git a/pymode/libs/astroid/manager.py b/pymode/libs/astroid/manager.py index d08adc29..4e7e35d0 100644 --- a/pymode/libs/astroid/manager.py +++ b/pymode/libs/astroid/manager.py @@ -1,33 +1,27 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """astroid manager: avoid multiple astroid build of a same module when possible by providing a class responsible to get astroid representation from various source and using a cache of built modules) """ -from __future__ import print_function -import imp import os +import sys import zipimport +import six + from astroid import exceptions +from astroid.interpreter._import import spec from astroid import modutils from astroid import transforms +from astroid import util def safe_repr(obj): @@ -79,20 +73,24 @@ def ast_from_file(self, filepath, modname=None, fallback=True, source=False): modname = '.'.join(modutils.modpath_from_file(filepath)) except ImportError: modname = filepath - if modname in self.astroid_cache and self.astroid_cache[modname].source_file == filepath: + if modname in self.astroid_cache and self.astroid_cache[modname].file == filepath: return self.astroid_cache[modname] if source: from astroid.builder import AstroidBuilder return AstroidBuilder(self).file_build(filepath, modname) elif fallback and modname: return self.ast_from_module_name(modname) - raise exceptions.AstroidBuildingException( - 'unable to get astroid for file %s' % filepath) + raise exceptions.AstroidBuildingError( + 'Unable to build an AST for {path}.', path=filepath) def _build_stub_module(self, modname): from astroid.builder import AstroidBuilder return AstroidBuilder(self).string_build('', modname) + def _build_namespace_module(self, modname, path): + from astroid.builder import build_namespace_package_module + return build_namespace_package_module(modname, path) + def _can_load_extension(self, modname): if self.always_load_extensions: return True @@ -113,32 +111,52 @@ def ast_from_module_name(self, modname, context_file=None): if context_file: os.chdir(os.path.dirname(context_file)) try: - filepath, mp_type = self.file_from_module_name(modname, context_file) - if mp_type == modutils.PY_ZIPMODULE: - module = self.zip_import_data(filepath) + found_spec = self.file_from_module_name(modname, context_file) + # pylint: disable=no-member + if found_spec.type == spec.ModuleType.PY_ZIPMODULE: + # pylint: disable=no-member + module = self.zip_import_data(found_spec.location) if module is not None: return module - elif mp_type in (imp.C_BUILTIN, imp.C_EXTENSION): - if mp_type == imp.C_EXTENSION and not self._can_load_extension(modname): + + elif found_spec.type in (spec.ModuleType.C_BUILTIN, + spec.ModuleType.C_EXTENSION): + # pylint: disable=no-member + if (found_spec.type == spec.ModuleType.C_EXTENSION + and not self._can_load_extension(modname)): return self._build_stub_module(modname) try: module = modutils.load_module_from_name(modname) - except Exception as ex: - msg = 'Unable to load module %s (%s)' % (modname, ex) - raise exceptions.AstroidBuildingException(msg) + except Exception as ex: # pylint: disable=broad-except + util.reraise(exceptions.AstroidImportError( + 'Loading {modname} failed with:\n{error}', + modname=modname, path=found_spec.location, error=ex)) return self.ast_from_module(module, modname) - elif mp_type == imp.PY_COMPILED: - msg = "Unable to load compiled module %s" % (modname,) - raise exceptions.AstroidBuildingException(msg) - if filepath is None: - msg = "Unable to load module %s" % (modname,) - raise exceptions.AstroidBuildingException(msg) - return self.ast_from_file(filepath, modname, fallback=False) - except exceptions.AstroidBuildingException as e: + + elif found_spec.type == spec.ModuleType.PY_COMPILED: + raise exceptions.AstroidImportError( + "Unable to load compiled module {modname}.", + # pylint: disable=no-member + modname=modname, path=found_spec.location) + + elif found_spec.type == spec.ModuleType.PY_NAMESPACE: + return self._build_namespace_module(modname, + # pylint: disable=no-member + found_spec.submodule_search_locations) + + # pylint: disable=no-member + if found_spec.location is None: + raise exceptions.AstroidImportError( + "Can't find a file for module {modname}.", + modname=modname) + + # pylint: disable=no-member + return self.ast_from_file(found_spec.location, modname, fallback=False) + except exceptions.AstroidBuildingError as e: for hook in self._failed_import_hooks: try: return hook(modname) - except exceptions.AstroidBuildingException: + except exceptions.AstroidBuildingError: pass raise e finally: @@ -167,19 +185,23 @@ def zip_import_data(self, filepath): return None def file_from_module_name(self, modname, contextfile): - # pylint: disable=redefined-variable-type try: value = self._mod_file_cache[(modname, contextfile)] + traceback = sys.exc_info()[2] except KeyError: try: value = modutils.file_info_from_modpath( modname.split('.'), context_file=contextfile) + traceback = sys.exc_info()[2] except ImportError as ex: - msg = 'Unable to load module %s (%s)' % (modname, ex) - value = exceptions.AstroidBuildingException(msg) + value = exceptions.AstroidImportError( + 'Failed to import module {modname} with error:\n{error}.', + modname=modname, error=ex) + traceback = sys.exc_info()[2] self._mod_file_cache[(modname, contextfile)] = value - if isinstance(value, exceptions.AstroidBuildingException): - raise value + if isinstance(value, exceptions.AstroidBuildingError): + six.reraise(exceptions.AstroidBuildingError, + value, traceback) return value def ast_from_module(self, module, modname=None): @@ -203,8 +225,9 @@ def ast_from_class(self, klass, modname=None): try: modname = klass.__module__ except AttributeError: - msg = 'Unable to get module for class %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) + util.reraise(exceptions.AstroidBuildingError( + 'Unable to get module for class {class_name}.', + cls=klass, class_repr=safe_repr(klass), modname=modname)) modastroid = self.ast_from_module_name(modname) return modastroid.getattr(klass.__name__)[0] # XXX @@ -217,21 +240,23 @@ def infer_ast_from_something(self, obj, context=None): try: modname = klass.__module__ except AttributeError: - msg = 'Unable to get module for %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) - except Exception as ex: - msg = ('Unexpected error while retrieving module for %s: %s' - % (safe_repr(klass), ex)) - raise exceptions.AstroidBuildingException(msg) + util.reraise(exceptions.AstroidBuildingError( + 'Unable to get module for {class_repr}.', + cls=klass, class_repr=safe_repr(klass))) + except Exception as ex: # pylint: disable=broad-except + util.reraise(exceptions.AstroidImportError( + 'Unexpected error while retrieving module for {class_repr}:\n' + '{error}', cls=klass, class_repr=safe_repr(klass), error=ex)) try: name = klass.__name__ except AttributeError: - msg = 'Unable to get name for %s' % safe_repr(klass) - raise exceptions.AstroidBuildingException(msg) - except Exception as ex: - exc = ('Unexpected error while retrieving name for %s: %s' - % (safe_repr(klass), ex)) - raise exceptions.AstroidBuildingException(exc) + util.reraise(exceptions.AstroidBuildingError( + 'Unable to get name for {class_repr}:\n', + cls=klass, class_repr=safe_repr(klass))) + except Exception as ex: # pylint: disable=broad-except + util.reraise(exceptions.AstroidImportError( + 'Unexpected error while retrieving name for {class_repr}:\n' + '{error}', cls=klass, class_repr=safe_repr(klass), error=ex)) # take care, on living object __module__ is regularly wrong :( modastroid = self.ast_from_module_name(modname) if klass is obj: @@ -247,7 +272,7 @@ def register_failed_import_hook(self, hook): `hook` must be a function that accepts a single argument `modname` which contains the name of the module or package that could not be imported. If `hook` can resolve the import, must return a node of type `astroid.Module`, - otherwise, it must raise `AstroidBuildingException`. + otherwise, it must raise `AstroidBuildingError`. """ self._failed_import_hooks.append(hook) diff --git a/pymode/libs/astroid/mixins.py b/pymode/libs/astroid/mixins.py index 57082f0f..739828d5 100644 --- a/pymode/libs/astroid/mixins.py +++ b/pymode/libs/astroid/mixins.py @@ -1,20 +1,10 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2010-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """This module contains some mixins for the different nodes. """ @@ -48,7 +38,7 @@ class FilterStmtsMixin(object): """Mixin for statement filtering and assignment type""" def _get_filtered_stmts(self, _, node, _stmts, mystmt): - """method used in _filter_stmts to get statemtents and trigger break""" + """method used in _filter_stmts to get statements and trigger break""" if self.statement() is mystmt: # original node's statement is the assignment, only keep # current node (gen exp, list comp) @@ -124,15 +114,9 @@ def do_import_module(self, modname=None): if mymodule.relative_to_absolute_name(modname, level) == mymodule.name: # FIXME: we used to raise InferenceError here, but why ? return mymodule - try: - return mymodule.import_module(modname, level=level, - relative_only=level and level >= 1) - except exceptions.AstroidBuildingException as ex: - if isinstance(ex.args[0], SyntaxError): - raise exceptions.InferenceError(str(ex)) - raise exceptions.InferenceError(modname) - except SyntaxError as ex: - raise exceptions.InferenceError(str(ex)) + + return mymodule.import_module(modname, level=level, + relative_only=level and level >= 1) def real_name(self, asname): """get name from 'as' name""" @@ -144,4 +128,6 @@ def real_name(self, asname): _asname = name if asname == _asname: return name - raise exceptions.NotFoundError(asname) + raise exceptions.AttributeInferenceError( + 'Could not find original name for {attribute} in {target!r}', + target=self, attribute=asname) diff --git a/pymode/libs/astroid/modutils.py b/pymode/libs/astroid/modutils.py index 31104cb5..f17bfdab 100644 --- a/pymode/libs/astroid/modutils.py +++ b/pymode/libs/astroid/modutils.py @@ -1,20 +1,13 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# astroid 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 Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015 Radosław Ganczarek +# Copyright (c) 2016 Jakub Wilk + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Python modules manipulation utility functions. :type PY_SOURCE_EXTS: tuple(str) @@ -26,22 +19,21 @@ :type BUILTIN_MODULES: dict :var BUILTIN_MODULES: dictionary with builtin module names has key """ -from __future__ import with_statement - import imp import os import platform import sys -from distutils.sysconfig import get_python_lib +from distutils.sysconfig import get_python_lib # pylint: disable=import-error +# pylint: disable=import-error, no-name-in-module from distutils.errors import DistutilsPlatformError -import zipimport +# distutils is replaced by virtualenv with a module that does +# weird path manipulations in order to get to the +# real distutils module. -try: - import pkg_resources -except ImportError: - pkg_resources = None +import six -PY_ZIPMODULE = object() +from .interpreter._import import spec +from .interpreter._import import util if sys.platform.startswith('win'): PY_SOURCE_EXTS = ('py', 'pyw') @@ -70,10 +62,18 @@ if os.name == 'nt': STD_LIB_DIRS.add(os.path.join(sys.prefix, 'dlls')) try: - # real_prefix is defined when running inside virtualenv. + # real_prefix is defined when running inside virtual environments, + # created with the **virtualenv** library. STD_LIB_DIRS.add(os.path.join(sys.real_prefix, 'dlls')) except AttributeError: - pass + # sys.base_exec_prefix is always defined, but in a virtual environment + # created with the stdlib **venv** module, it points to the original + # installation, if the virtual env is activated. + try: + STD_LIB_DIRS.add(os.path.join(sys.base_exec_prefix, 'dlls')) + except AttributeError: + pass + if platform.python_implementation() == 'PyPy': _root = os.path.join(sys.prefix, 'lib_pypy') STD_LIB_DIRS.add(_root) @@ -120,6 +120,10 @@ def _normalize_path(path): return os.path.normcase(os.path.abspath(path)) +def _canonicalize_path(path): + return os.path.realpath(os.path.expanduser(path)) + + def _path_from_filename(filename, is_jython=IS_JYTHON): if not is_jython: if sys.version_info > (3, 0): @@ -187,11 +191,11 @@ def load_module_from_name(dotted_name, path=None, use_sys=True): def load_module_from_modpath(parts, path=None, use_sys=1): - """Load a python module from its splitted name. + """Load a python module from its split name. :type parts: list(str) or tuple(str) :param parts: - python name of a module or package splitted on '.' + python name of a module or package split on '.' :type path: list or None :param path: @@ -234,7 +238,7 @@ def load_module_from_modpath(parts, path=None, use_sys=1): setattr(prevmodule, part, module) _file = getattr(module, '__file__', '') prevmodule = module - if not _file and _is_namespace(curname): + if not _file and util.is_namespace(curname): continue if not _file and len(modpath) != len(parts): raise ImportError('no module in %s' % '.'.join(parts[len(modpath):])) @@ -268,20 +272,48 @@ def load_module_from_file(filepath, path=None, use_sys=True, extrapath=None): return load_module_from_modpath(modpath, path, use_sys) -def _check_init(path, mod_path): +def check_modpath_has_init(path, mod_path): """check there are some __init__.py all along the way""" modpath = [] for part in mod_path: modpath.append(part) path = os.path.join(path, part) - if not _is_namespace('.'.join(modpath)) and not _has_init(path): - return False + if not _has_init(path): + old_namespace = util.is_namespace('.'.join(modpath)) + if not old_namespace: + return False return True +def modpath_from_file_with_callback(filename, extrapath=None, is_package_cb=None): + filename = _path_from_filename(filename) + filename = os.path.realpath(os.path.expanduser(filename)) + base = os.path.splitext(filename)[0] + + if extrapath is not None: + for path_ in six.moves.map(_canonicalize_path, extrapath): + path = os.path.abspath(path_) + if path and os.path.normcase(base[:len(path)]) == os.path.normcase(path): + submodpath = [pkg for pkg in base[len(path):].split(os.sep) + if pkg] + if is_package_cb(path, submodpath[:-1]): + return extrapath[path_].split('.') + submodpath + + for path in six.moves.map(_canonicalize_path, sys.path): + path = _cache_normalize_path(path) + if path and os.path.normcase(base).startswith(path): + modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] + if is_package_cb(path, modpath[:-1]): + return modpath + + raise ImportError('Unable to find module for %s in %s' % ( + filename, ', \n'.join(sys.path))) + + + def modpath_from_file(filename, extrapath=None): - """given a file path return the corresponding splitted module's name - (i.e name of a module or package splitted on '.') + """given a file path return the corresponding split module's name + (i.e name of a module or package split on '.') :type filename: str :param filename: file's path for which we want the module's name @@ -289,7 +321,7 @@ def modpath_from_file(filename, extrapath=None): :type extrapath: dict :param extrapath: optional extra search path, with path as key and package name for the path - as value. This is usually useful to handle package splitted in multiple + as value. This is usually useful to handle package split in multiple directories using __path__ trick. @@ -297,40 +329,22 @@ def modpath_from_file(filename, extrapath=None): if the corresponding module's name has not been found :rtype: list(str) - :return: the corresponding splitted module's name + :return: the corresponding split module's name """ - filename = _path_from_filename(filename) - filename = os.path.abspath(filename) - base = os.path.splitext(filename)[0] - if extrapath is not None: - for path_ in extrapath: - path = os.path.abspath(path_) - if path and os.path.normcase(base[:len(path)]) == os.path.normcase(path): - submodpath = [pkg for pkg in base[len(path):].split(os.sep) - if pkg] - if _check_init(path, submodpath[:-1]): - return extrapath[path_].split('.') + submodpath - for path in sys.path: - path = _cache_normalize_path(path) - if path and os.path.normcase(base).startswith(path): - modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] - if _check_init(path, modpath[:-1]): - return modpath - raise ImportError('Unable to find module for %s in %s' % ( - filename, ', \n'.join(sys.path))) + return modpath_from_file_with_callback(filename, extrapath, check_modpath_has_init) def file_from_modpath(modpath, path=None, context_file=None): - return file_info_from_modpath(modpath, path, context_file)[0] + return file_info_from_modpath(modpath, path, context_file).location def file_info_from_modpath(modpath, path=None, context_file=None): - """given a mod path (i.e. splitted module / package name), return the + """given a mod path (i.e. split module / package name), return the corresponding file, giving priority to source file over precompiled file if it exists :type modpath: list or tuple :param modpath: - splitted module's name (i.e name of a module or package splitted + split module's name (i.e name of a module or package split on '.') (this means explicit relative imports that start with dots have empty strings in this list!) @@ -360,13 +374,13 @@ def file_info_from_modpath(modpath, path=None, context_file=None): if modpath[0] == 'xml': # handle _xmlplus try: - return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context) + return _spec_from_modpath(['_xmlplus'] + modpath[1:], path, context) except ImportError: - return _file_from_modpath(modpath, path, context) + return _spec_from_modpath(modpath, path, context) elif modpath == ['os', 'path']: # FIXME: currently ignoring search_path... - return os.path.__file__, imp.PY_SOURCE - return _file_from_modpath(modpath, path, context) + return spec.ModuleSpec(name='os.path', location=os.path.__file__, module_type=imp.PY_SOURCE) + return _spec_from_modpath(modpath, path, context) def get_module_part(dotted_name, context_file=None): @@ -422,13 +436,13 @@ def get_module_part(dotted_name, context_file=None): file_from_modpath(parts[starti:i+1], path=path, context_file=context_file) except ImportError: - if not i >= max(1, len(parts) - 2): + if i < max(1, len(parts) - 2): raise return '.'.join(parts[:i]) return dotted_name -def get_module_files(src_directory, blacklist): +def get_module_files(src_directory, blacklist, list_all=False): """given a package directory return a list of all available python module's files in the package and its subpackages @@ -440,6 +454,10 @@ def get_module_files(src_directory, blacklist): :param blacklist: iterable list of files or directories to ignore. + :type list_all: bool + :param list_all: + get files from all paths, including ones without __init__.py + :rtype: list :return: the list of all available python module's files in the package and @@ -449,7 +467,7 @@ def get_module_files(src_directory, blacklist): for directory, dirnames, filenames in os.walk(src_directory): _handle_blacklist(blacklist, dirnames, filenames) # check for __init__.py - if not '__init__.py' in filenames: + if not list_all and '__init__.py' not in filenames: dirnames[:] = () continue for filename in filenames: @@ -520,7 +538,7 @@ def is_standard_module(modname, std_path=None): # (sys and __builtin__ for instance) if filename is None: # we assume there are no namespaces in stdlib - return not _is_namespace(modname) + return not util.is_namespace(modname) filename = _normalize_path(filename) if filename.startswith(_cache_normalize_path(EXT_LIB_DIR)): return False @@ -565,159 +583,38 @@ def is_relative(modname, from_file): # internal only functions ##################################################### -def _file_from_modpath(modpath, path=None, context=None): - """given a mod path (i.e. splitted module / package name), return the - corresponding file +def _spec_from_modpath(modpath, path=None, context=None): + """given a mod path (i.e. split module / package name), return the + corresponding spec this function is used internally, see `file_from_modpath`'s documentation for more information """ - assert len(modpath) > 0 + assert modpath + location = None if context is not None: try: - mtype, mp_filename = _module_file(modpath, [context]) + found_spec = spec.find_spec(modpath, [context]) + location = found_spec.location except ImportError: - mtype, mp_filename = _module_file(modpath, path) + found_spec = spec.find_spec(modpath, path) + location = found_spec.location else: - mtype, mp_filename = _module_file(modpath, path) - if mtype == imp.PY_COMPILED: + found_spec = spec.find_spec(modpath, path) + if found_spec.type == spec.ModuleType.PY_COMPILED: try: - return get_source_file(mp_filename), imp.PY_SOURCE + location = get_source_file(found_spec.location) + return found_spec._replace(location=location, type=spec.ModuleType.PY_SOURCE) except NoSourceFile: - return mp_filename, imp.PY_COMPILED - elif mtype == imp.C_BUILTIN: + return found_spec._replace(location=location) + elif found_spec.type == spec.ModuleType.C_BUILTIN: # integrated builtin module - return None, imp.C_BUILTIN - elif mtype == imp.PKG_DIRECTORY: - mp_filename = _has_init(mp_filename) - mtype = imp.PY_SOURCE - return mp_filename, mtype - -def _search_zip(modpath, pic): - for filepath, importer in list(pic.items()): - if importer is not None: - if importer.find_module(modpath[0]): - if not importer.find_module(os.path.sep.join(modpath)): - raise ImportError('No module named %s in %s/%s' % ( - '.'.join(modpath[1:]), filepath, modpath)) - return (PY_ZIPMODULE, - os.path.abspath(filepath) + os.path.sep + os.path.sep.join(modpath), - filepath) - raise ImportError('No module named %s' % '.'.join(modpath)) - -try: - import pkg_resources -except ImportError: - pkg_resources = None - + return found_spec._replace(location=None) + elif found_spec.type == spec.ModuleType.PKG_DIRECTORY: + location = _has_init(found_spec.location) + return found_spec._replace(location=location, type=spec.ModuleType.PY_SOURCE) + return found_spec -def _is_namespace(modname): - return (pkg_resources is not None - and modname in pkg_resources._namespace_packages) - - -def _module_file(modpath, path=None): - """get a module type / file path - - :type modpath: list or tuple - :param modpath: - splitted module's name (i.e name of a module or package splitted - on '.'), with leading empty strings for explicit relative import - - :type path: list or None - :param path: - optional list of path where the module or package should be - searched (use sys.path if nothing or None is given) - - - :rtype: tuple(int, str) - :return: the module type flag and the file path for a module - """ - # egg support compat - try: - pic = sys.path_importer_cache - _path = (path is None and sys.path or path) - for __path in _path: - if not __path in pic: - try: - pic[__path] = zipimport.zipimporter(__path) - except zipimport.ZipImportError: - pic[__path] = None - checkeggs = True - except AttributeError: - checkeggs = False - # pkg_resources support (aka setuptools namespace packages) - if _is_namespace(modpath[0]) and modpath[0] in sys.modules: - # setuptools has added into sys.modules a module object with proper - # __path__, get back information from there - module = sys.modules[modpath.pop(0)] - path = list(module.__path__) - if not modpath: - return imp.C_BUILTIN, None - imported = [] - while modpath: - modname = modpath[0] - # take care to changes in find_module implementation wrt builtin modules - # - # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) - # >>> imp.find_module('posix') - # (None, 'posix', ('', '', 6)) - # - # Python 3.3.1 (default, Apr 26 2013, 12:08:46) - # >>> imp.find_module('posix') - # (None, None, ('', '', 6)) - try: - stream, mp_filename, mp_desc = imp.find_module(modname, path) - except ImportError: - if checkeggs: - return _search_zip(modpath, pic)[:2] - raise - else: - # Don't forget to close the stream to avoid - # spurious ResourceWarnings. - if stream: - stream.close() - - if checkeggs and mp_filename: - fullabspath = [_cache_normalize_path(x) for x in _path] - try: - pathindex = fullabspath.index(os.path.dirname(_normalize_path(mp_filename))) - emtype, emp_filename, zippath = _search_zip(modpath, pic) - if pathindex > _path.index(zippath): - # an egg takes priority - return emtype, emp_filename - except ValueError: - # XXX not in _path - pass - except ImportError: - pass - checkeggs = False - imported.append(modpath.pop(0)) - mtype = mp_desc[2] - if modpath: - if mtype != imp.PKG_DIRECTORY: - raise ImportError('No module %s in %s' % ('.'.join(modpath), - '.'.join(imported))) - # XXX guess if package is using pkgutil.extend_path by looking for - # those keywords in the first four Kbytes - try: - with open(os.path.join(mp_filename, '__init__.py'), 'rb') as stream: - data = stream.read(4096) - except IOError: - path = [mp_filename] - else: - extend_path = b'pkgutil' in data and b'extend_path' in data - declare_namespace = ( - b"pkg_resources" in data - and b"declare_namespace(__name__)" in data) - if extend_path or declare_namespace: - # extend_path is called, search sys.path for module/packages - # of this name see pkgutil.extend_path documentation - path = [os.path.join(p, *imported) for p in sys.path - if os.path.isdir(os.path.join(p, *imported))] - else: - path = [mp_filename] - return mtype, mp_filename def _is_python_file(filename): """return true if the given filename should be considered as a python file @@ -739,3 +636,10 @@ def _has_init(directory): if os.path.exists(mod_or_pack + '.' + ext): return mod_or_pack + '.' + ext return None + + +def is_namespace(specobj): + return specobj.type == spec.ModuleType.PY_NAMESPACE + +def is_directory(specobj): + return specobj.type == spec.ModuleType.PKG_DIRECTORY diff --git a/pymode/libs/astroid/node_classes.py b/pymode/libs/astroid/node_classes.py index ca773c3a..b4e71874 100644 --- a/pymode/libs/astroid/node_classes.py +++ b/pymode/libs/astroid/node_classes.py @@ -1,68 +1,72 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014, 2016 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2016 Jakub Wilk + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Module for some node classes. More nodes in scoped_nodes.py """ import abc +import pprint import warnings +try: + from functools import singledispatch as _singledispatch +except ImportError: + from singledispatch import singledispatch as _singledispatch -import lazy_object_proxy import six +from astroid import as_string from astroid import bases from astroid import context as contextmod from astroid import decorators from astroid import exceptions +from astroid import manager from astroid import mixins from astroid import util BUILTINS = six.moves.builtins.__name__ +MANAGER = manager.AstroidManager() -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred def unpack_infer(stmt, context=None): """recursively generate nodes inferred by the given statement. If the inferred value is a list or a tuple, recurse on the elements """ if isinstance(stmt, (List, Tuple)): for elt in stmt.elts: - if elt is util.YES: + if elt is util.Uninferable: yield elt continue for inferred_elt in unpack_infer(elt, context): yield inferred_elt - return + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=stmt, context=context)) # if inferred is a final node, return it and stop inferred = next(stmt.infer(context)) if inferred is stmt: yield inferred - return - # else, infer recursivly, except YES object that should be returned as is + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=stmt, context=context)) + # else, infer recursively, except Uninferable object that should be returned as is for inferred in stmt.infer(context): - if inferred is util.YES: + if inferred is util.Uninferable: yield inferred else: for inf_inf in unpack_infer(inferred, context): yield inf_inf + raise StopIteration(dict(node=stmt, context=context)) -def are_exclusive(stmt1, stmt2, exceptions=None): +def are_exclusive(stmt1, stmt2, exceptions=None): # pylint: disable=redefined-outer-name """return true if the two given statements are mutually exclusive `exceptions` may be a list of exception names. If specified, discard If @@ -100,12 +104,22 @@ def are_exclusive(stmt1, stmt2, exceptions=None): c2attr, c2node = node.locate_child(previous) c1attr, c1node = node.locate_child(children[node]) if c1node is not c2node: - if ((c2attr == 'body' - and c1attr == 'handlers' - and children[node].catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or - (c2attr == 'handlers' and c1attr == 'orelse') or - (c2attr == 'orelse' and c1attr == 'handlers')): + first_in_body_caught_by_handlers = ( + c2attr == 'handlers' + and c1attr == 'body' + and previous.catch(exceptions)) + second_in_body_caught_by_handlers = ( + c2attr == 'body' + and c1attr == 'handlers' + and children[node].catch(exceptions)) + first_in_else_other_in_handlers = ( + c2attr == 'handlers' and c1attr == 'orelse') + second_in_else_other_in_handlers = ( + c2attr == 'orelse' and c1attr == 'handlers') + if any((first_in_body_caught_by_handlers, + second_in_body_caught_by_handlers, + first_in_else_other_in_handlers, + second_in_else_other_in_handlers)): return True elif c2attr == 'handlers' and c1attr == 'handlers': return previous is not children[node] @@ -115,19 +129,563 @@ def are_exclusive(stmt1, stmt2, exceptions=None): return False +# getitem() helpers. + +_SLICE_SENTINEL = object() + + +def _slice_value(index, context=None): + """Get the value of the given slice index.""" + + if isinstance(index, Const): + if isinstance(index.value, (int, type(None))): + return index.value + elif index is None: + return None + else: + # Try to infer what the index actually is. + # Since we can't return all the possible values, + # we'll stop at the first possible value. + try: + inferred = next(index.infer(context=context)) + except exceptions.InferenceError: + pass + else: + if isinstance(inferred, Const): + if isinstance(inferred.value, (int, type(None))): + return inferred.value + + # Use a sentinel, because None can be a valid + # value that this function can return, + # as it is the case for unspecified bounds. + return _SLICE_SENTINEL + + +def _infer_slice(node, context=None): + lower = _slice_value(node.lower, context) + upper = _slice_value(node.upper, context) + step = _slice_value(node.step, context) + if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)): + return slice(lower, upper, step) + + raise exceptions.AstroidTypeError( + message='Could not infer slice used in subscript', + node=node, index=node.parent, context=context) + + +def _container_getitem(instance, elts, index, context=None): + """Get a slice or an item, using the given *index*, for the given sequence.""" + try: + if isinstance(index, Slice): + index_slice = _infer_slice(index, context=context) + new_cls = instance.__class__() + new_cls.elts = elts[index_slice] + new_cls.parent = instance.parent + return new_cls + elif isinstance(index, Const): + return elts[index.value] + except IndexError: + util.reraise(exceptions.AstroidIndexError( + message='Index {index!s} out of range', + node=instance, index=index, context=context)) + except TypeError as exc: + util.reraise(exceptions.AstroidTypeError( + message='Type error {error!r}', error=exc, + node=instance, index=index, context=context)) + + raise exceptions.AstroidTypeError( + 'Could not use %s as subscript index' % index + ) + + +class NodeNG(object): + """Base Class for all Astroid node classes. + + It represents a node of the new abstract syntax tree. + """ + is_statement = False + optional_assign = False # True for For (and for Comprehension if py <3.0) + is_function = False # True for FunctionDef nodes + # attributes below are set by the builder module or by raw factories + lineno = None + col_offset = None + # parent node in the tree + parent = None + # attributes containing child node(s) redefined in most concrete classes: + _astroid_fields = () + # attributes containing non-nodes: + _other_fields = () + # attributes containing AST-dependent fields: + _other_other_fields = () + # instance specific inference function infer(node, context) + _explicit_inference = None + + def __init__(self, lineno=None, col_offset=None, parent=None): + self.lineno = lineno + self.col_offset = col_offset + self.parent = parent + + def infer(self, context=None, **kwargs): + """main interface to the interface system, return a generator on inferred + values. + + If the instance has some explicit inference function set, it will be + called instead of the default interface. + """ + if self._explicit_inference is not None: + # explicit_inference is not bound, give it self explicitly + try: + # pylint: disable=not-callable + return self._explicit_inference(self, context, **kwargs) + except exceptions.UseInferenceDefault: + pass + + if not context: + return self._infer(context, **kwargs) + + key = (self, context.lookupname, + context.callcontext, context.boundnode) + if key in context.inferred: + return iter(context.inferred[key]) + + return context.cache_generator(key, self._infer(context, **kwargs)) + + def _repr_name(self): + """return self.name or self.attrname or '' for nice representation""" + return getattr(self, 'name', getattr(self, 'attrname', '')) + + def __str__(self): + rname = self._repr_name() + cname = type(self).__name__ + if rname: + string = '%(cname)s.%(rname)s(%(fields)s)' + alignment = len(cname) + len(rname) + 2 + else: + string = '%(cname)s(%(fields)s)' + alignment = len(cname) + 1 + result = [] + for field in self._other_fields + self._astroid_fields: + value = getattr(self, field) + width = 80 - len(field) - alignment + lines = pprint.pformat(value, indent=2, + width=width).splitlines(True) + + inner = [lines[0]] + for line in lines[1:]: + inner.append(' ' * alignment + line) + result.append('%s=%s' % (field, ''.join(inner))) + + return string % {'cname': cname, + 'rname': rname, + 'fields': (',\n' + ' ' * alignment).join(result)} + + def __repr__(self): + rname = self._repr_name() + if rname: + string = '<%(cname)s.%(rname)s l.%(lineno)s at 0x%(id)x>' + else: + string = '<%(cname)s l.%(lineno)s at 0x%(id)x>' + return string % {'cname': type(self).__name__, + 'rname': rname, + 'lineno': self.fromlineno, + 'id': id(self)} + + def accept(self, visitor): + func = getattr(visitor, "visit_" + self.__class__.__name__.lower()) + return func(self) + + def get_children(self): + for field in self._astroid_fields: + attr = getattr(self, field) + if attr is None: + continue + if isinstance(attr, (list, tuple)): + for elt in attr: + yield elt + else: + yield attr + + def last_child(self): + """an optimized version of list(get_children())[-1]""" + for field in self._astroid_fields[::-1]: + attr = getattr(self, field) + if not attr: # None or empty listy / tuple + continue + if isinstance(attr, (list, tuple)): + return attr[-1] + + return attr + return None + + def parent_of(self, node): + """return true if i'm a parent of the given node""" + parent = node.parent + while parent is not None: + if self is parent: + return True + parent = parent.parent + return False + + def statement(self): + """return the first parent node marked as statement node""" + if self.is_statement: + return self + return self.parent.statement() + + def frame(self): + """return the first parent frame node (i.e. Module, FunctionDef or + ClassDef) + + """ + return self.parent.frame() + + def scope(self): + """return the first node defining a new scope (i.e. Module, + FunctionDef, ClassDef, Lambda but also GenExpr) + + """ + return self.parent.scope() + + def root(self): + """return the root node of the tree, (i.e. a Module)""" + if self.parent: + return self.parent.root() + return self + + def child_sequence(self, child): + """search for the right sequence where the child lies in""" + for field in self._astroid_fields: + node_or_sequence = getattr(self, field) + if node_or_sequence is child: + return [node_or_sequence] + # /!\ compiler.ast Nodes have an __iter__ walking over child nodes + if (isinstance(node_or_sequence, (tuple, list)) + and child in node_or_sequence): + return node_or_sequence + + msg = 'Could not find %s in %s\'s children' + raise exceptions.AstroidError(msg % (repr(child), repr(self))) + + def locate_child(self, child): + """return a 2-uple (child attribute name, sequence or node)""" + for field in self._astroid_fields: + node_or_sequence = getattr(self, field) + # /!\ compiler.ast Nodes have an __iter__ walking over child nodes + if child is node_or_sequence: + return field, child + if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence: + return field, node_or_sequence + msg = 'Could not find %s in %s\'s children' + raise exceptions.AstroidError(msg % (repr(child), repr(self))) + # FIXME : should we merge child_sequence and locate_child ? locate_child + # is only used in are_exclusive, child_sequence one time in pylint. + + def next_sibling(self): + """return the next sibling statement""" + return self.parent.next_sibling() + + def previous_sibling(self): + """return the previous sibling statement""" + return self.parent.previous_sibling() + + def nearest(self, nodes): + """return the node which is the nearest before this one in the + given list of nodes + """ + myroot = self.root() + mylineno = self.fromlineno + nearest = None, 0 + for node in nodes: + assert node.root() is myroot, \ + 'nodes %s and %s are not from the same module' % (self, node) + lineno = node.fromlineno + if node.fromlineno > mylineno: + break + if lineno > nearest[1]: + nearest = node, lineno + # FIXME: raise an exception if nearest is None ? + return nearest[0] + + # these are lazy because they're relatively expensive to compute for every + # single node, and they rarely get looked at + + @decorators.cachedproperty + def fromlineno(self): + if self.lineno is None: + return self._fixed_source_line() + + return self.lineno + + @decorators.cachedproperty + def tolineno(self): + if not self._astroid_fields: + # can't have children + lastchild = None + else: + lastchild = self.last_child() + if lastchild is None: + return self.fromlineno + + return lastchild.tolineno + + def _fixed_source_line(self): + """return the line number where the given node appears + + we need this method since not all nodes have the lineno attribute + correctly set... + """ + line = self.lineno + _node = self + try: + while line is None: + _node = next(_node.get_children()) + line = _node.lineno + except StopIteration: + _node = self.parent + while _node and line is None: + line = _node.lineno + _node = _node.parent + return line + + def block_range(self, lineno): + """handle block line numbers range for non block opening statements + """ + return lineno, self.tolineno + + def set_local(self, name, stmt): + """delegate to a scoped parent handling a locals dictionary""" + self.parent.set_local(name, stmt) + + def nodes_of_class(self, klass, skip_klass=None): + """return an iterator on nodes which are instance of the given class(es) + + klass may be a class object or a tuple of class objects + """ + if isinstance(self, klass): + yield self + for child_node in self.get_children(): + if skip_klass is not None and isinstance(child_node, skip_klass): + continue + for matching in child_node.nodes_of_class(klass, skip_klass): + yield matching + + def _infer_name(self, frame, name): + # overridden for ImportFrom, Import, Global, TryExcept and Arguments + return None + + def _infer(self, context=None): + """we don't know how to resolve a statement by default""" + # this method is overridden by most concrete classes + raise exceptions.InferenceError('No inference function for {node!r}.', + node=self, context=context) + + def inferred(self): + '''return list of inferred values for a more simple inference usage''' + return list(self.infer()) + + def infered(self): + warnings.warn('%s.infered() is deprecated and slated for removal ' + 'in astroid 2.0, use %s.inferred() instead.' + % (type(self).__name__, type(self).__name__), + PendingDeprecationWarning, stacklevel=2) + return self.inferred() + + def instantiate_class(self): + """instantiate a node if it is a ClassDef node, else return self""" + return self + + def has_base(self, node): + return False + + def callable(self): + return False + + def eq(self, value): + return False + + def as_string(self): + return as_string.to_code(self) + + def repr_tree(self, ids=False, include_linenos=False, + ast_state=False, indent=' ', max_depth=0, max_width=80): + """Returns a string representation of the AST from this node. + + :param ids: If true, includes the ids with the node type names. + + :param include_linenos: If true, includes the line numbers and + column offsets. + + :param ast_state: If true, includes information derived from + the whole AST like local and global variables. + + :param indent: A string to use to indent the output string. + + :param max_depth: If set to a positive integer, won't return + nodes deeper than max_depth in the string. + + :param max_width: Only positive integer values are valid, the + default is 80. Attempts to format the output string to stay + within max_width characters, but can exceed it under some + circumstances. + """ + @_singledispatch + def _repr_tree(node, result, done, cur_indent='', depth=1): + """Outputs a representation of a non-tuple/list, non-node that's + contained within an AST, including strings. + """ + lines = pprint.pformat(node, + width=max(max_width - len(cur_indent), + 1)).splitlines(True) + result.append(lines[0]) + result.extend([cur_indent + line for line in lines[1:]]) + return len(lines) != 1 + + # pylint: disable=unused-variable; doesn't understand singledispatch + @_repr_tree.register(tuple) + @_repr_tree.register(list) + def _repr_seq(node, result, done, cur_indent='', depth=1): + """Outputs a representation of a sequence that's contained within an AST.""" + cur_indent += indent + result.append('[') + if not node: + broken = False + elif len(node) == 1: + broken = _repr_tree(node[0], result, done, cur_indent, depth) + elif len(node) == 2: + broken = _repr_tree(node[0], result, done, cur_indent, depth) + if not broken: + result.append(', ') + else: + result.append(',\n') + result.append(cur_indent) + broken = (_repr_tree(node[1], result, done, cur_indent, depth) + or broken) + else: + result.append('\n') + result.append(cur_indent) + for child in node[:-1]: + _repr_tree(child, result, done, cur_indent, depth) + result.append(',\n') + result.append(cur_indent) + _repr_tree(node[-1], result, done, cur_indent, depth) + broken = True + result.append(']') + return broken + + # pylint: disable=unused-variable; doesn't understand singledispatch + @_repr_tree.register(NodeNG) + def _repr_node(node, result, done, cur_indent='', depth=1): + """Outputs a strings representation of an astroid node.""" + if node in done: + result.append(indent + ' max_depth: + result.append('...') + return False + depth += 1 + cur_indent += indent + if ids: + result.append('%s<0x%x>(\n' % (type(node).__name__, id(node))) + else: + result.append('%s(' % type(node).__name__) + fields = [] + if include_linenos: + fields.extend(('lineno', 'col_offset')) + fields.extend(node._other_fields) + fields.extend(node._astroid_fields) + if ast_state: + fields.extend(node._other_other_fields) + if not fields: + broken = False + elif len(fields) == 1: + result.append('%s=' % fields[0]) + broken = _repr_tree(getattr(node, fields[0]), result, done, + cur_indent, depth) + else: + result.append('\n') + result.append(cur_indent) + for field in fields[:-1]: + result.append('%s=' % field) + _repr_tree(getattr(node, field), result, done, cur_indent, + depth) + result.append(',\n') + result.append(cur_indent) + result.append('%s=' % fields[-1]) + _repr_tree(getattr(node, fields[-1]), result, done, cur_indent, + depth) + broken = True + result.append(')') + return broken + + result = [] + _repr_tree(self, result, set()) + return ''.join(result) + + def bool_value(self): + """Determine the bool value of this node + + The boolean value of a node can have three + possible values: + + * False. For instance, empty data structures, + False, empty strings, instances which return + explicitly False from the __nonzero__ / __bool__ + method. + * True. Most of constructs are True by default: + classes, functions, modules etc + * Uninferable: the inference engine is uncertain of the + node's value. + """ + return util.Uninferable + + +class Statement(NodeNG): + """Statement node adding a few attributes""" + is_statement = True + + def next_sibling(self): + """return the next sibling statement""" + stmts = self.parent.child_sequence(self) + index = stmts.index(self) + try: + return stmts[index +1] + except IndexError: + pass + + def previous_sibling(self): + """return the previous sibling statement""" + stmts = self.parent.child_sequence(self) + index = stmts.index(self) + if index >= 1: + return stmts[index -1] + + + @six.add_metaclass(abc.ABCMeta) class _BaseContainer(mixins.ParentAssignTypeMixin, - bases.NodeNG, - bases.Instance): + NodeNG, bases.Instance): """Base class for Set, FrozenSet, Tuple and List.""" _astroid_fields = ('elts',) - def __init__(self, elts=None): + def __init__(self, lineno=None, col_offset=None, parent=None): + self.elts = [] + super(_BaseContainer, self).__init__(lineno, col_offset, parent) + + def postinit(self, elts): + self.elts = elts + + @classmethod + def from_constants(cls, elts=None): + node = cls() if elts is None: - self.elts = [] + node.elts = [] else: - self.elts = [const_factory(e) for e in elts] + node.elts = [const_factory(e) for e in elts] + return node def itered(self): return self.elts @@ -197,7 +755,6 @@ def _filter_stmts(self, stmts, frame, offset): if self.statement() is myframe and myframe.parent: myframe = myframe.parent.frame() - mystmt = self.statement() # line filtering if we are in the same frame # @@ -228,8 +785,8 @@ def _filter_stmts(self, stmts, frame, offset): optional_assign = assign_type.optional_assign if optional_assign and assign_type.parent_of(self): - # we are inside a loop, loop var assigment is hidding previous - # assigment + # we are inside a loop, loop var assignment is hiding previous + # assignment _stmts = [node] _stmt_parents = [stmt.parent] continue @@ -246,7 +803,7 @@ def _filter_stmts(self, stmts, frame, offset): # both statements are not at the same block level continue # if currently visited node is following previously considered - # assignement and both are not exclusive, we can drop the + # assignment and both are not exclusive, we can drop the # previous one. For instance in the following code :: # # if a: @@ -266,7 +823,7 @@ def _filter_stmts(self, stmts, frame, offset): # # moreover, on loop assignment types, assignment won't # necessarily be done if the loop has no iteration, so we don't - # want to clear previous assigments if any (hence the test on + # want to clear previous assignments if any (hence the test on # optional_assign) if not (optional_assign or are_exclusive(_stmts[pindex], node)): del _stmt_parents[pindex] @@ -287,19 +844,34 @@ def _filter_stmts(self, stmts, frame, offset): # Name classes -class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG): - """class representing an AssName node""" +class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG): + """class representing an AssignName node""" + _other_fields = ('name',) + def __init__(self, name=None, lineno=None, col_offset=None, parent=None): + self.name = name + super(AssignName, self).__init__(lineno, col_offset, parent) -class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG): + +class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG): """class representing a DelName node""" + _other_fields = ('name',) + + def __init__(self, name=None, lineno=None, col_offset=None, parent=None): + self.name = name + super(DelName, self).__init__(lineno, col_offset, parent) -class Name(LookupMixIn, bases.NodeNG): +class Name(LookupMixIn, NodeNG): """class representing a Name node""" + _other_fields = ('name',) + def __init__(self, name=None, lineno=None, col_offset=None, parent=None): + self.name = name + super(Name, self).__init__(lineno, col_offset, parent) -class Arguments(mixins.AssignTypeMixin, bases.NodeNG): + +class Arguments(mixins.AssignTypeMixin, NodeNG): """class representing an Arguments node""" if six.PY3: # Python 3.4+ uses a different approach regarding annotations, @@ -314,21 +886,38 @@ class Arguments(mixins.AssignTypeMixin, bases.NodeNG): # annotation, its value will be None. _astroid_fields = ('args', 'defaults', 'kwonlyargs', - 'kw_defaults', 'annotations', - 'varargannotation', 'kwargannotation') - annotations = None + 'kw_defaults', 'annotations', 'varargannotation', + 'kwargannotation', 'kwonlyargs_annotations') varargannotation = None kwargannotation = None else: _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults') - args = None - defaults = None - kwonlyargs = None - kw_defaults = None + _other_fields = ('vararg', 'kwarg') - def __init__(self, vararg=None, kwarg=None): + def __init__(self, vararg=None, kwarg=None, parent=None): + super(Arguments, self).__init__(parent=parent) self.vararg = vararg self.kwarg = kwarg + self.args = [] + self.defaults = [] + self.kwonlyargs = [] + self.kw_defaults = [] + self.annotations = [] + self.kwonlyargs_annotations = [] + + def postinit(self, args, defaults, kwonlyargs, kw_defaults, + annotations, + kwonlyargs_annotations=None, + varargannotation=None, + kwargannotation=None): + self.args = args + self.defaults = defaults + self.kwonlyargs = kwonlyargs + self.kw_defaults = kw_defaults + self.annotations = annotations + self.kwonlyargs_annotations = kwonlyargs_annotations + self.varargannotation = varargannotation + self.kwargannotation = kwargannotation def _infer_name(self, frame, name): if self.parent is frame: @@ -353,7 +942,11 @@ def format_args(self): if self.kwonlyargs: if not self.vararg: result.append('*') - result.append(_format_args(self.kwonlyargs, self.kw_defaults)) + result.append(_format_args( + self.kwonlyargs, + self.kw_defaults, + self.kwonlyargs_annotations + )) if self.kwarg: result.append('**%s' % self.kwarg) return ', '.join(result) @@ -371,7 +964,7 @@ def default_value(self, argname): i = _find_arg(argname, self.kwonlyargs)[0] if i is not None and self.kw_defaults[i] is not None: return self.kw_defaults[i] - raise exceptions.NoDefault() + raise exceptions.NoDefault(func=self.parent, name=argname) def is_argument(self, name): """return True if the name is defined in arguments""" @@ -379,7 +972,8 @@ def is_argument(self, name): return True if name == self.kwarg: return True - return self.find_argname(name, True)[1] is not None + return (self.find_argname(name, True)[1] is not None or + self.kwonlyargs and _find_arg(name, self.kwonlyargs, True)[1] is not None) def find_argname(self, argname, rec=False): """return index and Name node with given name""" @@ -430,56 +1024,164 @@ def _format_args(args, defaults=None, annotations=None): return ', '.join(values) -class AssignAttr(mixins.ParentAssignTypeMixin, bases.NodeNG): +class AssignAttr(mixins.ParentAssignTypeMixin, NodeNG): """class representing an AssignAttr node""" _astroid_fields = ('expr',) + _other_fields = ('attrname',) expr = None -class Assert(bases.Statement): + def __init__(self, attrname=None, lineno=None, col_offset=None, parent=None): + self.attrname = attrname + super(AssignAttr, self).__init__(lineno, col_offset, parent) + + def postinit(self, expr=None): + self.expr = expr + + +class Assert(Statement): """class representing an Assert node""" _astroid_fields = ('test', 'fail',) test = None fail = None -class Assign(bases.Statement, mixins.AssignTypeMixin): + def postinit(self, test=None, fail=None): + self.fail = fail + self.test = test + + +class Assign(mixins.AssignTypeMixin, Statement): """class representing an Assign node""" _astroid_fields = ('targets', 'value',) targets = None value = None -class AugAssign(bases.Statement, mixins.AssignTypeMixin): + def postinit(self, targets=None, value=None): + self.targets = targets + self.value = value + + +class AnnAssign(mixins.AssignTypeMixin, Statement): + """Class representing an AnnAssign node""" + + _astroid_fields = ('target', 'annotation', 'value',) + _other_fields = ('simple',) + target = None + annotation = None + value = None + simple = None + + def postinit(self, target, annotation, simple, value=None): + self.target = target + self.annotation = annotation + self.value = value + self.simple = simple + + +class AugAssign(mixins.AssignTypeMixin, Statement): """class representing an AugAssign node""" - _astroid_fields = ('target', 'value',) + _astroid_fields = ('target', 'value') + _other_fields = ('op',) target = None value = None -class Repr(bases.NodeNG): - """class representing a Backquote node""" + def __init__(self, op=None, lineno=None, col_offset=None, parent=None): + self.op = op + super(AugAssign, self).__init__(lineno, col_offset, parent) + + def postinit(self, target=None, value=None): + self.target = target + self.value = value + + # This is set by inference.py + def _infer_augassign(self, context=None): + raise NotImplementedError + + def type_errors(self, context=None): + """Return a list of TypeErrors which can occur during inference. + + Each TypeError is represented by a :class:`BadBinaryOperationMessage`, + which holds the original exception. + """ + try: + results = self._infer_augassign(context=context) + return [result for result in results + if isinstance(result, util.BadBinaryOperationMessage)] + except exceptions.InferenceError: + return [] + + +class Repr(NodeNG): + """class representing a Repr node""" _astroid_fields = ('value',) value = None -class BinOp(bases.NodeNG): + def postinit(self, value=None): + self.value = value + + +class BinOp(NodeNG): """class representing a BinOp node""" - _astroid_fields = ('left', 'right',) + _astroid_fields = ('left', 'right') + _other_fields = ('op',) left = None right = None -class BoolOp(bases.NodeNG): + def __init__(self, op=None, lineno=None, col_offset=None, parent=None): + self.op = op + super(BinOp, self).__init__(lineno, col_offset, parent) + + def postinit(self, left=None, right=None): + self.left = left + self.right = right + + # This is set by inference.py + def _infer_binop(self, context=None): + raise NotImplementedError + + def type_errors(self, context=None): + """Return a list of TypeErrors which can occur during inference. + + Each TypeError is represented by a :class:`BadBinaryOperationMessage`, + which holds the original exception. + """ + try: + results = self._infer_binop(context=context) + return [result for result in results + if isinstance(result, util.BadBinaryOperationMessage)] + except exceptions.InferenceError: + return [] + + +class BoolOp(NodeNG): """class representing a BoolOp node""" _astroid_fields = ('values',) + _other_fields = ('op',) values = None -class Break(bases.Statement): + def __init__(self, op=None, lineno=None, col_offset=None, parent=None): + self.op = op + super(BoolOp, self).__init__(lineno, col_offset, parent) + + def postinit(self, values=None): + self.values = values + + +class Break(Statement): """class representing a Break node""" -class Call(bases.NodeNG): +class Call(NodeNG): """class representing a Call node""" _astroid_fields = ('func', 'args', 'keywords') func = None args = None keywords = None + def postinit(self, func=None, args=None, keywords=None): + self.func = func + self.args = args + self.keywords = keywords + @property def starargs(self): args = self.args or [] @@ -490,12 +1192,17 @@ def kwargs(self): keywords = self.keywords or [] return [keyword for keyword in keywords if keyword.arg is None] -class Compare(bases.NodeNG): + +class Compare(NodeNG): """class representing a Compare node""" _astroid_fields = ('left', 'ops',) left = None ops = None + def postinit(self, left=None, ops=None): + self.left = left + self.ops = ops + def get_children(self): """override get_children for tuple fields""" yield self.left @@ -509,12 +1216,25 @@ def last_child(self): #return self.left -class Comprehension(bases.NodeNG): +class Comprehension(NodeNG): """class representing a Comprehension node""" _astroid_fields = ('target', 'iter', 'ifs') + _other_fields = ('is_async',) target = None iter = None ifs = None + is_async = None + + def __init__(self, parent=None): + super(Comprehension, self).__init__() + self.parent = parent + + # pylint: disable=redefined-builtin; same name as builtin ast module. + def postinit(self, target=None, iter=None, ifs=None, is_async=None): + self.target = target + self.iter = iter + self.ifs = ifs + self.is_async = is_async optional_assign = True def assign_type(self): @@ -542,21 +1262,45 @@ def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt): return stmts, False -class Const(bases.NodeNG, bases.Instance): +class Const(NodeNG, bases.Instance): """represent a constant node like num, str, bool, None, bytes""" + _other_fields = ('value',) - def __init__(self, value=None): + def __init__(self, value, lineno=None, col_offset=None, parent=None): self.value = value + super(Const, self).__init__(lineno, col_offset, parent) def getitem(self, index, context=None): - if isinstance(self.value, six.string_types): - return Const(self.value[index]) - if isinstance(self.value, bytes) and six.PY3: - # Bytes aren't instances of six.string_types - # on Python 3. Also, indexing them should return - # integers. - return Const(self.value[index]) - raise TypeError('%r (value=%s)' % (self, self.value)) + if isinstance(index, Const): + index_value = index.value + elif isinstance(index, Slice): + index_value = _infer_slice(index, context=context) + + else: + raise exceptions.AstroidTypeError( + 'Could not use type {} as subscript index'.format(type(index)) + ) + + try: + if isinstance(self.value, six.string_types): + return Const(self.value[index_value]) + if isinstance(self.value, bytes) and six.PY3: + # Bytes aren't instances of six.string_types + # on Python 3. Also, indexing them should return + # integers. + return Const(self.value[index_value]) + except IndexError as exc: + util.reraise(exceptions.AstroidIndexError( + message='Index {index!r} out of range', error=exc, + node=self, index=index, context=context)) + except TypeError as exc: + util.reraise(exceptions.AstroidTypeError( + message='Type error {error!r}', error=exc, + node=self, index=index, context=context)) + + raise exceptions.AstroidTypeError( + '%r (value=%s)' % (self, self.value) + ) def has_dynamic_getattr(self): return False @@ -569,17 +1313,20 @@ def itered(self): def pytype(self): return self._proxied.qname() + def bool_value(self): + return bool(self.value) + -class Continue(bases.Statement): +class Continue(Statement): """class representing a Continue node""" -class Decorators(bases.NodeNG): +class Decorators(NodeNG): """class representing a Decorators node""" _astroid_fields = ('nodes',) nodes = None - def __init__(self, nodes=None): + def postinit(self, nodes): self.nodes = nodes def scope(self): @@ -587,29 +1334,49 @@ def scope(self): return self.parent.parent.scope() -class DelAttr(mixins.ParentAssignTypeMixin, bases.NodeNG): +class DelAttr(mixins.ParentAssignTypeMixin, NodeNG): """class representing a DelAttr node""" _astroid_fields = ('expr',) + _other_fields = ('attrname',) expr = None + def __init__(self, attrname=None, lineno=None, col_offset=None, parent=None): + self.attrname = attrname + super(DelAttr, self).__init__(lineno, col_offset, parent) + def postinit(self, expr=None): + self.expr = expr -class Delete(mixins.AssignTypeMixin, bases.Statement): + +class Delete(mixins.AssignTypeMixin, Statement): """class representing a Delete node""" _astroid_fields = ('targets',) targets = None + def postinit(self, targets=None): + self.targets = targets + -class Dict(bases.NodeNG, bases.Instance): +class Dict(NodeNG, bases.Instance): """class representing a Dict node""" _astroid_fields = ('items',) - def __init__(self, items=None): + def __init__(self, lineno=None, col_offset=None, parent=None): + self.items = [] + super(Dict, self).__init__(lineno, col_offset, parent) + + def postinit(self, items): + self.items = items + + @classmethod + def from_constants(cls, items=None): + node = cls() if items is None: - self.items = [] + node.items = [] else: - self.items = [(const_factory(k), const_factory(v)) - for k, v in list(items.items())] + node.items = [(const_factory(k), const_factory(v)) + for k, v in items.items()] + return node def pytype(self): return '%s.dict' % BUILTINS @@ -630,56 +1397,72 @@ def last_child(self): def itered(self): return self.items[::2] - def getitem(self, lookup_key, context=None): + def getitem(self, index, context=None): for key, value in self.items: # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}. if isinstance(key, DictUnpack): try: - return value.getitem(lookup_key, context) - except IndexError: + return value.getitem(index, context) + except (exceptions.AstroidTypeError, exceptions.AstroidIndexError): continue for inferredkey in key.infer(context): - if inferredkey is util.YES: + if inferredkey is util.Uninferable: continue - if isinstance(inferredkey, Const) \ - and inferredkey.value == lookup_key: - return value - # This should raise KeyError, but all call sites only catch - # IndexError. Let's leave it like that for now. - raise IndexError(lookup_key) + if isinstance(inferredkey, Const) and isinstance(index, Const): + if inferredkey.value == index.value: + return value + raise exceptions.AstroidIndexError(index) -class Expr(bases.Statement): + def bool_value(self): + return bool(self.items) + + +class Expr(Statement): """class representing a Expr node""" _astroid_fields = ('value',) value = None + def postinit(self, value=None): + self.value = value + -class Ellipsis(bases.NodeNG): # pylint: disable=redefined-builtin +class Ellipsis(NodeNG): # pylint: disable=redefined-builtin """class representing an Ellipsis node""" + def bool_value(self): + return True + -class EmptyNode(bases.NodeNG): +class EmptyNode(NodeNG): """class representing an EmptyNode node""" + object = None -class ExceptHandler(mixins.AssignTypeMixin, bases.Statement): + +class ExceptHandler(mixins.AssignTypeMixin, Statement): """class representing an ExceptHandler node""" _astroid_fields = ('type', 'name', 'body',) type = None name = None body = None + # pylint: disable=redefined-builtin; had to use the same name as builtin ast module. + def postinit(self, type=None, name=None, body=None): + self.type = type + self.name = name + self.body = body + @decorators.cachedproperty def blockstart_tolineno(self): if self.name: return self.name.tolineno elif self.type: return self.type.tolineno - else: - return self.lineno - def catch(self, exceptions): + return self.lineno + + def catch(self, exceptions): # pylint: disable=redefined-outer-name if self.type is None or exceptions is None: return True for node in self.type.nodes_of_class(Name): @@ -687,20 +1470,30 @@ def catch(self, exceptions): return True -class Exec(bases.Statement): +class Exec(Statement): """class representing an Exec node""" _astroid_fields = ('expr', 'globals', 'locals',) expr = None globals = None locals = None + # pylint: disable=redefined-builtin; had to use the same name as builtin ast module. + def postinit(self, expr=None, globals=None, locals=None): + self.expr = expr + self.globals = globals + self.locals = locals -class ExtSlice(bases.NodeNG): + +class ExtSlice(NodeNG): """class representing an ExtSlice node""" _astroid_fields = ('dims',) dims = None -class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement): + def postinit(self, dims=None): + self.dims = dims + + +class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, Statement): """class representing a For node""" _astroid_fields = ('target', 'iter', 'body', 'orelse',) target = None @@ -708,6 +1501,13 @@ class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement): body = None orelse = None + # pylint: disable=redefined-builtin; had to use the same name as builtin ast module. + def postinit(self, target=None, iter=None, body=None, orelse=None): + self.target = target + self.iter = iter + self.body = body + self.orelse = orelse + optional_assign = True @decorators.cachedproperty def blockstart_tolineno(self): @@ -718,7 +1518,7 @@ class AsyncFor(For): """Asynchronous For built with `async` keyword.""" -class Await(bases.NodeNG): +class Await(NodeNG): """Await node for the `await` keyword.""" _astroid_fields = ('value', ) @@ -728,37 +1528,56 @@ def postinit(self, value=None): self.value = value -class ImportFrom(mixins.ImportFromMixin, bases.Statement): - """class representing a From node""" +class ImportFrom(mixins.ImportFromMixin, Statement): + """class representing a ImportFrom node""" + _other_fields = ('modname', 'names', 'level') - def __init__(self, fromname, names, level=0): + def __init__(self, fromname, names, level=0, lineno=None, + col_offset=None, parent=None): self.modname = fromname self.names = names self.level = level + super(ImportFrom, self).__init__(lineno, col_offset, parent) -class Attribute(bases.NodeNG): + +class Attribute(NodeNG): """class representing a Attribute node""" _astroid_fields = ('expr',) + _other_fields = ('attrname',) expr = None + def __init__(self, attrname=None, lineno=None, col_offset=None, parent=None): + self.attrname = attrname + super(Attribute, self).__init__(lineno, col_offset, parent) + + def postinit(self, expr=None): + self.expr = expr -class Global(bases.Statement): + +class Global(Statement): """class representing a Global node""" + _other_fields = ('names',) - def __init__(self, names): + def __init__(self, names, lineno=None, col_offset=None, parent=None): self.names = names + super(Global, self).__init__(lineno, col_offset, parent) def _infer_name(self, frame, name): return name -class If(mixins.BlockRangeMixIn, bases.Statement): +class If(mixins.BlockRangeMixIn, Statement): """class representing an If node""" _astroid_fields = ('test', 'body', 'orelse') test = None body = None orelse = None + def postinit(self, test=None, body=None, orelse=None): + self.test = test + self.body = body + self.orelse = orelse + @decorators.cachedproperty def blockstart_tolineno(self): return self.test.tolineno @@ -773,73 +1592,119 @@ def block_range(self, lineno): self.body[0].fromlineno - 1) -class IfExp(bases.NodeNG): +class IfExp(NodeNG): """class representing an IfExp node""" _astroid_fields = ('test', 'body', 'orelse') test = None body = None orelse = None + def postinit(self, test=None, body=None, orelse=None): + self.test = test + self.body = body + self.orelse = orelse -class Import(mixins.ImportFromMixin, bases.Statement): + +class Import(mixins.ImportFromMixin, Statement): """class representing an Import node""" + _other_fields = ('names',) + + def __init__(self, names=None, lineno=None, col_offset=None, parent=None): + self.names = names + super(Import, self).__init__(lineno, col_offset, parent) -class Index(bases.NodeNG): +class Index(NodeNG): """class representing an Index node""" _astroid_fields = ('value',) value = None + def postinit(self, value=None): + self.value = value + -class Keyword(bases.NodeNG): +class Keyword(NodeNG): """class representing a Keyword node""" _astroid_fields = ('value',) + _other_fields = ('arg',) value = None + def __init__(self, arg=None, lineno=None, col_offset=None, parent=None): + self.arg = arg + super(Keyword, self).__init__(lineno, col_offset, parent) + + def postinit(self, value=None): + self.value = value + class List(_BaseContainer): """class representing a List node""" + _other_fields = ('ctx',) + + def __init__(self, ctx=None, lineno=None, + col_offset=None, parent=None): + self.ctx = ctx + super(List, self).__init__(lineno, col_offset, parent) def pytype(self): return '%s.list' % BUILTINS def getitem(self, index, context=None): - return self.elts[index] + return _container_getitem(self, self.elts, index, context=context) -class Nonlocal(bases.Statement): +class Nonlocal(Statement): """class representing a Nonlocal node""" + _other_fields = ('names',) - def __init__(self, names): + def __init__(self, names, lineno=None, col_offset=None, parent=None): self.names = names + super(Nonlocal, self).__init__(lineno, col_offset, parent) def _infer_name(self, frame, name): return name -class Pass(bases.Statement): +class Pass(Statement): """class representing a Pass node""" -class Print(bases.Statement): +class Print(Statement): """class representing a Print node""" _astroid_fields = ('dest', 'values',) dest = None values = None + def __init__(self, nl=None, lineno=None, col_offset=None, parent=None): + self.nl = nl + super(Print, self).__init__(lineno, col_offset, parent) + + def postinit(self, dest=None, values=None): + self.dest = dest + self.values = values + -class Raise(bases.Statement): +class Raise(Statement): """class representing a Raise node""" exc = None if six.PY2: _astroid_fields = ('exc', 'inst', 'tback') inst = None tback = None + + def postinit(self, exc=None, inst=None, tback=None): + self.exc = exc + self.inst = inst + self.tback = tback else: _astroid_fields = ('exc', 'cause') exc = None cause = None + def postinit(self, exc=None, cause=None): + self.exc = exc + self.cause = cause + def raises_not_implemented(self): if not self.exc: return @@ -848,11 +1713,14 @@ def raises_not_implemented(self): return True -class Return(bases.Statement): +class Return(Statement): """class representing a Return node""" _astroid_fields = ('value',) value = None + def postinit(self, value=None): + self.value = value + class Set(_BaseContainer): """class representing a Set node""" @@ -861,33 +1729,94 @@ def pytype(self): return '%s.set' % BUILTINS -class Slice(bases.NodeNG): +class Slice(NodeNG): """class representing a Slice node""" _astroid_fields = ('lower', 'upper', 'step') lower = None upper = None step = None -class Starred(mixins.ParentAssignTypeMixin, bases.NodeNG): + def postinit(self, lower=None, upper=None, step=None): + self.lower = lower + self.upper = upper + self.step = step + + def _wrap_attribute(self, attr): + """Wrap the empty attributes of the Slice in a Const node.""" + if not attr: + const = const_factory(attr) + const.parent = self + return const + return attr + + @decorators.cachedproperty + def _proxied(self): + builtins = MANAGER.astroid_cache[BUILTINS] + return builtins.getattr('slice')[0] + + def pytype(self): + return '%s.slice' % BUILTINS + + def igetattr(self, attrname, context=None): + if attrname == 'start': + yield self._wrap_attribute(self.lower) + elif attrname == 'stop': + yield self._wrap_attribute(self.upper) + elif attrname == 'step': + yield self._wrap_attribute(self.step) + else: + for value in self.getattr(attrname, context=context): + yield value + + def getattr(self, attrname, context=None): + return self._proxied.getattr(attrname, context) + + +class Starred(mixins.ParentAssignTypeMixin, NodeNG): """class representing a Starred node""" _astroid_fields = ('value',) + _other_fields = ('ctx', ) value = None + def __init__(self, ctx=None, lineno=None, col_offset=None, parent=None): + self.ctx = ctx + super(Starred, self).__init__(lineno=lineno, + col_offset=col_offset, parent=parent) + + def postinit(self, value=None): + self.value = value -class Subscript(bases.NodeNG): + +class Subscript(NodeNG): """class representing a Subscript node""" _astroid_fields = ('value', 'slice') + _other_fields = ('ctx', ) value = None slice = None + def __init__(self, ctx=None, lineno=None, col_offset=None, parent=None): + self.ctx = ctx + super(Subscript, self).__init__(lineno=lineno, + col_offset=col_offset, parent=parent) + + # pylint: disable=redefined-builtin; had to use the same name as builtin ast module. + def postinit(self, value=None, slice=None): + self.value = value + self.slice = slice + -class TryExcept(mixins.BlockRangeMixIn, bases.Statement): +class TryExcept(mixins.BlockRangeMixIn, Statement): """class representing a TryExcept node""" _astroid_fields = ('body', 'handlers', 'orelse',) body = None handlers = None orelse = None + def postinit(self, body=None, handlers=None, orelse=None): + self.body = body + self.handlers = handlers + self.orelse = orelse + def _infer_name(self, frame, name): return name @@ -904,12 +1833,16 @@ def block_range(self, lineno): return self._elsed_block_range(lineno, self.orelse, last) -class TryFinally(mixins.BlockRangeMixIn, bases.Statement): +class TryFinally(mixins.BlockRangeMixIn, Statement): """class representing a TryFinally node""" _astroid_fields = ('body', 'finalbody',) body = None finalbody = None + def postinit(self, body=None, finalbody=None): + self.body = body + self.finalbody = finalbody + def block_range(self, lineno): """handle block line numbers range for try/finally statements""" child = self.body[0] @@ -923,41 +1856,82 @@ def block_range(self, lineno): class Tuple(_BaseContainer): """class representing a Tuple node""" + _other_fields = ('ctx',) + + def __init__(self, ctx=None, lineno=None, + col_offset=None, parent=None): + self.ctx = ctx + super(Tuple, self).__init__(lineno, col_offset, parent) + def pytype(self): return '%s.tuple' % BUILTINS def getitem(self, index, context=None): - return self.elts[index] + return _container_getitem(self, self.elts, index, context=context) -class UnaryOp(bases.NodeNG): +class UnaryOp(NodeNG): """class representing an UnaryOp node""" _astroid_fields = ('operand',) + _other_fields = ('op',) operand = None + def __init__(self, op=None, lineno=None, col_offset=None, parent=None): + self.op = op + super(UnaryOp, self).__init__(lineno, col_offset, parent) -class While(mixins.BlockRangeMixIn, bases.Statement): + def postinit(self, operand=None): + self.operand = operand + + # This is set by inference.py + def _infer_unaryop(self, context=None): + raise NotImplementedError + + def type_errors(self, context=None): + """Return a list of TypeErrors which can occur during inference. + + Each TypeError is represented by a :class:`BadUnaryOperationMessage`, + which holds the original exception. + """ + try: + results = self._infer_unaryop(context=context) + return [result for result in results + if isinstance(result, util.BadUnaryOperationMessage)] + except exceptions.InferenceError: + return [] + + +class While(mixins.BlockRangeMixIn, Statement): """class representing a While node""" _astroid_fields = ('test', 'body', 'orelse',) test = None body = None orelse = None + def postinit(self, test=None, body=None, orelse=None): + self.test = test + self.body = body + self.orelse = orelse + @decorators.cachedproperty def blockstart_tolineno(self): return self.test.tolineno def block_range(self, lineno): - """handle block line numbers range for for and while statements""" + """handle block line numbers range for and while statements""" return self. _elsed_block_range(lineno, self.orelse) -class With(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement): +class With(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, Statement): """class representing a With node""" _astroid_fields = ('items', 'body') items = None body = None + def postinit(self, items=None, body=None): + self.items = items + self.body = body + @decorators.cachedproperty def blockstart_tolineno(self): return self.items[-1][0].tolineno @@ -975,19 +1949,56 @@ class AsyncWith(With): """Asynchronous `with` built with the `async` keyword.""" -class Yield(bases.NodeNG): +class Yield(NodeNG): """class representing a Yield node""" _astroid_fields = ('value',) value = None + def postinit(self, value=None): + self.value = value + + class YieldFrom(Yield): """ Class representing a YieldFrom node. """ -class DictUnpack(bases.NodeNG): +class DictUnpack(NodeNG): """Represents the unpacking of dicts into dicts using PEP 448.""" +class FormattedValue(NodeNG): + """Represents a PEP 498 format string.""" + _astroid_fields = ('value', 'format_spec') + value = None + conversion = None + format_spec = None + + def postinit(self, value, conversion=None, format_spec=None): + self.value = value + self.conversion = conversion + self.format_spec = format_spec + + +class JoinedStr(NodeNG): + """Represents a list of string expressions to be joined.""" + _astroid_fields = ('values',) + values = None + + def postinit(self, values=None): + self.values = values + + +class Unknown(NodeNG): + '''This node represents a node in a constructed AST where + introspection is not possible. At the moment, it's only used in + the args attribute of FunctionDef nodes where function signature + introspection failed. + ''' + def infer(self, context=None, **kwargs): + '''Inference on an Unknown node immediately terminates.''' + yield util.Uninferable + + # constants ############################################################## CONST_CLS = { @@ -1003,6 +2014,7 @@ def _update_const_classes(): """update constant classes, so the keys of CONST_CLS can be reused""" klasses = (bool, int, float, complex, str) if six.PY2: + # pylint: disable=undefined-variable klasses += (unicode, long) klasses += (bytes,) for kls in klasses: @@ -1010,6 +2022,27 @@ def _update_const_classes(): _update_const_classes() +def _two_step_initialization(cls, value): + instance = cls() + instance.postinit(value) + return instance + + +def _dict_initialization(cls, value): + if isinstance(value, dict): + value = tuple(value.items()) + return _two_step_initialization(cls, value) + + +_CONST_CLS_CONSTRUCTORS = { + List: _two_step_initialization, + Tuple: _two_step_initialization, + Dict: _dict_initialization, + Set: _two_step_initialization, + Const: lambda cls, value: cls(value) +} + + def const_factory(value): """return an astroid node for a python value""" # XXX we should probably be stricter here and only consider stuff in @@ -1017,9 +2050,21 @@ def const_factory(value): # we should rather recall the builder on this value than returning an empty # node (another option being that const_factory shouldn't be called with something # not in CONST_CLS) - assert not isinstance(value, bases.NodeNG) + assert not isinstance(value, NodeNG) + + # Hack for ignoring elements of a sequence + # or a mapping, in order to avoid transforming + # each element to an AST. This is fixed in 2.0 + # and this approach is a temporary hack. + if isinstance(value, (list, set, tuple, dict)): + elts = [] + else: + elts = value + try: - return CONST_CLS[value.__class__](value) + initializer_cls = CONST_CLS[value.__class__] + initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls] + return initializer(initializer_cls, elts) except (KeyError, AttributeError): node = EmptyNode() node.object = value @@ -1027,27 +2072,11 @@ def const_factory(value): # Backward-compatibility aliases -def instancecheck(cls, other): - wrapped = cls.__wrapped__ - other_cls = other.__class__ - is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped) - warnings.warn("%r is deprecated and slated for removal in astroid " - "2.0, use %r instead" % (cls.__class__.__name__, - wrapped.__name__), - PendingDeprecationWarning, stacklevel=2) - return is_instance_of - - -def proxy_alias(alias_name, node_type): - proxy = type(alias_name, (lazy_object_proxy.Proxy,), - {'__class__': object.__dict__['__class__'], - '__instancecheck__': instancecheck}) - return proxy(lambda: node_type) - -Backquote = proxy_alias('Backquote', Repr) -Discard = proxy_alias('Discard', Expr) -AssName = proxy_alias('AssName', AssignName) -AssAttr = proxy_alias('AssAttr', AssignAttr) -Getattr = proxy_alias('Getattr', Attribute) -CallFunc = proxy_alias('CallFunc', Call) -From = proxy_alias('From', ImportFrom) + +Backquote = util.proxy_alias('Backquote', Repr) +Discard = util.proxy_alias('Discard', Expr) +AssName = util.proxy_alias('AssName', AssignName) +AssAttr = util.proxy_alias('AssAttr', AssignAttr) +Getattr = util.proxy_alias('Getattr', Attribute) +CallFunc = util.proxy_alias('CallFunc', Call) +From = util.proxy_alias('From', ImportFrom) diff --git a/pymode/libs/astroid/nodes.py b/pymode/libs/astroid/nodes.py index 2fd6cb65..2b207d02 100644 --- a/pymode/libs/astroid/nodes.py +++ b/pymode/libs/astroid/nodes.py @@ -1,20 +1,11 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2011, 2013 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """ on all nodes : .is_statement, returning true if the node should be considered as a @@ -37,7 +28,7 @@ # pylint: disable=unused-import,redefined-builtin from astroid.node_classes import ( - Arguments, AssignAttr, Assert, Assign, + Arguments, AssignAttr, Assert, Assign, AnnAssign, AssignName, AugAssign, Repr, BinOp, BoolOp, Break, Call, Compare, Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, Dict, Expr, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, @@ -46,10 +37,12 @@ TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, YieldFrom, const_factory, AsyncFor, Await, AsyncWith, + FormattedValue, JoinedStr, # Backwards-compatibility aliases Backquote, Discard, AssName, AssAttr, Getattr, CallFunc, From, # Node not present in the builtin ast module. DictUnpack, + Unknown, ) from astroid.scoped_nodes import ( Module, GeneratorExp, Lambda, DictComp, @@ -64,7 +57,7 @@ ALL_NODE_CLASSES = ( AsyncFunctionDef, AsyncFor, AsyncWith, Await, - Arguments, AssignAttr, Assert, Assign, AssignName, AugAssign, + Arguments, AssignAttr, Assert, Assign, AnnAssign, AssignName, AugAssign, Repr, BinOp, BoolOp, Break, Call, ClassDef, Compare, Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, @@ -84,4 +77,5 @@ UnaryOp, While, With, Yield, YieldFrom, + FormattedValue, JoinedStr, ) diff --git a/pymode/libs/astroid/objects.py b/pymode/libs/astroid/objects.py index d2f4270b..7a873449 100644 --- a/pymode/libs/astroid/objects.py +++ b/pymode/libs/astroid/objects.py @@ -1,73 +1,50 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """ Inference objects are a way to represent composite AST nodes, which are used only as inference results, so they can't be found in the -code tree. For instance, inferring the following frozenset use, leads to an -inferred FrozenSet: - - CallFunc(func=Name('frozenset'), args=Tuple(...)) +original AST tree. For instance, inferring the following frozenset use, +leads to an inferred FrozenSet: + Call(func=Name('frozenset'), args=Tuple(...)) """ import six +from astroid import bases +from astroid import decorators +from astroid import exceptions from astroid import MANAGER -from astroid.bases import ( - BUILTINS, NodeNG, Instance, _infer_stmts, - BoundMethod, _is_property -) -from astroid.decorators import cachedproperty -from astroid.exceptions import ( - SuperError, SuperArgumentTypeError, - NotFoundError, MroError -) -from astroid.node_classes import const_factory -from astroid.scoped_nodes import ClassDef, FunctionDef -from astroid.mixins import ParentAssignTypeMixin - - -class FrozenSet(NodeNG, Instance, ParentAssignTypeMixin): - """class representing a FrozenSet composite node""" +from astroid import node_classes +from astroid import scoped_nodes +from astroid import util - def __init__(self, elts=None): - if elts is None: - self.elts = [] - else: - self.elts = [const_factory(e) for e in elts] + +BUILTINS = six.moves.builtins.__name__ +objectmodel = util.lazy_import('interpreter.objectmodel') + + +class FrozenSet(node_classes._BaseContainer): + """class representing a FrozenSet composite node""" def pytype(self): return '%s.frozenset' % BUILTINS - def itered(self): - return self.elts - def _infer(self, context=None): yield self - @cachedproperty - def _proxied(self): + @decorators.cachedproperty + def _proxied(self): # pylint: disable=method-hidden builtins = MANAGER.astroid_cache[BUILTINS] return builtins.getattr('frozenset')[0] -class Super(NodeNG): +class Super(node_classes.NodeNG): """Proxy class over a super call. This class offers almost the same behaviour as Python's super, @@ -79,50 +56,53 @@ class Super(NodeNG): *self_class* is the class where the super call is, while *scope* is the function where the super call is. """ + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.SuperModel()) + # pylint: disable=super-init-not-called def __init__(self, mro_pointer, mro_type, self_class, scope): self.type = mro_type self.mro_pointer = mro_pointer self._class_based = False self._self_class = self_class self._scope = scope - self._model = { - '__thisclass__': self.mro_pointer, - '__self_class__': self._self_class, - '__self__': self.type, - '__class__': self._proxied, - } def _infer(self, context=None): yield self def super_mro(self): """Get the MRO which will be used to lookup attributes in this super.""" - if not isinstance(self.mro_pointer, ClassDef): - raise SuperArgumentTypeError("The first super argument must be type.") + if not isinstance(self.mro_pointer, scoped_nodes.ClassDef): + raise exceptions.SuperError( + "The first argument to super must be a subtype of " + "type, not {mro_pointer}.", super_=self) - if isinstance(self.type, ClassDef): + if isinstance(self.type, scoped_nodes.ClassDef): # `super(type, type)`, most likely in a class method. self._class_based = True mro_type = self.type else: mro_type = getattr(self.type, '_proxied', None) - if not isinstance(mro_type, (Instance, ClassDef)): - raise SuperArgumentTypeError("super(type, obj): obj must be an " - "instance or subtype of type") + if not isinstance(mro_type, (bases.Instance, scoped_nodes.ClassDef)): + raise exceptions.SuperError( + "The second argument to super must be an " + "instance or subtype of type, not {type}.", + super_=self) if not mro_type.newstyle: - raise SuperError("Unable to call super on old-style classes.") + raise exceptions.SuperError("Unable to call super on old-style classes.", super_=self) mro = mro_type.mro() if self.mro_pointer not in mro: - raise SuperArgumentTypeError("super(type, obj): obj must be an " - "instance or subtype of type") + raise exceptions.SuperError( + "The second argument to super must be an " + "instance or subtype of type, not {type}.", + super_=self) index = mro.index(self.mro_pointer) return mro[index + 1:] - @cachedproperty + @decorators.cachedproperty def _proxied(self): builtins = MANAGER.astroid_cache[BUILTINS] return builtins.getattr('super')[0] @@ -141,46 +121,100 @@ def name(self): def igetattr(self, name, context=None): """Retrieve the inferred values of the given attribute name.""" - local_name = self._model.get(name) - if local_name: - yield local_name + if name in self.special_attributes: + yield self.special_attributes.lookup(name) return try: mro = self.super_mro() - except (MroError, SuperError) as exc: - # Don't let invalid MROs or invalid super calls - # to leak out as is from this function. - six.raise_from(NotFoundError, exc) - + # Don't let invalid MROs or invalid super calls + # leak out as is from this function. + except exceptions.SuperError as exc: + util.reraise(exceptions.AttributeInferenceError( + ('Lookup for {name} on {target!r} because super call {super!r} ' + 'is invalid.'), + target=self, attribute=name, context=context, super_=exc.super_)) + except exceptions.MroError as exc: + util.reraise(exceptions.AttributeInferenceError( + ('Lookup for {name} on {target!r} failed because {cls!r} has an ' + 'invalid MRO.'), + target=self, attribute=name, context=context, mros=exc.mros, + cls=exc.cls)) found = False for cls in mro: - if name not in cls._locals: + if name not in cls.locals: continue found = True - for infered in _infer_stmts([cls[name]], context, frame=self): - if not isinstance(infered, FunctionDef): - yield infered + for inferred in bases._infer_stmts([cls[name]], context, frame=self): + if not isinstance(inferred, scoped_nodes.FunctionDef): + yield inferred continue # We can obtain different descriptors from a super depending # on what we are accessing and where the super call is. - if infered.type == 'classmethod': - yield BoundMethod(infered, cls) - elif self._scope.type == 'classmethod' and infered.type == 'method': - yield infered - elif self._class_based or infered.type == 'staticmethod': - yield infered - elif _is_property(infered): + if inferred.type == 'classmethod': + yield bases.BoundMethod(inferred, cls) + elif self._scope.type == 'classmethod' and inferred.type == 'method': + yield inferred + elif self._class_based or inferred.type == 'staticmethod': + yield inferred + elif bases._is_property(inferred): # TODO: support other descriptors as well. - for value in infered.infer_call_result(self, context): + for value in inferred.infer_call_result(self, context): yield value else: - yield BoundMethod(infered, cls) + yield bases.BoundMethod(inferred, cls) if not found: - raise NotFoundError(name) + raise exceptions.AttributeInferenceError(target=self, + attribute=name, + context=context) def getattr(self, name, context=None): return list(self.igetattr(name, context=context)) + + +class ExceptionInstance(bases.Instance): + """Class for instances of exceptions + + It has special treatment for some of the exceptions's attributes, + which are transformed at runtime into certain concrete objects, such as + the case of .args. + """ + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.ExceptionInstanceModel()) + + +class DictInstance(bases.Instance): + """Special kind of instances for dictionaries + + This instance knows the underlying object model of the dictionaries, which means + that methods such as .values or .items can be properly inferred. + """ + + # pylint: disable=unnecessary-lambda + special_attributes = util.lazy_descriptor(lambda: objectmodel.DictModel()) + + +# Custom objects tailored for dictionaries, which are used to +# disambiguate between the types of Python 2 dict's method returns +# and Python 3 (where they return set like objects). +class DictItems(bases.Proxy): + __str__ = node_classes.NodeNG.__str__ + __repr__ = node_classes.NodeNG.__repr__ + + +class DictKeys(bases.Proxy): + __str__ = node_classes.NodeNG.__str__ + __repr__ = node_classes.NodeNG.__repr__ + + +class DictValues(bases.Proxy): + __str__ = node_classes.NodeNG.__str__ + __repr__ = node_classes.NodeNG.__repr__ + +# TODO: Hack to solve the circular import problem between node_classes and objects +# This is not needed in 2.0, which has a cleaner design overall +node_classes.Dict.__bases__ = (node_classes.NodeNG, DictInstance) diff --git a/pymode/libs/astroid/protocols.py b/pymode/libs/astroid/protocols.py index 87a6d4d2..f19a9f41 100644 --- a/pymode/libs/astroid/protocols.py +++ b/pymode/libs/astroid/protocols.py @@ -1,39 +1,45 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """this module contains a set of functions to handle python protocols for nodes where it makes sense. """ import collections -import operator +import operator as operator_mod import sys +import six + from astroid import arguments from astroid import bases from astroid import context as contextmod from astroid import exceptions +from astroid import decorators from astroid import node_classes +from astroid import helpers from astroid import nodes from astroid import util +raw_building = util.lazy_import('raw_building') +objects = util.lazy_import('objects') + +def _reflected_name(name): + return "__r" + name[2:] + +def _augmented_name(name): + return "__i" + name[2:] + + +_CONTEXTLIB_MGR = 'contextlib.contextmanager' BIN_OP_METHOD = {'+': '__add__', '-': '__sub__', - '/': '__div__', + '/': '__div__' if six.PY2 else '__truediv__', '//': '__floordiv__', '*': '__mul__', '**': '__pow__', @@ -46,41 +52,40 @@ '@': '__matmul__' } +REFLECTED_BIN_OP_METHOD = { + key: _reflected_name(value) + for (key, value) in BIN_OP_METHOD.items() +} +AUGMENTED_OP_METHOD = { + key + "=": _augmented_name(value) + for (key, value) in BIN_OP_METHOD.items() +} + UNARY_OP_METHOD = {'+': '__pos__', '-': '__neg__', '~': '__invert__', 'not': None, # XXX not '__nonzero__' } +_UNARY_OPERATORS = { + '+': operator_mod.pos, + '-': operator_mod.neg, + '~': operator_mod.invert, + 'not': operator_mod.not_, +} -# unary operations ############################################################ -def tl_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not bool(self.elts)) - raise TypeError() # XXX log unsupported operation -nodes.Tuple.infer_unary_op = tl_infer_unary_op -nodes.List.infer_unary_op = tl_infer_unary_op +def _infer_unary_op(obj, op): + func = _UNARY_OPERATORS[op] + value = func(obj) + return nodes.const_factory(value) +nodes.Tuple.infer_unary_op = lambda self, op: _infer_unary_op(tuple(self.elts), op) +nodes.List.infer_unary_op = lambda self, op: _infer_unary_op(self.elts, op) +nodes.Set.infer_unary_op = lambda self, op: _infer_unary_op(set(self.elts), op) +nodes.Const.infer_unary_op = lambda self, op: _infer_unary_op(self.value, op) +nodes.Dict.infer_unary_op = lambda self, op: _infer_unary_op(dict(self.items), op) -def dict_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not bool(self.items)) - raise TypeError() # XXX log unsupported operation -nodes.Dict.infer_unary_op = dict_infer_unary_op - - -def const_infer_unary_op(self, operator): - if operator == 'not': - return node_classes.const_factory(not self.value) - # XXX log potentially raised TypeError - elif operator == '+': - return node_classes.const_factory(+self.value) - else: # operator == '-': - return node_classes.const_factory(-self.value) -nodes.Const.infer_unary_op = const_infer_unary_op - - -# binary operations ########################################################### +# Binary operations BIN_OP_IMPL = {'+': lambda a, b: a + b, '-': lambda a, b: a - b, @@ -95,50 +100,45 @@ def const_infer_unary_op(self, operator): '<<': lambda a, b: a << b, '>>': lambda a, b: a >> b, } - if sys.version_info >= (3, 5): # MatMult is available since Python 3.5+. - BIN_OP_IMPL['@'] = operator.matmul + BIN_OP_IMPL['@'] = operator_mod.matmul -for key, impl in list(BIN_OP_IMPL.items()): - BIN_OP_IMPL[key+'='] = impl +for _KEY, _IMPL in list(BIN_OP_IMPL.items()): + BIN_OP_IMPL[_KEY + '='] = _IMPL -def const_infer_binary_op(self, binop, other, context): - operator = binop.op - for other in other.infer(context): - if isinstance(other, nodes.Const): - try: - impl = BIN_OP_IMPL[operator] - try: - yield node_classes.const_factory(impl(self.value, other.value)) - except Exception: - # ArithmeticError is not enough: float >> float is a TypeError - # TODO : let pylint know about the problem - pass - except TypeError: - # XXX log TypeError - continue - elif other is util.YES: - yield other - else: +@decorators.yes_if_nothing_inferred +def const_infer_binary_op(self, opnode, operator, other, context, _): + not_implemented = nodes.Const(NotImplemented) + if isinstance(other, nodes.Const): + try: + impl = BIN_OP_IMPL[operator] try: - for val in other.infer_binary_op(binop, self, context): - yield val - except AttributeError: - yield util.YES -nodes.Const.infer_binary_op = bases.yes_if_nothing_inferred(const_infer_binary_op) + yield nodes.const_factory(impl(self.value, other.value)) + except TypeError: + # ArithmeticError is not enough: float >> float is a TypeError + yield not_implemented + except Exception: # pylint: disable=broad-except + yield util.Uninferable + except TypeError: + yield not_implemented + elif isinstance(self.value, six.string_types) and operator == '%': + # TODO(cpopa): implement string interpolation later on. + yield util.Uninferable + else: + yield not_implemented +nodes.Const.infer_binary_op = const_infer_binary_op -def _multiply_seq_by_int(self, binop, other, context): - node = self.__class__() - node.parent = binop +def _multiply_seq_by_int(self, opnode, other, context): + node = self.__class__(parent=opnode) elts = [] for elt in self.elts: - infered = util.safe_infer(elt, context) + infered = helpers.safe_infer(elt, context) if infered is None: - infered = util.YES + infered = util.Uninferable elts.append(infered) node.elts = elts * other.value return node @@ -146,61 +146,50 @@ def _multiply_seq_by_int(self, binop, other, context): def _filter_uninferable_nodes(elts, context): for elt in elts: - if elt is util.YES: - yield elt + if elt is util.Uninferable: + yield nodes.Unknown() else: for inferred in elt.infer(context): - yield inferred - - -def tl_infer_binary_op(self, binop, other, context): - operator = binop.op - for other in other.infer(context): - if isinstance(other, self.__class__) and operator == '+': - node = self.__class__() - node.parent = binop - elts = list(_filter_uninferable_nodes(self.elts, context)) - elts += list(_filter_uninferable_nodes(other.elts, context)) - node.elts = elts - yield node - elif isinstance(other, nodes.Const) and operator == '*': - if not isinstance(other.value, int): - yield util.YES - continue - yield _multiply_seq_by_int(self, binop, other, context) - elif isinstance(other, bases.Instance) and not isinstance(other, nodes.Const): - yield util.YES - # XXX else log TypeError -nodes.Tuple.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op) -nodes.List.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op) - - -def dict_infer_binary_op(self, binop, other, context): - for other in other.infer(context): - if isinstance(other, bases.Instance) and isinstance(other._proxied, nodes.ClassDef): - yield util.YES - # XXX else log TypeError -nodes.Dict.infer_binary_op = bases.yes_if_nothing_inferred(dict_infer_binary_op) - -def instance_infer_binary_op(self, binop, other, context): - operator = binop.op - try: - methods = self.getattr(BIN_OP_METHOD[operator]) - except (exceptions.NotFoundError, KeyError): - # Unknown operator - yield util.YES + if inferred is not util.Uninferable: + yield inferred + else: + yield nodes.Unknown() + + +@decorators.yes_if_nothing_inferred +def tl_infer_binary_op(self, opnode, operator, other, context, method): + not_implemented = nodes.Const(NotImplemented) + if isinstance(other, self.__class__) and operator == '+': + node = self.__class__(parent=opnode) + elts = list(_filter_uninferable_nodes(self.elts, context)) + elts += list(_filter_uninferable_nodes(other.elts, context)) + node.elts = elts + yield node + elif isinstance(other, nodes.Const) and operator == '*': + if not isinstance(other.value, int): + yield not_implemented + return + yield _multiply_seq_by_int(self, opnode, other, context) + elif isinstance(other, bases.Instance) and operator == '*': + # Verify if the instance supports __index__. + as_index = helpers.class_instance_as_index(other) + if not as_index: + yield util.Uninferable + else: + yield _multiply_seq_by_int(self, opnode, as_index, context) else: - for method in methods: - if not isinstance(method, nodes.FunctionDef): - continue - for result in method.infer_call_result(self, context): - if result is not util.YES: - yield result - # We are interested only in the first infered method, - # don't go looking in the rest of the methods of the ancestors. - break + yield not_implemented + +nodes.Tuple.infer_binary_op = tl_infer_binary_op +nodes.List.infer_binary_op = tl_infer_binary_op + + +@decorators.yes_if_nothing_inferred +def instance_class_infer_binary_op(self, opnode, operator, other, context, method): + return method.infer_call_result(self, context) -bases.Instance.infer_binary_op = bases.yes_if_nothing_inferred(instance_infer_binary_op) +bases.Instance.infer_binary_op = instance_class_infer_binary_op +nodes.ClassDef.infer_binary_op = instance_class_infer_binary_op # assignment ################################################################## @@ -221,7 +210,7 @@ def _resolve_looppart(parts, asspath, context): asspath = asspath[:] index = asspath.pop(0) for part in parts: - if part is util.YES: + if part is util.Uninferable: continue # XXX handle __iter__ and log potentially detected errors if not hasattr(part, 'itered'): @@ -231,31 +220,35 @@ def _resolve_looppart(parts, asspath, context): except TypeError: continue # XXX log error for stmt in itered: + index_node = nodes.Const(index) try: - assigned = stmt.getitem(index, context) - except (AttributeError, IndexError): - continue - except TypeError: # stmt is unsubscriptable Const + assigned = stmt.getitem(index_node, context) + except (AttributeError, + exceptions.AstroidTypeError, + exceptions.AstroidIndexError): continue if not asspath: # we achieved to resolved the assignment path, # don't infer the last part yield assigned - elif assigned is util.YES: + elif assigned is util.Uninferable: break else: # we are not yet on the last part of the path # search on each possibly inferred value try: for inferred in _resolve_looppart(assigned.infer(context), - asspath, context): + asspath, context): yield inferred except exceptions.InferenceError: break - -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred def for_assigned_stmts(self, node=None, context=None, asspath=None): + if isinstance(self, nodes.AsyncFor) or getattr(self, 'is_async', False): + # Skip inferring of async code for now + raise StopIteration(dict(node=self, unknown=node, + assign_path=asspath, context=context)) if asspath is None: for lst in self.iter.infer(context): if isinstance(lst, (nodes.Tuple, nodes.List)): @@ -263,8 +256,12 @@ def for_assigned_stmts(self, node=None, context=None, asspath=None): yield item else: for inferred in _resolve_looppart(self.iter.infer(context), - asspath, context): + asspath, context): yield inferred + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, unknown=node, + assign_path=asspath, context=context)) nodes.For.assigned_stmts = for_assigned_stmts nodes.Comprehension.assigned_stmts = for_assigned_stmts @@ -276,9 +273,9 @@ def sequence_assigned_stmts(self, node=None, context=None, asspath=None): try: index = self.elts.index(node) except ValueError: - util.reraise(exceptions.InferenceError( - 'Tried to retrieve a node {node!r} which does not exist', - node=self, assign_path=asspath, context=context)) + util.reraise(exceptions.InferenceError( + 'Tried to retrieve a node {node!r} which does not exist', + node=self, assign_path=asspath, context=context)) asspath.insert(0, index) return self.parent.assigned_stmts(node=self, context=context, asspath=asspath) @@ -297,17 +294,21 @@ def _arguments_infer_argname(self, name, context): # arguments information may be missing, in which case we can't do anything # more if not (self.args or self.vararg or self.kwarg): - yield util.YES + yield util.Uninferable return # first argument of instance/class method if self.args and getattr(self.args[0], 'name', None) == name: functype = self.parent.type + cls = self.parent.parent.scope() + is_metaclass = isinstance(cls, nodes.ClassDef) and cls.type == 'metaclass' + # If this is a metaclass, then the first argument will always + # be the class, not an instance. + if is_metaclass or functype == 'classmethod': + yield cls + return if functype == 'method': yield bases.Instance(self.parent.parent.frame()) return - if functype == 'classmethod': - yield self.parent.parent.frame() - return if context and context.callcontext: call_site = arguments.CallSite(context.callcontext) @@ -317,24 +318,24 @@ def _arguments_infer_argname(self, name, context): # TODO: just provide the type here, no need to have an empty Dict. if name == self.vararg: - vararg = node_classes.const_factory(()) + vararg = nodes.const_factory(()) vararg.parent = self yield vararg return if name == self.kwarg: - kwarg = node_classes.const_factory({}) + kwarg = nodes.const_factory({}) kwarg.parent = self yield kwarg return - # if there is a default value, yield it. And then yield YES to reflect + # if there is a default value, yield it. And then yield Uninferable to reflect # we can't guess given argument value try: context = contextmod.copy_context(context) for inferred in self.default_value(name).infer(context): yield inferred - yield util.YES + yield util.Uninferable except exceptions.NoDefault: - yield util.YES + yield util.Uninferable def arguments_assigned_stmts(self, node=None, context=None, asspath=None): @@ -350,15 +351,28 @@ def arguments_assigned_stmts(self, node=None, context=None, asspath=None): nodes.Arguments.assigned_stmts = arguments_assigned_stmts -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred def assign_assigned_stmts(self, node=None, context=None, asspath=None): if not asspath: yield self.value return for inferred in _resolve_asspart(self.value.infer(context), asspath, context): yield inferred + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, unknown=node, + assign_path=asspath, context=context)) + + +def assign_annassigned_stmts(self, node=None, context=None, asspath=None): + for inferred in assign_assigned_stmts(self, node, context, asspath): + if inferred is None: + yield util.Uninferable + else: + yield inferred nodes.Assign.assigned_stmts = assign_assigned_stmts +nodes.AnnAssign.assigned_stmts = assign_annassigned_stmts nodes.AugAssign.assigned_stmts = assign_assigned_stmts @@ -368,96 +382,212 @@ def _resolve_asspart(parts, asspath, context): index = asspath.pop(0) for part in parts: if hasattr(part, 'getitem'): + index_node = nodes.Const(index) try: - assigned = part.getitem(index, context) + assigned = part.getitem(index_node, context) # XXX raise a specific exception to avoid potential hiding of # unexpected exception ? - except (TypeError, IndexError): + except (exceptions.AstroidTypeError, exceptions.AstroidIndexError): return if not asspath: # we achieved to resolved the assignment path, don't infer the # last part yield assigned - elif assigned is util.YES: + elif assigned is util.Uninferable: return else: # we are not yet on the last part of the path search on each # possibly inferred value try: for inferred in _resolve_asspart(assigned.infer(context), - asspath, context): + asspath, context): yield inferred except exceptions.InferenceError: return -@bases.raise_if_nothing_inferred +@decorators.raise_if_nothing_inferred def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None): for assigned in node_classes.unpack_infer(self.type): if isinstance(assigned, nodes.ClassDef): - assigned = bases.Instance(assigned) + assigned = objects.ExceptionInstance(assigned) + yield assigned -nodes.ExceptHandler.assigned_stmts = bases.raise_if_nothing_inferred(excepthandler_assigned_stmts) + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, unknown=node, + assign_path=asspath, context=context)) + + +nodes.ExceptHandler.assigned_stmts = excepthandler_assigned_stmts + + +def _infer_context_manager(self, mgr, context): + try: + inferred = next(mgr.infer(context=context)) + except exceptions.InferenceError: + return + if isinstance(inferred, bases.Generator): + # Check if it is decorated with contextlib.contextmanager. + func = inferred.parent + if not func.decorators: + return + for decorator_node in func.decorators.nodes: + decorator = next(decorator_node.infer(context)) + if isinstance(decorator, nodes.FunctionDef): + if decorator.qname() == _CONTEXTLIB_MGR: + break + else: + # It doesn't interest us. + return + # Get the first yield point. If it has multiple yields, + # then a RuntimeError will be raised. + # TODO(cpopa): Handle flows. + yield_point = next(func.nodes_of_class(nodes.Yield), None) + if yield_point: + if not yield_point.value: + # TODO(cpopa): an empty yield. Should be wrapped to Const. + const = nodes.Const(None) + const.parent = yield_point + const.lineno = yield_point.lineno + yield const + else: + for inferred in yield_point.value.infer(context=context): + yield inferred + elif isinstance(inferred, bases.Instance): + try: + enter = next(inferred.igetattr('__enter__', context=context)) + except (exceptions.InferenceError, exceptions.AttributeInferenceError): + return + if not isinstance(enter, bases.BoundMethod): + return + if not context.callcontext: + context.callcontext = contextmod.CallContext(args=[inferred]) + for result in enter.infer_call_result(self, context): + yield result -@bases.raise_if_nothing_inferred + +@decorators.raise_if_nothing_inferred def with_assigned_stmts(self, node=None, context=None, asspath=None): + """Infer names and other nodes from a *with* statement. + + This enables only inference for name binding in a *with* statement. + For instance, in the following code, inferring `func` will return + the `ContextManager` class, not whatever ``__enter__`` returns. + We are doing this intentionally, because we consider that the context + manager result is whatever __enter__ returns and what it is binded + using the ``as`` keyword. + + class ContextManager(object): + def __enter__(self): + return 42 + with ContextManager() as f: + pass + # ContextManager().infer() will return ContextManager + # f.infer() will return 42. + + Arguments: + self: nodes.With + node: The target of the assignment, `as (a, b)` in `with foo as (a, b)`. + context: TODO + asspath: TODO + """ + mgr = next(mgr for (mgr, vars) in self.items if vars == node) if asspath is None: - for _, vars in self.items: - if vars is None: - continue - for lst in vars.infer(context): - if isinstance(lst, (nodes.Tuple, nodes.List)): - for item in lst.nodes: - yield item + for result in _infer_context_manager(self, mgr, context): + yield result + else: + for result in _infer_context_manager(self, mgr, context): + # Walk the asspath and get the item at the final index. + obj = result + for index in asspath: + if not hasattr(obj, 'elts'): + raise exceptions.InferenceError( + 'Wrong type ({targets!r}) for {node!r} assignment', + node=self, targets=node, assign_path=asspath, + context=context) + try: + obj = obj.elts[index] + except IndexError: + util.reraise(exceptions.InferenceError( + 'Tried to infer a nonexistent target with index {index} ' + 'in {node!r}.', node=self, targets=node, + assign_path=asspath, context=context)) + except TypeError: + util.reraise(exceptions.InferenceError( + 'Tried to unpack an non-iterable value ' + 'in {node!r}.', node=self, targets=node, + assign_path=asspath, context=context)) + yield obj + # Explicit StopIteration to return error information, see comment + # in raise_if_nothing_inferred. + raise StopIteration(dict(node=self, unknown=node, + assign_path=asspath, context=context)) + nodes.With.assigned_stmts = with_assigned_stmts -@bases.yes_if_nothing_inferred +@decorators.yes_if_nothing_inferred def starred_assigned_stmts(self, node=None, context=None, asspath=None): + """ + Arguments: + self: nodes.Starred + node: TODO + context: TODO + asspath: TODO + """ stmt = self.statement() if not isinstance(stmt, (nodes.Assign, nodes.For)): - raise exceptions.InferenceError() + raise exceptions.InferenceError('Statement {stmt!r} enclosing {node!r} ' + 'must be an Assign or For node.', + node=self, stmt=stmt, unknown=node, + context=context) if isinstance(stmt, nodes.Assign): value = stmt.value lhs = stmt.targets[0] if sum(1 for node in lhs.nodes_of_class(nodes.Starred)) > 1: - # Too many starred arguments in the expression. - raise exceptions.InferenceError() + raise exceptions.InferenceError('Too many starred arguments in the ' + ' assignment targets {lhs!r}.', + node=self, targets=lhs, + unknown=node, context=context) if context is None: context = contextmod.InferenceContext() try: rhs = next(value.infer(context)) except exceptions.InferenceError: - yield util.YES + yield util.Uninferable return - if rhs is util.YES or not hasattr(rhs, 'elts'): + if rhs is util.Uninferable or not hasattr(rhs, 'elts'): # Not interested in inferred values without elts. - yield util.YES + yield util.Uninferable return elts = collections.deque(rhs.elts[:]) if len(lhs.elts) > len(rhs.elts): - # a, *b, c = (1, 2) - raise exceptions.InferenceError() + raise exceptions.InferenceError('More targets, {targets!r}, than ' + 'values to unpack, {values!r}.', + node=self, targets=lhs, + values=rhs, unknown=node, + context=context) # Unpack iteratively the values from the rhs of the assignment, # until the find the starred node. What will remain will # be the list of values which the Starred node will represent # This is done in two steps, from left to right to remove # anything before the starred node and from right to left - # to remvoe anything after the starred node. + # to remove anything after the starred node. - for index, node in enumerate(lhs.elts): - if not isinstance(node, nodes.Starred): + for index, left_node in enumerate(lhs.elts): + if not isinstance(left_node, nodes.Starred): elts.popleft() continue lhs_elts = collections.deque(reversed(lhs.elts[index:])) - for node in lhs_elts: - if not isinstance(node, nodes.Starred): + for right_node in lhs_elts: + if not isinstance(right_node, nodes.Starred): elts.pop() continue # We're done diff --git a/pymode/libs/astroid/raw_building.py b/pymode/libs/astroid/raw_building.py index aaaf52f2..21e60d11 100644 --- a/pymode/libs/astroid/raw_building.py +++ b/pymode/libs/astroid/raw_building.py @@ -1,47 +1,42 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """this module contains a set of functions to create astroid trees from scratch (build_* functions) or from living object (object_build_* functions) """ -import sys +import inspect +import logging import os -from os.path import abspath -from inspect import (getargspec, isdatadescriptor, isfunction, ismethod, - ismethoddescriptor, isclass, isbuiltin, ismodule) +import sys +import types + import six -from astroid.node_classes import CONST_CLS -from astroid.nodes import (Module, Class, Const, const_factory, From, - Function, EmptyNode, Name, Arguments) -from astroid.bases import BUILTINS, Generator -from astroid.manager import AstroidManager -MANAGER = AstroidManager() +from astroid import bases +from astroid import manager +from astroid import node_classes +from astroid import nodes -_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types + +MANAGER = manager.AstroidManager() +# the keys of CONST_CLS eg python builtin types +_CONSTANTS = tuple(node_classes.CONST_CLS) _JYTHON = os.name == 'java' _BUILTINS = vars(six.moves.builtins) +_LOG = logging.getLogger(__name__) + def _io_discrepancy(member): # _io module names itself `io`: http://bugs.python.org/issue18602 member_self = getattr(member, '__self__', None) return (member_self and - ismodule(member_self) and + inspect.ismodule(member_self) and member_self.__name__ == '_io' and member.__module__ == 'io') @@ -56,72 +51,75 @@ def _add_dunder_class(func, member): cls_name = getattr(python_cls, '__name__', None) if not cls_name: return - bases = [ancestor.__name__ for ancestor in python_cls.__bases__] - ast_klass = build_class(cls_name, bases, python_cls.__doc__) - func._instance_attrs['__class__'] = [ast_klass] + cls_bases = [ancestor.__name__ for ancestor in python_cls.__bases__] + ast_klass = build_class(cls_name, cls_bases, python_cls.__doc__) + func.instance_attrs['__class__'] = [ast_klass] _marker = object() -def attach_dummy_node(node, name, object=_marker): + +def attach_dummy_node(node, name, runtime_object=_marker): """create a dummy node and register it in the locals of the given node with the specified name """ - enode = EmptyNode() - enode.object = object + enode = nodes.EmptyNode() + enode.object = runtime_object _attach_local_node(node, enode, name) def _has_underlying_object(self): - return hasattr(self, 'object') and self.object is not _marker + return self.object is not None and self.object is not _marker -EmptyNode.has_underlying_object = _has_underlying_object +nodes.EmptyNode.has_underlying_object = _has_underlying_object def attach_const_node(node, name, value): """create a Const node and register it in the locals of the given node with the specified name """ - if not name in node.special_attributes: - _attach_local_node(node, const_factory(value), name) + if name not in node.special_attributes: + _attach_local_node(node, nodes.const_factory(value), name) def attach_import_node(node, modname, membername): - """create a From node and register it in the locals of the given + """create a ImportFrom node and register it in the locals of the given node with the specified name """ - from_node = From(modname, [(membername, None)]) + from_node = nodes.ImportFrom(modname, [(membername, None)]) _attach_local_node(node, from_node, membername) def build_module(name, doc=None): """create and initialize a astroid Module node""" - node = Module(name, doc, pure_python=False) + node = nodes.Module(name, doc, pure_python=False) node.package = False node.parent = None return node + def build_class(name, basenames=(), doc=None): - """create and initialize a astroid Class node""" - node = Class(name, doc) + """create and initialize a astroid ClassDef node""" + node = nodes.ClassDef(name, doc) for base in basenames: - basenode = Name() + basenode = nodes.Name() basenode.name = base node.bases.append(basenode) basenode.parent = node return node -def build_function(name, args=None, defaults=None, flag=0, doc=None): - """create and initialize a astroid Function node""" + +def build_function(name, args=None, defaults=None, doc=None): + """create and initialize a astroid FunctionDef node""" args, defaults = args or [], defaults or [] # first argument is now a list of decorators - func = Function(name, doc) - func.args = argsnode = Arguments() + func = nodes.FunctionDef(name, doc) + func.args = argsnode = nodes.Arguments() argsnode.args = [] for arg in args: - argsnode.args.append(Name()) + argsnode.args.append(nodes.Name()) argsnode.args[-1].name = arg argsnode.args[-1].parent = argsnode argsnode.defaults = [] for default in defaults: - argsnode.defaults.append(const_factory(default)) + argsnode.defaults.append(nodes.const_factory(default)) argsnode.defaults[-1].parent = argsnode argsnode.kwarg = None argsnode.vararg = None @@ -132,8 +130,8 @@ def build_function(name, args=None, defaults=None, flag=0, doc=None): def build_from_import(fromname, names): - """create and initialize an astroid From import statement""" - return From(fromname, [(name, None) for name in names]) + """create and initialize an astroid ImportFrom import statement""" + return nodes.ImportFrom(fromname, [(name, None) for name in names]) def register_arguments(func, args=None): """add given arguments to local @@ -148,32 +146,37 @@ def register_arguments(func, args=None): if func.args.kwarg: func.set_local(func.args.kwarg, func.args) for arg in args: - if isinstance(arg, Name): + if isinstance(arg, nodes.Name): func.set_local(arg.name, arg) else: register_arguments(func, arg.elts) + def object_build_class(node, member, localname): """create astroid for a living class object""" basenames = [base.__name__ for base in member.__bases__] return _base_class_object_build(node, member, basenames, localname=localname) + def object_build_function(node, member, localname): """create astroid for a living function object""" - args, varargs, varkw, defaults = getargspec(member) + # pylint: disable=deprecated-method; completely removed in 2.0 + args, varargs, varkw, defaults = inspect.getargspec(member) if varargs is not None: args.append(varargs) if varkw is not None: args.append(varkw) func = build_function(getattr(member, '__name__', None) or localname, args, - defaults, six.get_function_code(member).co_flags, member.__doc__) + defaults, member.__doc__) node.add_local_node(func, localname) + def object_build_datadescriptor(node, member, name): """create astroid for a living data descriptor object""" return _base_class_object_build(node, member, [], name) + def object_build_methoddescriptor(node, member, localname): """create astroid for a living method descriptor object""" # FIXME get arguments ? @@ -185,6 +188,7 @@ def object_build_methoddescriptor(node, member, localname): node.add_local_node(func, localname) _add_dunder_class(func, member) + def _base_class_object_build(node, member, basenames, name=None, localname=None): """create astroid for a living class object, with a given set of base names (e.g. ancestors) @@ -202,25 +206,41 @@ def _base_class_object_build(node, member, basenames, name=None, localname=None) instdict = member().__dict__ else: raise TypeError - except: + except: # pylint: disable=bare-except pass else: - for name, obj in instdict.items(): - valnode = EmptyNode() + for item_name, obj in instdict.items(): + valnode = nodes.EmptyNode() valnode.object = obj valnode.parent = klass valnode.lineno = 1 - klass._instance_attrs[name] = [valnode] + klass.instance_attrs[item_name] = [valnode] return klass +def _build_from_function(node, name, member, module): + # verify this is not an imported function + try: + code = six.get_function_code(member) + except AttributeError: + # Some implementations don't provide the code object, + # such as Jython. + code = None + filename = getattr(code, 'co_filename', None) + if filename is None: + assert isinstance(member, object) + object_build_methoddescriptor(node, member, name) + elif filename != getattr(module, '__file__', None): + attach_dummy_node(node, name, member) + else: + object_build_function(node, member, name) class InspectBuilder(object): """class for building nodes from living object this is actually a really minimal representation, including only Module, - Function and Class nodes and some others as guessed. + FunctionDef and ClassDef nodes and some others as guessed. """ # astroid from living objects ############################################### @@ -242,7 +262,7 @@ def inspect_build(self, module, modname=None, path=None): except AttributeError: # in jython, java modules have no __doc__ (see #109562) node = build_module(modname) - node.source_file = path and abspath(path) or path + node.file = node.path = os.path.abspath(path) if path else path node.name = modname MANAGER.cache_module(node) node.package = hasattr(module, '__path__') @@ -264,30 +284,21 @@ def object_build(self, node, obj): # damned ExtensionClass.Base, I know you're there ! attach_dummy_node(node, name) continue - if ismethod(member): + if inspect.ismethod(member): member = six.get_method_function(member) - if isfunction(member): - # verify this is not an imported function - filename = getattr(six.get_function_code(member), - 'co_filename', None) - if filename is None: - assert isinstance(member, object) - object_build_methoddescriptor(node, member, name) - elif filename != getattr(self._module, '__file__', None): - attach_dummy_node(node, name, member) - else: - object_build_function(node, member, name) - elif isbuiltin(member): + if inspect.isfunction(member): + _build_from_function(node, name, member, self._module) + elif inspect.isbuiltin(member): if (not _io_discrepancy(member) and self.imported_member(node, member, name)): continue object_build_methoddescriptor(node, member, name) - elif isclass(member): + elif inspect.isclass(member): if self.imported_member(node, member, name): continue if member in self._done: class_node = self._done[member] - if not class_node in node._locals.get(name, ()): + if class_node not in node.locals.get(name, ()): node.add_local_node(class_node, name) else: class_node = object_build_class(node, member, name) @@ -295,14 +306,18 @@ def object_build(self, node, obj): self.object_build(class_node, member) if name == '__class__' and class_node.parent is None: class_node.parent = self._done[self._module] - elif ismethoddescriptor(member): + elif inspect.ismethoddescriptor(member): assert isinstance(member, object) object_build_methoddescriptor(node, member, name) - elif isdatadescriptor(member): + elif inspect.isdatadescriptor(member): assert isinstance(member, object) object_build_datadescriptor(node, member, name) - elif type(member) in _CONSTANTS: + elif isinstance(member, _CONSTANTS): attach_const_node(node, name, member) + elif inspect.isroutine(member): + # This should be called for Jython, where some builtin + # methods aren't caught by isbuiltin branch. + _build_from_function(node, name, member, self._module) else: # create an empty node so that the name is actually defined attach_dummy_node(node, name, member) @@ -314,11 +329,9 @@ def imported_member(self, node, member, name): # (see http://www.logilab.org/ticket/57299 for instance) try: modname = getattr(member, '__module__', None) - except: - # XXX use logging - print('unexpected error while building astroid from living object') - import traceback - traceback.print_exc() + except: # pylint: disable=bare-except + _LOG.exception('unexpected error while building ' + 'astroid from living object') modname = None if modname is None: if (name in ('__new__', '__subclasshook__') @@ -326,7 +339,7 @@ def imported_member(self, node, member, name): # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14) # >>> print object.__new__.__module__ # None - modname = BUILTINS + modname = six.moves.builtins.__name__ else: attach_dummy_node(node, name, member) return True @@ -361,7 +374,8 @@ def _astroid_bootstrapping(astroid_builtin=None): from six.moves import builtins astroid_builtin = Astroid_BUILDER.inspect_build(builtins) - for cls, node_cls in CONST_CLS.items(): + # pylint: disable=redefined-outer-name + for cls, node_cls in node_classes.CONST_CLS.items(): if cls is type(None): proxy = build_class('NoneType') proxy.parent = astroid_builtin @@ -382,9 +396,21 @@ def _astroid_bootstrapping(astroid_builtin=None): # infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870) def _set_proxied(const): return _CONST_PROXY[const.value.__class__] -Const._proxied = property(_set_proxied) - -from types import GeneratorType -Generator._proxied = Class(GeneratorType.__name__, GeneratorType.__doc__) -Astroid_BUILDER.object_build(Generator._proxied, GeneratorType) - +nodes.Const._proxied = property(_set_proxied) + +_GeneratorType = nodes.ClassDef(types.GeneratorType.__name__, types.GeneratorType.__doc__) +_GeneratorType.parent = MANAGER.astroid_cache[six.moves.builtins.__name__] +bases.Generator._proxied = _GeneratorType +Astroid_BUILDER.object_build(bases.Generator._proxied, types.GeneratorType) + +_builtins = MANAGER.astroid_cache[six.moves.builtins.__name__] +BUILTIN_TYPES = (types.GetSetDescriptorType, types.GeneratorType, + types.MemberDescriptorType, type(None), type(NotImplemented), + types.FunctionType, types.MethodType, + types.BuiltinFunctionType, types.ModuleType, types.TracebackType) +for _type in BUILTIN_TYPES: + if _type.__name__ not in _builtins: + cls = nodes.ClassDef(_type.__name__, _type.__doc__) + cls.parent = MANAGER.astroid_cache[six.moves.builtins.__name__] + Astroid_BUILDER.object_build(cls, _type) + _builtins[_type.__name__] = cls diff --git a/pymode/libs/astroid/rebuilder.py b/pymode/libs/astroid/rebuilder.py index 859b8280..60a1ad77 100644 --- a/pymode/libs/astroid/rebuilder.py +++ b/pymode/libs/astroid/rebuilder.py @@ -1,79 +1,60 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2009-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """this module contains utilities for rebuilding a _ast tree in order to get a single Astroid representation """ import sys import _ast -from _ast import ( - # binary operators - Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor, - LShift, RShift, - # logical operators - And, Or, - # unary operators - UAdd, USub, Not, Invert, - # comparison operators - Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn, - ) - -from astroid import nodes as new -from astroid import astpeephole - -_BIN_OP_CLASSES = {Add: '+', - BitAnd: '&', - BitOr: '|', - BitXor: '^', - Div: '/', - FloorDiv: '//', - Mod: '%', - Mult: '*', - Pow: '**', - Sub: '-', - LShift: '<<', - RShift: '>>', +import astroid +from astroid import astpeephole +from astroid import nodes + + + +_BIN_OP_CLASSES = {_ast.Add: '+', + _ast.BitAnd: '&', + _ast.BitOr: '|', + _ast.BitXor: '^', + _ast.Div: '/', + _ast.FloorDiv: '//', + _ast.Mod: '%', + _ast.Mult: '*', + _ast.Pow: '**', + _ast.Sub: '-', + _ast.LShift: '<<', + _ast.RShift: '>>', } if sys.version_info >= (3, 5): - from _ast import MatMult - _BIN_OP_CLASSES[MatMult] = '@' + _BIN_OP_CLASSES[_ast.MatMult] = '@' -_BOOL_OP_CLASSES = {And: 'and', - Or: 'or', +_BOOL_OP_CLASSES = {_ast.And: 'and', + _ast.Or: 'or', } -_UNARY_OP_CLASSES = {UAdd: '+', - USub: '-', - Not: 'not', - Invert: '~', +_UNARY_OP_CLASSES = {_ast.UAdd: '+', + _ast.USub: '-', + _ast.Not: 'not', + _ast.Invert: '~', } -_CMP_OP_CLASSES = {Eq: '==', - Gt: '>', - GtE: '>=', - In: 'in', - Is: 'is', - IsNot: 'is not', - Lt: '<', - LtE: '<=', - NotEq: '!=', - NotIn: 'not in', +_CMP_OP_CLASSES = {_ast.Eq: '==', + _ast.Gt: '>', + _ast.GtE: '>=', + _ast.In: 'in', + _ast.Is: 'is', + _ast.IsNot: 'is not', + _ast.Lt: '<', + _ast.LtE: '<=', + _ast.NotEq: '!=', + _ast.NotIn: 'not in', } CONST_NAME_TRANSFORMS = {'None': None, @@ -88,39 +69,25 @@ 'excepthandler': 'ExceptHandler', 'keyword': 'Keyword', } -PY3K = sys.version_info >= (3, 0) +PY3 = sys.version_info >= (3, 0) PY34 = sys.version_info >= (3, 4) +CONTEXTS = {_ast.Load: astroid.Load, + _ast.Store: astroid.Store, + _ast.Del: astroid.Del, + _ast.Param: astroid.Store} -def _init_set_doc(node, newnode): - newnode.doc = None + +def _get_doc(node): try: if isinstance(node.body[0], _ast.Expr) and isinstance(node.body[0].value, _ast.Str): - newnode.doc = node.body[0].value.s + doc = node.body[0].value.s node.body = node.body[1:] - + return node, doc except IndexError: pass # ast built from scratch + return node, None -def _lineno_parent(oldnode, newnode, parent): - newnode.parent = parent - newnode.lineno = oldnode.lineno - newnode.col_offset = oldnode.col_offset - -def _set_infos(oldnode, newnode, parent): - newnode.parent = parent - if hasattr(oldnode, 'lineno'): - newnode.lineno = oldnode.lineno - if hasattr(oldnode, 'col_offset'): - newnode.col_offset = oldnode.col_offset - -def _create_yield_node(node, parent, rebuilder, factory): - newnode = factory() - _lineno_parent(node, newnode, parent) - if node.value is not None: - newnode.value = rebuilder.visit(node.value, newnode, None) - return newnode - -def _visit_or_none(node, attr, visitor, parent, assign_ctx, visit='visit', +def _visit_or_none(node, attr, visitor, parent, visit='visit', **kws): """If the given node has an attribute, visits the attribute, and otherwise returns None. @@ -128,9 +95,13 @@ def _visit_or_none(node, attr, visitor, parent, assign_ctx, visit='visit', """ value = getattr(node, attr, None) if value: - return getattr(visitor, visit)(value, parent, assign_ctx, **kws) - else: - return None + return getattr(visitor, visit)(value, parent, **kws) + + return None + + +def _get_context(node): + return CONTEXTS.get(type(node.ctx), astroid.Load) class TreeRebuilder(object): @@ -138,7 +109,6 @@ class TreeRebuilder(object): def __init__(self, manager): self._manager = manager - self.asscontext = None self._global_names = [] self._import_from_nodes = [] self._delayed_assattr = [] @@ -147,15 +117,13 @@ def __init__(self, manager): def visit_module(self, node, modname, modpath, package): """visit a Module node by returning a fresh instance of it""" - newnode = new.Module(modname, None) - newnode.package = package - newnode.parent = None - _init_set_doc(node, newnode) - newnode.body = [self.visit(child, newnode) for child in node.body] - newnode.source_file = modpath + node, doc = _get_doc(node) + newnode = nodes.Module(name=modname, doc=doc, file=modpath, path=modpath, + package=package, parent=None) + newnode.postinit([self.visit(child, newnode) for child in node.body]) return newnode - def visit(self, node, parent, assign_ctx=None): + def visit(self, node, parent): cls = node.__class__ if cls in self._visit_meths: visit_method = self._visit_meths[cls] @@ -164,7 +132,7 @@ def visit(self, node, parent, assign_ctx=None): visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower() visit_method = getattr(self, visit_name) self._visit_meths[cls] = visit_method - return visit_method(node, parent, assign_ctx) + return visit_method(node, parent) def _save_assignment(self, node, name=None): """save assignement situation since node.parent is not available yet""" @@ -173,40 +141,68 @@ def _save_assignment(self, node, name=None): else: node.parent.set_local(node.name, node) - def visit_arguments(self, node, parent, assign_ctx=None): + def visit_arguments(self, node, parent): """visit a Arguments node by returning a fresh instance of it""" - newnode = new.Arguments() - newnode.parent = parent - newnode.args = [self.visit(child, newnode, "Assign") - for child in node.args] - newnode.defaults = [self.visit(child, newnode, assign_ctx) - for child in node.defaults] - newnode.kwonlyargs = [] - newnode.kw_defaults = [] vararg, kwarg = node.vararg, node.kwarg + if PY34: + newnode = nodes.Arguments(vararg.arg if vararg else None, + kwarg.arg if kwarg else None, + parent) + else: + newnode = nodes.Arguments(vararg, kwarg, parent) + args = [self.visit(child, newnode) for child in node.args] + defaults = [self.visit(child, newnode) + for child in node.defaults] + varargannotation = None + kwargannotation = None # change added in 82732 (7c5c678e4164), vararg and kwarg # are instances of `_ast.arg`, not strings if vararg: if PY34: - if vararg.annotation: - newnode.varargannotation = self.visit(vararg.annotation, - newnode, assign_ctx) + if node.vararg.annotation: + varargannotation = self.visit(node.vararg.annotation, + newnode) vararg = vararg.arg - elif PY3K and node.varargannotation: - newnode.varargannotation = self.visit(node.varargannotation, - newnode, assign_ctx) + elif PY3 and node.varargannotation: + varargannotation = self.visit(node.varargannotation, + newnode) if kwarg: if PY34: - if kwarg.annotation: - newnode.kwargannotation = self.visit(kwarg.annotation, - newnode, assign_ctx) + if node.kwarg.annotation: + kwargannotation = self.visit(node.kwarg.annotation, + newnode) kwarg = kwarg.arg - elif PY3K: + elif PY3: if node.kwargannotation: - newnode.kwargannotation = self.visit(node.kwargannotation, - newnode, assign_ctx) - newnode.vararg = vararg - newnode.kwarg = kwarg + kwargannotation = self.visit(node.kwargannotation, + newnode) + if PY3: + kwonlyargs = [self.visit(child, newnode) for child + in node.kwonlyargs] + kw_defaults = [self.visit(child, newnode) if child else + None for child in node.kw_defaults] + annotations = [self.visit(arg.annotation, newnode) if + arg.annotation else None for arg in node.args] + kwonlyargs_annotations = [ + self.visit(arg.annotation, newnode) if arg.annotation else None + for arg in node.kwonlyargs + ] + else: + kwonlyargs = [] + kw_defaults = [] + annotations = [] + kwonlyargs_annotations = [] + + newnode.postinit( + args=args, + defaults=defaults, + kwonlyargs=kwonlyargs, + kw_defaults=kw_defaults, + annotations=annotations, + kwonlyargs_annotations=kwonlyargs_annotations, + varargannotation=varargannotation, + kwargannotation=kwargannotation + ) # save argument names in locals: if vararg: newnode.parent.set_local(vararg, newnode) @@ -214,57 +210,46 @@ def visit_arguments(self, node, parent, assign_ctx=None): newnode.parent.set_local(kwarg, newnode) return newnode - def visit_assignattr(self, node, parent, assign_ctx=None): - """visit a AssAttr node by returning a fresh instance of it""" - newnode = new.AssignAttr() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.expr, newnode, assign_ctx) - self._delayed_assattr.append(newnode) - return newnode - - def visit_assert(self, node, parent, assign_ctx=None): + def visit_assert(self, node, parent): """visit a Assert node by returning a fresh instance of it""" - newnode = new.Assert() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - if node.msg is not None: - newnode.fail = self.visit(node.msg, newnode, assign_ctx) + newnode = nodes.Assert(node.lineno, node.col_offset, parent) + if node.msg: + msg = self.visit(node.msg, newnode) + else: + msg = None + newnode.postinit(self.visit(node.test, newnode), msg) return newnode - def visit_assign(self, node, parent, assign_ctx=None): + def visit_assign(self, node, parent): """visit a Assign node by returning a fresh instance of it""" - newnode = new.Assign() - _lineno_parent(node, newnode, parent) - newnode.targets = [self.visit(child, newnode, "Assign") - for child in node.targets] - newnode.value = self.visit(node.value, newnode, None) - return newnode - - def visit_assignname(self, node, parent, assign_ctx=None, node_name=None): - '''visit a node and return a AssName node''' - newnode = new.AssignName() - _set_infos(node, newnode, parent) - newnode.name = node_name + newnode = nodes.Assign(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.targets], + self.visit(node.value, newnode)) + return newnode + + def visit_assignname(self, node, parent, node_name=None): + '''visit a node and return a AssignName node''' + newnode = nodes.AssignName(node_name, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) self._save_assignment(newnode) return newnode - def visit_augassign(self, node, parent, assign_ctx=None): + def visit_augassign(self, node, parent): """visit a AugAssign node by returning a fresh instance of it""" - newnode = new.AugAssign() - _lineno_parent(node, newnode, parent) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "=" - newnode.target = self.visit(node.target, newnode, "Assign") - newnode.value = self.visit(node.value, newnode, None) + newnode = nodes.AugAssign(_BIN_OP_CLASSES[type(node.op)] + "=", + node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.target, newnode), + self.visit(node.value, newnode)) return newnode - def visit_repr(self, node, parent, assign_ctx=None): + def visit_repr(self, node, parent): """visit a Backquote node by returning a fresh instance of it""" - newnode = new.Repr() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) + newnode = nodes.Repr(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_binop(self, node, parent, assign_ctx=None): + def visit_binop(self, node, parent): """visit a BinOp node by returning a fresh instance of it""" if isinstance(node.left, _ast.BinOp) and self._manager.optimize_ast: # Optimize BinOp operations in order to remove @@ -279,711 +264,651 @@ def visit_binop(self, node, parent, assign_ctx=None): # problem for the correctness of the program). # # ("a" + "b" + # one thousand more + "c") - optimized = self._peepholer.optimize_binop(node) + optimized = self._peepholer.optimize_binop(node, parent) if optimized: - _lineno_parent(node, optimized, parent) return optimized - newnode = new.BinOp() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode, assign_ctx) - newnode.right = self.visit(node.right, newnode, assign_ctx) - newnode.op = _BIN_OP_CLASSES[node.op.__class__] + newnode = nodes.BinOp(_BIN_OP_CLASSES[type(node.op)], + node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.left, newnode), + self.visit(node.right, newnode)) return newnode - def visit_boolop(self, node, parent, assign_ctx=None): + def visit_boolop(self, node, parent): """visit a BoolOp node by returning a fresh instance of it""" - newnode = new.BoolOp() - _lineno_parent(node, newnode, parent) - newnode.values = [self.visit(child, newnode, assign_ctx) - for child in node.values] - newnode.op = _BOOL_OP_CLASSES[node.op.__class__] + newnode = nodes.BoolOp(_BOOL_OP_CLASSES[type(node.op)], + node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.values]) return newnode - def visit_break(self, node, parent, assign_ctx=None): + def visit_break(self, node, parent): """visit a Break node by returning a fresh instance of it""" - newnode = new.Break() - _set_infos(node, newnode, parent) - return newnode + return nodes.Break(getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), + parent) - def visit_call(self, node, parent, assign_ctx=None): + def visit_call(self, node, parent): """visit a CallFunc node by returning a fresh instance of it""" - newnode = new.Call() - _lineno_parent(node, newnode, parent) - newnode.func = self.visit(node.func, newnode, assign_ctx) - args = [self.visit(child, newnode, assign_ctx) + newnode = nodes.Call(node.lineno, node.col_offset, parent) + starargs = _visit_or_none(node, 'starargs', self, newnode) + kwargs = _visit_or_none(node, 'kwargs', self, newnode) + args = [self.visit(child, newnode) for child in node.args] - starargs = _visit_or_none(node, 'starargs', self, newnode, - assign_ctx) - kwargs = _visit_or_none(node, 'kwargs', self, newnode, - assign_ctx) - keywords = None if node.keywords: - keywords = [self.visit(child, newnode, assign_ctx) + keywords = [self.visit(child, newnode) for child in node.keywords] - + else: + keywords = None if starargs: - new_starargs = new.Starred() - new_starargs.col_offset = starargs.col_offset - new_starargs.lineno = starargs.lineno - new_starargs.parent = starargs.parent - new_starargs.value = starargs + new_starargs = nodes.Starred(col_offset=starargs.col_offset, + lineno=starargs.lineno, + parent=starargs.parent) + new_starargs.postinit(value=starargs) args.append(new_starargs) if kwargs: - new_kwargs = new.Keyword() - new_kwargs.arg = None - new_kwargs.col_offset = kwargs.col_offset - new_kwargs.lineno = kwargs.lineno - new_kwargs.parent = kwargs.parent - new_kwargs.value = kwargs + new_kwargs = nodes.Keyword(arg=None, col_offset=kwargs.col_offset, + lineno=kwargs.lineno, + parent=kwargs.parent) + new_kwargs.postinit(value=kwargs) if keywords: keywords.append(new_kwargs) else: keywords = [new_kwargs] - newnode.args = args - newnode.keywords = keywords - return newnode - - def visit_classdef(self, node, parent, assign_ctx=None): - """visit a Class node to become astroid""" - newnode = new.ClassDef(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.bases = [self.visit(child, newnode, assign_ctx) - for child in node.bases] - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] + newnode.postinit(self.visit(node.func, newnode), + args, keywords) + return newnode + + def visit_classdef(self, node, parent, newstyle=None): + """visit a ClassDef node to become astroid""" + node, doc = _get_doc(node) + newnode = nodes.ClassDef(node.name, doc, node.lineno, + node.col_offset, parent) + metaclass = None + if PY3: + for keyword in node.keywords: + if keyword.arg == 'metaclass': + metaclass = self.visit(keyword, newnode).value + break if node.decorator_list: - newnode.decorators = self.visit_decorators(node, newnode, assign_ctx) - newnode.parent.frame().set_local(newnode.name, newnode) + decorators = self.visit_decorators(node, newnode) + else: + decorators = None + newnode.postinit([self.visit(child, newnode) + for child in node.bases], + [self.visit(child, newnode) + for child in node.body], + decorators, newstyle, metaclass, + [self.visit(kwd, newnode) for kwd in node.keywords + if kwd.arg != 'metaclass'] if PY3 else []) return newnode - def visit_const(self, node, parent, assign_ctx=None): + def visit_const(self, node, parent): """visit a Const node by returning a fresh instance of it""" - newnode = new.Const(node.value) - _set_infos(node, newnode, parent) - return newnode + return nodes.Const(node.value, + getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) - def visit_continue(self, node, parent, assign_ctx=None): + def visit_continue(self, node, parent): """visit a Continue node by returning a fresh instance of it""" - newnode = new.Continue() - _set_infos(node, newnode, parent) - return newnode + return nodes.Continue(getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), + parent) - def visit_compare(self, node, parent, assign_ctx=None): + def visit_compare(self, node, parent): """visit a Compare node by returning a fresh instance of it""" - newnode = new.Compare() - _lineno_parent(node, newnode, parent) - newnode.left = self.visit(node.left, newnode, assign_ctx) - newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode, assign_ctx)) - for (op, expr) in zip(node.ops, node.comparators)] + newnode = nodes.Compare(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.left, newnode), + [(_CMP_OP_CLASSES[op.__class__], + self.visit(expr, newnode)) + for (op, expr) in zip(node.ops, node.comparators)]) return newnode - def visit_comprehension(self, node, parent, assign_ctx=None): + def visit_comprehension(self, node, parent): """visit a Comprehension node by returning a fresh instance of it""" - newnode = new.Comprehension() - newnode.parent = parent - newnode.target = self.visit(node.target, newnode, 'Assign') - newnode.iter = self.visit(node.iter, newnode, None) - newnode.ifs = [self.visit(child, newnode, None) - for child in node.ifs] + newnode = nodes.Comprehension(parent) + newnode.postinit(self.visit(node.target, newnode), + self.visit(node.iter, newnode), + [self.visit(child, newnode) + for child in node.ifs], + getattr(node, 'is_async', None)) return newnode - def visit_decorators(self, node, parent, assign_ctx=None): + def visit_decorators(self, node, parent): """visit a Decorators node by returning a fresh instance of it""" - # /!\ node is actually a _ast.Function node while - # parent is a astroid.nodes.Function node - newnode = new.Decorators() - _lineno_parent(node, newnode, parent) - decorators = node.decorator_list - newnode.nodes = [self.visit(child, newnode, assign_ctx) - for child in decorators] + # /!\ node is actually a _ast.FunctionDef node while + # parent is a astroid.nodes.FunctionDef node + newnode = nodes.Decorators(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.decorator_list]) return newnode - def visit_delete(self, node, parent, assign_ctx=None): + def visit_delete(self, node, parent): """visit a Delete node by returning a fresh instance of it""" - newnode = new.Delete() - _lineno_parent(node, newnode, parent) - newnode.targets = [self.visit(child, newnode, 'Del') - for child in node.targets] + newnode = nodes.Delete(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.targets]) return newnode - def _visit_dict_items(self, node, parent, newnode, assign_ctx): + def _visit_dict_items(self, node, parent, newnode): for key, value in zip(node.keys, node.values): - rebuilt_value = self.visit(value, newnode, assign_ctx) + rebuilt_value = self.visit(value, newnode) if not key: # Python 3.5 and extended unpacking - rebuilt_key = new.DictUnpack() - rebuilt_key.lineno = rebuilt_value.lineno - rebuilt_key.col_offset = rebuilt_value.col_offset - rebuilt_key.parent = rebuilt_value.parent + rebuilt_key = nodes.DictUnpack(rebuilt_value.lineno, + rebuilt_value.col_offset, + parent) else: - rebuilt_key = self.visit(key, newnode, assign_ctx) + rebuilt_key = self.visit(key, newnode) yield rebuilt_key, rebuilt_value - def visit_dict(self, node, parent, assign_ctx=None): + def visit_dict(self, node, parent): """visit a Dict node by returning a fresh instance of it""" - newnode = new.Dict() - _lineno_parent(node, newnode, parent) - newnode.items = list(self._visit_dict_items(node, parent, newnode, assign_ctx)) + newnode = nodes.Dict(node.lineno, node.col_offset, parent) + items = list(self._visit_dict_items(node, parent, newnode)) + newnode.postinit(items) return newnode - def visit_dictcomp(self, node, parent, assign_ctx=None): + def visit_dictcomp(self, node, parent): """visit a DictComp node by returning a fresh instance of it""" - newnode = new.DictComp() - _lineno_parent(node, newnode, parent) - newnode.key = self.visit(node.key, newnode, assign_ctx) - newnode.value = self.visit(node.value, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] + newnode = nodes.DictComp(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.key, newnode), + self.visit(node.value, newnode), + [self.visit(child, newnode) + for child in node.generators]) return newnode - def visit_expr(self, node, parent, assign_ctx=None): - """visit a Discard node by returning a fresh instance of it""" - newnode = new.Expr() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) + def visit_expr(self, node, parent): + """visit a Expr node by returning a fresh instance of it""" + newnode = nodes.Expr(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_ellipsis(self, node, parent, assign_ctx=None): + def visit_ellipsis(self, node, parent): """visit an Ellipsis node by returning a fresh instance of it""" - newnode = new.Ellipsis() - _set_infos(node, newnode, parent) - return newnode + return nodes.Ellipsis(getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) - def visit_emptynode(self, node, parent, assign_ctx=None): + + def visit_emptynode(self, node, parent): """visit an EmptyNode node by returning a fresh instance of it""" - newnode = new.EmptyNode() - _set_infos(node, newnode, parent) - return newnode + return nodes.EmptyNode(getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) + - def visit_excepthandler(self, node, parent, assign_ctx=None): + def visit_excepthandler(self, node, parent): """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode, assign_ctx) - if node.name is not None: - # /!\ node.name can be a tuple - newnode.name = self.visit(node.name, newnode, 'Assign') - newnode.body = [self.visit(child, newnode, None) - for child in node.body] + newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent) + # /!\ node.name can be a tuple + newnode.postinit(_visit_or_none(node, 'type', self, newnode), + _visit_or_none(node, 'name', self, newnode), + [self.visit(child, newnode) + for child in node.body]) return newnode - def visit_exec(self, node, parent, assign_ctx=None): + def visit_exec(self, node, parent): """visit an Exec node by returning a fresh instance of it""" - newnode = new.Exec() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.body, newnode) - if node.globals is not None: - newnode.globals = self.visit(node.globals, newnode, - assign_ctx) - if node.locals is not None: - newnode.locals = self.visit(node.locals, newnode, - assign_ctx) - return newnode - - def visit_extslice(self, node, parent, assign_ctx=None): + newnode = nodes.Exec(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.body, newnode), + _visit_or_none(node, 'globals', self, newnode), + _visit_or_none(node, 'locals', self, newnode)) + return newnode + + def visit_extslice(self, node, parent): """visit an ExtSlice node by returning a fresh instance of it""" - newnode = new.ExtSlice() - newnode.parent = parent - newnode.dims = [self.visit(dim, newnode, assign_ctx) - for dim in node.dims] + newnode = nodes.ExtSlice(parent=parent) + newnode.postinit([self.visit(dim, newnode) + for dim in node.dims]) return newnode - def _visit_for(self, cls, node, parent, assign_ctx=None): + def _visit_for(self, cls, node, parent): """visit a For node by returning a fresh instance of it""" - newnode = cls() - _lineno_parent(node, newnode, parent) - newnode.target = self.visit(node.target, newnode, "Assign") - newnode.iter = self.visit(node.iter, newnode, None) - newnode.body = [self.visit(child, newnode, None) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, None) - for child in node.orelse] + newnode = cls(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.target, newnode), + self.visit(node.iter, newnode), + [self.visit(child, newnode) + for child in node.body], + [self.visit(child, newnode) + for child in node.orelse]) return newnode - def visit_for(self, node, parent, assign_ctx=None): - return self._visit_for(new.For, node, parent, - assign_ctx=assign_ctx) - def visit_importfrom(self, node, parent, assign_ctx=None): - """visit a From node by returning a fresh instance of it""" + def visit_for(self, node, parent): + return self._visit_for(nodes.For, node, parent) + + def visit_importfrom(self, node, parent): + """visit an ImportFrom node by returning a fresh instance of it""" names = [(alias.name, alias.asname) for alias in node.names] - newnode = new.ImportFrom(node.module or '', names, node.level or None) - _set_infos(node, newnode, parent) + newnode = nodes.ImportFrom(node.module or '', names, node.level or None, + getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) # store From names to add them to locals after building self._import_from_nodes.append(newnode) return newnode - def _visit_functiondef(self, cls, node, parent, assign_ctx=None): + def _visit_functiondef(self, cls, node, parent): """visit an FunctionDef node to become astroid""" self._global_names.append({}) - newnode = cls(node.name, None) - _lineno_parent(node, newnode, parent) - _init_set_doc(node, newnode) - newnode.args = self.visit(node.args, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - decorators = node.decorator_list - if decorators: - newnode.decorators = self.visit_decorators( - node, newnode, assign_ctx) - if PY3K and node.returns: - newnode.returns = self.visit(node.returns, newnode, - assign_ctx) + node, doc = _get_doc(node) + newnode = cls(node.name, doc, node.lineno, + node.col_offset, parent) + if node.decorator_list: + decorators = self.visit_decorators(node, newnode) + else: + decorators = None + if PY3 and node.returns: + returns = self.visit(node.returns, newnode) + else: + returns = None + newnode.postinit(self.visit(node.args, newnode), + [self.visit(child, newnode) + for child in node.body], + decorators, returns) self._global_names.pop() - frame = newnode.parent.frame() - frame.set_local(newnode.name, newnode) return newnode - def visit_functiondef(self, node, parent, assign_ctx=None): - return self._visit_functiondef(new.FunctionDef, node, parent, - assign_ctx=assign_ctx) + def visit_functiondef(self, node, parent): + return self._visit_functiondef(nodes.FunctionDef, node, parent) - def visit_generatorexp(self, node, parent, assign_ctx=None): - """visit a GenExpr node by returning a fresh instance of it""" - newnode = new.GeneratorExp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] + def visit_generatorexp(self, node, parent): + """visit a GeneratorExp node by returning a fresh instance of it""" + newnode = nodes.GeneratorExp(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.elt, newnode), + [self.visit(child, newnode) + for child in node.generators]) return newnode - def visit_attribute(self, node, parent, assign_ctx=None): - """visit a Getattr node by returning a fresh instance of it""" - # pylint: disable=redefined-variable-type - if assign_ctx == "Del": + def visit_attribute(self, node, parent): + """visit an Attribute node by returning a fresh instance of it""" + context = _get_context(node) + if context == astroid.Del: # FIXME : maybe we should reintroduce and visit_delattr ? - # for instance, deactivating asscontext - newnode = new.DelAttr() - elif assign_ctx == "Assign": - # FIXME : maybe we should call visit_assattr ? + # for instance, deactivating assign_ctx + newnode = nodes.DelAttr(node.attr, node.lineno, node.col_offset, + parent) + elif context == astroid.Store: + newnode = nodes.AssignAttr(node.attr, node.lineno, node.col_offset, + parent) # Prohibit a local save if we are in an ExceptHandler. - newnode = new.AssignAttr() - if not isinstance(parent, new.ExceptHandler): + if not isinstance(parent, astroid.ExceptHandler): self._delayed_assattr.append(newnode) else: - newnode = new.Attribute() - _lineno_parent(node, newnode, parent) - newnode.expr = self.visit(node.value, newnode, None) - newnode.attrname = node.attr + newnode = nodes.Attribute(node.attr, node.lineno, node.col_offset, + parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_global(self, node, parent, assign_ctx=None): - """visit an Global node to become astroid""" - newnode = new.Global(node.names) - _set_infos(node, newnode, parent) + def visit_global(self, node, parent): + """visit a Global node to become astroid""" + newnode = nodes.Global(node.names, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) if self._global_names: # global at the module level, no effect for name in node.names: self._global_names[-1].setdefault(name, []).append(newnode) return newnode - def visit_if(self, node, parent, assign_ctx=None): - """visit a If node by returning a fresh instance of it""" - newnode = new.If() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] + def visit_if(self, node, parent): + """visit an If node by returning a fresh instance of it""" + newnode = nodes.If(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.test, newnode), + [self.visit(child, newnode) + for child in node.body], + [self.visit(child, newnode) + for child in node.orelse]) return newnode - def visit_ifexp(self, node, parent, assign_ctx=None): + def visit_ifexp(self, node, parent): """visit a IfExp node by returning a fresh instance of it""" - newnode = new.IfExp() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = self.visit(node.body, newnode, assign_ctx) - newnode.orelse = self.visit(node.orelse, newnode, assign_ctx) + newnode = nodes.IfExp(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.test, newnode), + self.visit(node.body, newnode), + self.visit(node.orelse, newnode)) return newnode - def visit_import(self, node, parent, assign_ctx=None): + def visit_import(self, node, parent): """visit a Import node by returning a fresh instance of it""" - newnode = new.Import() - _set_infos(node, newnode, parent) - newnode.names = [(alias.name, alias.asname) for alias in node.names] + names = [(alias.name, alias.asname) for alias in node.names] + newnode = nodes.Import(names, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) # save import names in parent's locals: for (name, asname) in newnode.names: name = asname or name - newnode.parent.set_local(name.split('.')[0], newnode) + parent.set_local(name.split('.')[0], newnode) return newnode - def visit_index(self, node, parent, assign_ctx=None): + def visit_index(self, node, parent): """visit a Index node by returning a fresh instance of it""" - newnode = new.Index() - newnode.parent = parent - newnode.value = self.visit(node.value, newnode, assign_ctx) + newnode = nodes.Index(parent=parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_keyword(self, node, parent, assign_ctx=None): + def visit_keyword(self, node, parent): """visit a Keyword node by returning a fresh instance of it""" - newnode = new.Keyword() - newnode.parent = parent - newnode.arg = node.arg - newnode.value = self.visit(node.value, newnode, assign_ctx) + newnode = nodes.Keyword(node.arg, parent=parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_lambda(self, node, parent, assign_ctx=None): + def visit_lambda(self, node, parent): """visit a Lambda node by returning a fresh instance of it""" - newnode = new.Lambda() - _lineno_parent(node, newnode, parent) - newnode.args = self.visit(node.args, newnode, assign_ctx) - newnode.body = self.visit(node.body, newnode, assign_ctx) + newnode = nodes.Lambda(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.args, newnode), + self.visit(node.body, newnode)) return newnode - def visit_list(self, node, parent, assign_ctx=None): + def visit_list(self, node, parent): """visit a List node by returning a fresh instance of it""" - newnode = new.List() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] + context = _get_context(node) + newnode = nodes.List(ctx=context, + lineno=node.lineno, + col_offset=node.col_offset, + parent=parent) + newnode.postinit([self.visit(child, newnode) + for child in node.elts]) return newnode - def visit_listcomp(self, node, parent, assign_ctx=None): + def visit_listcomp(self, node, parent): """visit a ListComp node by returning a fresh instance of it""" - newnode = new.ListComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] + newnode = nodes.ListComp(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.elt, newnode), + [self.visit(child, newnode) + for child in node.generators]) return newnode - def visit_name(self, node, parent, assign_ctx=None): + def visit_name(self, node, parent): """visit a Name node by returning a fresh instance of it""" + context = _get_context(node) # True and False can be assigned to something in py2x, so we have to - # check first the asscontext - # pylint: disable=redefined-variable-type - if assign_ctx == "Del": - newnode = new.DelName() - elif assign_ctx is not None: # Ass - newnode = new.AssName() + # check first the context. + if context == astroid.Del: + newnode = nodes.DelName(node.id, node.lineno, node.col_offset, + parent) + elif context == astroid.Store: + newnode = nodes.AssignName(node.id, node.lineno, node.col_offset, + parent) elif node.id in CONST_NAME_TRANSFORMS: - newnode = new.Const(CONST_NAME_TRANSFORMS[node.id]) - _set_infos(node, newnode, parent) + newnode = nodes.Const(CONST_NAME_TRANSFORMS[node.id], + getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) return newnode else: - newnode = new.Name() - _lineno_parent(node, newnode, parent) - newnode.name = node.id + newnode = nodes.Name(node.id, node.lineno, node.col_offset, parent) # XXX REMOVE me : - if assign_ctx in ('Del', 'Assign'): # 'Aug' ?? + if context in (astroid.Del, astroid.Store): # 'Aug' ?? self._save_assignment(newnode) return newnode - def visit_bytes(self, node, parent, assign_ctx=None): - """visit a Bytes node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode + def visit_str(self, node, parent): + """visit a String/Bytes node by returning a fresh instance of Const""" + return nodes.Const(node.s, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) + visit_bytes = visit_str - def visit_num(self, node, parent, assign_ctx=None): + def visit_num(self, node, parent): """visit a Num node by returning a fresh instance of Const""" - newnode = new.Const(node.n) - _set_infos(node, newnode, parent) - return newnode + return nodes.Const(node.n, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) - def visit_pass(self, node, parent, assign_ctx=None): + def visit_pass(self, node, parent): """visit a Pass node by returning a fresh instance of it""" - newnode = new.Pass() - _set_infos(node, newnode, parent) - return newnode - - def visit_str(self, node, parent, assign_ctx=None): - """visit a Str node by returning a fresh instance of Const""" - newnode = new.Const(node.s) - _set_infos(node, newnode, parent) - return newnode + return nodes.Pass(node.lineno, node.col_offset, parent) - def visit_print(self, node, parent, assign_ctx=None): + def visit_print(self, node, parent): """visit a Print node by returning a fresh instance of it""" - newnode = new.Print() - _lineno_parent(node, newnode, parent) - newnode.nl = node.nl - if node.dest is not None: - newnode.dest = self.visit(node.dest, newnode, assign_ctx) - newnode.values = [self.visit(child, newnode, assign_ctx) - for child in node.values] + newnode = nodes.Print(node.nl, node.lineno, node.col_offset, parent) + newnode.postinit(_visit_or_none(node, 'dest', self, newnode), + [self.visit(child, newnode) + for child in node.values]) return newnode - def visit_raise(self, node, parent, assign_ctx=None): + def visit_raise(self, node, parent): """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.exc = self.visit(node.type, newnode, assign_ctx) - if node.inst is not None: - newnode.inst = self.visit(node.inst, newnode, assign_ctx) - if node.tback is not None: - newnode.tback = self.visit(node.tback, newnode, assign_ctx) + newnode = nodes.Raise(node.lineno, node.col_offset, parent) + newnode.postinit(_visit_or_none(node, 'type', self, newnode), + _visit_or_none(node, 'inst', self, newnode), + _visit_or_none(node, 'tback', self, newnode)) return newnode - def visit_return(self, node, parent, assign_ctx=None): + def visit_return(self, node, parent): """visit a Return node by returning a fresh instance of it""" - newnode = new.Return() - _lineno_parent(node, newnode, parent) + newnode = nodes.Return(node.lineno, node.col_offset, parent) if node.value is not None: - newnode.value = self.visit(node.value, newnode, assign_ctx) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_set(self, node, parent, assign_ctx=None): + def visit_set(self, node, parent): """visit a Set node by returning a fresh instance of it""" - newnode = new.Set() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] + newnode = nodes.Set(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.elts]) return newnode - def visit_setcomp(self, node, parent, assign_ctx=None): + def visit_setcomp(self, node, parent): """visit a SetComp node by returning a fresh instance of it""" - newnode = new.SetComp() - _lineno_parent(node, newnode, parent) - newnode.elt = self.visit(node.elt, newnode, assign_ctx) - newnode.generators = [self.visit(child, newnode, assign_ctx) - for child in node.generators] + newnode = nodes.SetComp(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.elt, newnode), + [self.visit(child, newnode) + for child in node.generators]) return newnode - def visit_slice(self, node, parent, assign_ctx=None): + def visit_slice(self, node, parent): """visit a Slice node by returning a fresh instance of it""" - newnode = new.Slice() - newnode.parent = parent - if node.lower is not None: - newnode.lower = self.visit(node.lower, newnode, assign_ctx) - if node.upper is not None: - newnode.upper = self.visit(node.upper, newnode, assign_ctx) - if node.step is not None: - newnode.step = self.visit(node.step, newnode, assign_ctx) + newnode = nodes.Slice(parent=parent) + newnode.postinit(_visit_or_none(node, 'lower', self, newnode), + _visit_or_none(node, 'upper', self, newnode), + _visit_or_none(node, 'step', self, newnode)) return newnode - def visit_subscript(self, node, parent, assign_ctx=None): + def visit_subscript(self, node, parent): """visit a Subscript node by returning a fresh instance of it""" - newnode = new.Subscript() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, None) - newnode.slice = self.visit(node.slice, newnode, None) + context = _get_context(node) + newnode = nodes.Subscript(ctx=context, + lineno=node.lineno, + col_offset=node.col_offset, + parent=parent) + newnode.postinit(self.visit(node.value, newnode), + self.visit(node.slice, newnode)) return newnode - def visit_tryexcept(self, node, parent, assign_ctx=None): + def visit_tryexcept(self, node, parent): """visit a TryExcept node by returning a fresh instance of it""" - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.handlers = [self.visit(child, newnode, assign_ctx) - for child in node.handlers] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] + newnode = nodes.TryExcept(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.body], + [self.visit(child, newnode) + for child in node.handlers], + [self.visit(child, newnode) + for child in node.orelse]) return newnode - def visit_tryfinally(self, node, parent, assign_ctx=None): + def visit_tryfinally(self, node, parent): """visit a TryFinally node by returning a fresh instance of it""" - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.finalbody = [self.visit(n, newnode, assign_ctx) - for n in node.finalbody] + newnode = nodes.TryFinally(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.body], + [self.visit(n, newnode) + for n in node.finalbody]) return newnode - def visit_tuple(self, node, parent, assign_ctx=None): + def visit_tuple(self, node, parent): """visit a Tuple node by returning a fresh instance of it""" - newnode = new.Tuple() - _lineno_parent(node, newnode, parent) - newnode.elts = [self.visit(child, newnode, assign_ctx) - for child in node.elts] + context = _get_context(node) + newnode = nodes.Tuple(ctx=context, + lineno=node.lineno, + col_offset=node.col_offset, + parent=parent) + newnode.postinit([self.visit(child, newnode) + for child in node.elts]) return newnode - def visit_unaryop(self, node, parent, assign_ctx=None): + def visit_unaryop(self, node, parent): """visit a UnaryOp node by returning a fresh instance of it""" - newnode = new.UnaryOp() - _lineno_parent(node, newnode, parent) - newnode.operand = self.visit(node.operand, newnode, assign_ctx) - newnode.op = _UNARY_OP_CLASSES[node.op.__class__] + newnode = nodes.UnaryOp(_UNARY_OP_CLASSES[node.op.__class__], + node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.operand, newnode)) return newnode - def visit_while(self, node, parent, assign_ctx=None): + def visit_while(self, node, parent): """visit a While node by returning a fresh instance of it""" - newnode = new.While() - _lineno_parent(node, newnode, parent) - newnode.test = self.visit(node.test, newnode, assign_ctx) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] + newnode = nodes.While(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.test, newnode), + [self.visit(child, newnode) + for child in node.body], + [self.visit(child, newnode) + for child in node.orelse]) return newnode - def visit_with(self, node, parent, assign_ctx=None): - newnode = new.With() - _lineno_parent(node, newnode, parent) - expr = self.visit(node.context_expr, newnode, assign_ctx) + def visit_with(self, node, parent): + newnode = nodes.With(node.lineno, node.col_offset, parent) + expr = self.visit(node.context_expr, newnode) if node.optional_vars is not None: - vars = self.visit(node.optional_vars, newnode, 'Assign') + optional_vars = self.visit(node.optional_vars, newnode) else: - vars = None - self.asscontext = None - newnode.items = [(expr, vars)] - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] + optional_vars = None + newnode.postinit([(expr, optional_vars)], + [self.visit(child, newnode) + for child in node.body]) return newnode - def visit_yield(self, node, parent, assign_ctx=None): + def visit_yield(self, node, parent): """visit a Yield node by returning a fresh instance of it""" - return _create_yield_node(node, parent, self, new.Yield) + newnode = nodes.Yield(node.lineno, node.col_offset, parent) + if node.value is not None: + newnode.postinit(self.visit(node.value, newnode)) + return newnode -class TreeRebuilder3k(TreeRebuilder): + +class TreeRebuilder3(TreeRebuilder): """extend and overwrite TreeRebuilder for python3k""" - def visit_arg(self, node, parent, assign_ctx=None): + def visit_arg(self, node, parent): """visit a arg node by returning a fresh AssName instance""" # TODO(cpopa): introduce an Arg node instead of using AssignName. - return self.visit_assignname(node, parent, assign_ctx, node.arg) + return self.visit_assignname(node, parent, node.arg) - def visit_nameconstant(self, node, parent, assign_ctx=None): + def visit_nameconstant(self, node, parent): # in Python 3.4 we have NameConstant for True / False / None - newnode = new.Const(node.value) - _set_infos(node, newnode, parent) - return newnode + return nodes.Const(node.value, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) - def visit_arguments(self, node, parent, assign_ctx=None): - newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent, assign_ctx) - newnode.kwonlyargs = [self.visit(child, newnode, 'Assign') - for child in node.kwonlyargs] - newnode.kw_defaults = [self.visit(child, newnode, None) - if child else None for child in node.kw_defaults] - newnode.annotations = [ - self.visit(arg.annotation, newnode, None) if arg.annotation else None - for arg in node.args] - return newnode - - def visit_excepthandler(self, node, parent, assign_ctx=None): + def visit_excepthandler(self, node, parent): """visit an ExceptHandler node by returning a fresh instance of it""" - newnode = new.ExceptHandler() - _lineno_parent(node, newnode, parent) - if node.type is not None: - newnode.type = self.visit(node.type, newnode, assign_ctx) - if node.name is not None: - newnode.name = self.visit_assignname(node, newnode, 'Assign', node.name) - newnode.body = [self.visit(child, newnode, None) - for child in node.body] + newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent) + if node.name: + name = self.visit_assignname(node, newnode, node.name) + else: + name = None + newnode.postinit(_visit_or_none(node, 'type', self, newnode), + name, + [self.visit(child, newnode) + for child in node.body]) return newnode - def visit_nonlocal(self, node, parent, assign_ctx=None): + def visit_nonlocal(self, node, parent): """visit a Nonlocal node and return a new instance of it""" - newnode = new.Nonlocal(node.names) - _set_infos(node, newnode, parent) - return newnode + return nodes.Nonlocal(node.names, getattr(node, 'lineno', None), + getattr(node, 'col_offset', None), parent) - def visit_raise(self, node, parent, assign_ctx=None): + + def visit_raise(self, node, parent): """visit a Raise node by returning a fresh instance of it""" - newnode = new.Raise() - _lineno_parent(node, newnode, parent) + newnode = nodes.Raise(node.lineno, node.col_offset, parent) # no traceback; anyway it is not used in Pylint - if node.exc is not None: - newnode.exc = self.visit(node.exc, newnode, assign_ctx) - if node.cause is not None: - newnode.cause = self.visit(node.cause, newnode, assign_ctx) + newnode.postinit(_visit_or_none(node, 'exc', self, newnode), + _visit_or_none(node, 'cause', self, newnode)) return newnode - def visit_starred(self, node, parent, assign_ctx=None): + def visit_starred(self, node, parent): """visit a Starred node and return a new instance of it""" - newnode = new.Starred() - _lineno_parent(node, newnode, parent) - newnode.value = self.visit(node.value, newnode, assign_ctx) + context = _get_context(node) + newnode = nodes.Starred(ctx=context, lineno=node.lineno, + col_offset=node.col_offset, + parent=parent) + newnode.postinit(self.visit(node.value, newnode)) return newnode - def visit_try(self, node, parent, assign_ctx=None): - # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes - # pylint: disable=redefined-variable-type + def visit_try(self, node, parent): + # python 3.3 introduce a new Try node replacing + # TryFinally/TryExcept nodes if node.finalbody: - newnode = new.TryFinally() - _lineno_parent(node, newnode, parent) - newnode.finalbody = [self.visit(n, newnode, assign_ctx) - for n in node.finalbody] + newnode = nodes.TryFinally(node.lineno, node.col_offset, parent) if node.handlers: - excnode = new.TryExcept() - _lineno_parent(node, excnode, newnode) - excnode.body = [self.visit(child, excnode, assign_ctx) - for child in node.body] - excnode.handlers = [self.visit(child, excnode, assign_ctx) - for child in node.handlers] - excnode.orelse = [self.visit(child, excnode, assign_ctx) - for child in node.orelse] - newnode.body = [excnode] + body = [self.visit_tryexcept(node, newnode)] else: - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] + body = [self.visit(child, newnode) + for child in node.body] + newnode.postinit(body, + [self.visit(n, newnode) + for n in node.finalbody]) + return newnode elif node.handlers: - newnode = new.TryExcept() - _lineno_parent(node, newnode, parent) - newnode.body = [self.visit(child, newnode, assign_ctx) - for child in node.body] - newnode.handlers = [self.visit(child, newnode, assign_ctx) - for child in node.handlers] - newnode.orelse = [self.visit(child, newnode, assign_ctx) - for child in node.orelse] + return self.visit_tryexcept(node, parent) + + def visit_annassign(self, node, parent): + """visit an AnnAssign node by returning a fresh instance of it""" + newnode = nodes.AnnAssign(node.lineno, node.col_offset, parent) + annotation = _visit_or_none(node, 'annotation', self, newnode) + newnode.postinit(target=self.visit(node.target, newnode), + annotation=annotation, + simple=node.simple, + value=_visit_or_none(node, 'value', self, newnode)) return newnode - def _visit_with(self, cls, node, parent, assign_ctx=None): + def _visit_with(self, cls, node, parent): if 'items' not in node._fields: # python < 3.3 - return super(TreeRebuilder3k, self).visit_with(node, parent, - assign_ctx) + return super(TreeRebuilder3, self).visit_with(node, parent) - newnode = cls() - _lineno_parent(node, newnode, parent) + newnode = cls(node.lineno, node.col_offset, parent) def visit_child(child): expr = self.visit(child.context_expr, newnode) - if child.optional_vars: - var = self.visit(child.optional_vars, newnode, - 'Assign') - else: - var = None + var = _visit_or_none(child, 'optional_vars', self, newnode) return expr, var - newnode.items = [visit_child(child) - for child in node.items] - newnode.body = [self.visit(child, newnode, None) - for child in node.body] + newnode.postinit([visit_child(child) for child in node.items], + [self.visit(child, newnode) + for child in node.body]) return newnode - def visit_with(self, node, parent, assign_ctx=None): - return self._visit_with(new.With, node, parent, assign_ctx=assign_ctx) - - def visit_yieldfrom(self, node, parent, assign_ctx=None): - return _create_yield_node(node, parent, self, new.YieldFrom) + def visit_with(self, node, parent): + return self._visit_with(nodes.With, node, parent) - def visit_classdef(self, node, parent, assign_ctx=None): - newnode = super(TreeRebuilder3k, self).visit_classdef(node, parent, assign_ctx) - newnode._newstyle = True - for keyword in node.keywords: - if keyword.arg == 'metaclass': - newnode._metaclass = self.visit(keyword, newnode, assign_ctx).value - break + def visit_yieldfrom(self, node, parent): + newnode = nodes.YieldFrom(node.lineno, node.col_offset, parent) + if node.value is not None: + newnode.postinit(self.visit(node.value, newnode)) return newnode - # Async structs added in Python 3.5 - def visit_asyncfunctiondef(self, node, parent, assign_ctx=None): - return self._visit_functiondef(new.AsyncFunctionDef, node, parent, - assign_ctx=assign_ctx) + def visit_classdef(self, node, parent, newstyle=True): + return super(TreeRebuilder3, self).visit_classdef(node, parent, + newstyle=newstyle) + # Async structs added in Python 3.5 + def visit_asyncfunctiondef(self, node, parent): + return self._visit_functiondef(nodes.AsyncFunctionDef, node, parent) - def visit_asyncfor(self, node, parent, assign_ctx=None): - return self._visit_for(new.AsyncFor, node, parent, - assign_ctx=assign_ctx) + def visit_asyncfor(self, node, parent): + return self._visit_for(nodes.AsyncFor, node, parent) - def visit_await(self, node, parent, assign_ctx=None): - newnode = new.Await() - newnode.lineno = node.lineno - newnode.col_offset = node.col_offset - newnode.parent = parent - newnode.value = self.visit(node.value, newnode, None) + def visit_await(self, node, parent): + newnode = nodes.Await(node.lineno, node.col_offset, parent) + newnode.postinit(value=self.visit(node.value, newnode)) return newnode - def visit_asyncwith(self, node, parent, assign_ctx=None): - return self._visit_with(new.AsyncWith, node, parent, - assign_ctx=assign_ctx) + def visit_asyncwith(self, node, parent): + return self._visit_with(nodes.AsyncWith, node, parent) + + def visit_joinedstr(self, node, parent): + newnode = nodes.JoinedStr(node.lineno, node.col_offset, parent) + newnode.postinit([self.visit(child, newnode) + for child in node.values]) + return newnode + def visit_formattedvalue(self, node, parent): + newnode = nodes.FormattedValue(node.lineno, node.col_offset, parent) + newnode.postinit(self.visit(node.value, newnode), + node.conversion, + _visit_or_none(node, 'format_spec', self, newnode)) + return newnode if sys.version_info >= (3, 0): - TreeRebuilder = TreeRebuilder3k + TreeRebuilder = TreeRebuilder3 diff --git a/pymode/libs/astroid/scoped_nodes.py b/pymode/libs/astroid/scoped_nodes.py index d78d1510..052ec688 100644 --- a/pymode/libs/astroid/scoped_nodes.py +++ b/pymode/libs/astroid/scoped_nodes.py @@ -1,20 +1,12 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2011, 2013-2015 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015 Rene Zhang + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """ This module contains the classes for "scoped" node, i.e. which are opening a @@ -22,20 +14,22 @@ Lambda, GeneratorExp, DictComp and SetComp to some extent). """ +import sys import io import itertools import warnings import six -import wrapt from astroid import bases from astroid import context as contextmod from astroid import exceptions +from astroid import decorators as decorators_mod +from astroid.interpreter import objectmodel +from astroid.interpreter import dunder_lookup from astroid import manager from astroid import mixins from astroid import node_classes -from astroid import decorators as decorators_mod from astroid import util @@ -43,7 +37,7 @@ ITER_METHODS = ('__iter__', '__getitem__') -def _c3_merge(sequences): +def _c3_merge(sequences, cls, context): """Merges MROs in *sequences* to a single MRO using the C3 algorithm. Adapted from http://www.python.org/download/releases/2.3/mro/. @@ -65,12 +59,10 @@ def _c3_merge(sequences): if not candidate: # Show all the remaining bases, which were considered as # candidates for the next mro sequence. - bases = ["({})".format(", ".join(base.name - for base in subsequence)) - for subsequence in sequences] raise exceptions.InconsistentMroError( - "Cannot create a consistent method resolution " - "order for bases %s" % ", ".join(bases)) + message="Cannot create a consistent method resolution order " + "for MROs {mros} of class {cls!r}.", + mros=sequences, cls=cls, context=context) result.append(candidate) # remove the chosen candidate @@ -79,21 +71,13 @@ def _c3_merge(sequences): del seq[0] -def _verify_duplicates_mro(sequences): +def _verify_duplicates_mro(sequences, cls, context): for sequence in sequences: names = [node.qname() for node in sequence] if len(names) != len(set(names)): - raise exceptions.DuplicateBasesError('Duplicates found in the mro.') - - -def remove_nodes(cls): - @wrapt.decorator - def decorator(func, instance, args, kwargs): - nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)] - if not nodes: - raise exceptions.NotFoundError() - return nodes - return decorator + raise exceptions.DuplicateBasesError( + message='Duplicates found in MROs {mros} for {cls!r}.', + mros=sequences, cls=cls, context=context) def function_to_method(n, klass): @@ -105,20 +89,6 @@ def function_to_method(n, klass): return n -def std_special_attributes(self, name, add_locals=True): - if add_locals: - locals = self._locals - else: - locals = {} - if name == '__name__': - return [node_classes.const_factory(self.name)] + locals.get(name, []) - if name == '__doc__': - return [node_classes.const_factory(self.doc)] + locals.get(name, []) - if name == '__dict__': - return [node_classes.Dict()] + locals.get(name, []) - raise exceptions.NotFoundError(name) - - MANAGER = manager.AstroidManager() def builtin_lookup(name): """lookup a name into the builtin module @@ -129,14 +99,15 @@ def builtin_lookup(name): if name == '__dict__': return builtin_astroid, () try: - stmts = builtin_astroid._locals[name] + stmts = builtin_astroid.locals[name] except KeyError: stmts = () return builtin_astroid, stmts # TODO move this Mixin to mixins.py; problem: 'FunctionDef' in _scope_lookup -class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG): +class LocalsDictNodeNG(node_classes.LookupMixIn, + node_classes.NodeNG): """ this class provides locals handling common to Module, FunctionDef and ClassDef nodes, including a dict like interface for direct access to locals information @@ -146,23 +117,14 @@ class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG): # dictionary of locals with name as key and node defining the local as # value - @property - def locals(self): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - return self._locals - @locals.setter - def locals(self, _locals): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - self._locals = _locals - @locals.deleter - def locals(self): - util.attribute_to_function_warning('locals', 2.0, 'get_locals') - del self._locals + + locals = {} def qname(self): """return the 'qualified' name of the node, eg module.name, module.class.name ... """ + # pylint: disable=no-member; github.com/pycqa/astroid/issues/278 if self.parent is None: return self.name return '%s.%s' % (self.parent.frame().qname(), self.name) @@ -181,7 +143,7 @@ def scope(self): def _scope_lookup(self, node, name, offset=0): """XXX method for interfacing the scope lookup""" try: - stmts = node._filter_stmts(self._locals[name], self, offset) + stmts = node._filter_stmts(self.locals[name], self, offset) except KeyError: stmts = () if stmts: @@ -202,13 +164,17 @@ def set_local(self, name, stmt): if the name is already defined, ignore it """ - #assert not stmt in self._locals.get(name, ()), (self, stmt) - self._locals.setdefault(name, []).append(stmt) + #assert not stmt in self.locals.get(name, ()), (self, stmt) + self.locals.setdefault(name, []).append(stmt) __setitem__ = set_local def _append_node(self, child): """append a child, linking it in the tree""" + # pylint: disable=no-member; depending by the class + # which uses the current class as a mixin or base class. + # It's rewritten in 2.0, so it makes no sense for now + # to spend development time on it. self.body.append(child) child.parent = self @@ -227,7 +193,7 @@ def __getitem__(self, item): :param item: the name of the locally defined object :raises KeyError: if the name is not defined """ - return self._locals[item][0] + return self.locals[item][0] def __iter__(self): """method from the `dict` interface returning an iterator on @@ -239,7 +205,7 @@ def keys(self): """method from the `dict` interface returning a tuple containing locally defined names """ - return list(self._locals.keys()) + return list(self.locals.keys()) def values(self): """method from the `dict` interface returning a tuple containing @@ -255,7 +221,7 @@ def items(self): return list(zip(self.keys(), self.values())) def __contains__(self, name): - return name in self._locals + return name in self.locals class Module(LocalsDictNodeNG): @@ -268,9 +234,9 @@ class Module(LocalsDictNodeNG): # the file from which as been extracted the astroid representation. It may # be None if the representation has been built from a built-in module - source_file = None + file = None # Alternatively, if built from a string/bytes, this can be set - source_code = None + file_bytes = None # encoding of python source file, so we can get unicode out of it (python2 # only) file_encoding = None @@ -282,96 +248,43 @@ class Module(LocalsDictNodeNG): package = None # dictionary of globals with name as key and node defining the global # as value - _globals = None + globals = None # Future imports - _future_imports = None + future_imports = None + special_attributes = objectmodel.ModuleModel() # names of python special attributes (handled by getattr impl.) - special_attributes = set(('__name__', '__doc__', '__file__', '__path__', - '__dict__')) + # names of module attributes available through the global scope scope_attrs = set(('__name__', '__doc__', '__file__', '__path__')) - def __init__(self, name, doc, pure_python=True): + _other_fields = ('name', 'doc', 'file', 'path', 'package', + 'pure_python', 'future_imports') + _other_other_fields = ('locals', 'globals') + + def __init__(self, name, doc, file=None, path=None, package=None, + parent=None, pure_python=True): self.name = name self.doc = doc + self.file = file + self.path = path + self.package = package + self.parent = parent self.pure_python = pure_python - self._locals = self._globals = {} + self.locals = self.globals = {} self.body = [] - self._future_imports = set() - - # Future deprecation warnings - @property - def file(self): - util.rename_warning('file', 2.0, 'source_file') - return self.source_file - @file.setter - def file(self, source_file): - util.rename_warning('file', 2.0, 'source_file') - self.source_file = source_file - @file.deleter - def file(self): - util.rename_warning('file', 2.0, 'source_file') - del self.source_file + self.future_imports = set() + # pylint: enable=redefined-builtin - @property - def path(self): - util.rename_warning('path', 2.0, 'source_file') - return self.source_file - @path.setter - def path(self, source_file): - util.rename_warning('path', 2.0, 'source_file') - self.source_file = source_file - @path.deleter - def path(self): - util.rename_warning('path', 2.0, 'source_file') - del self.source_file - - @property - def file_bytes(self): - util.rename_warning('file_bytes', 2.0, 'source_code') - return self.source_code - @file_bytes.setter - def file_bytes(self, source_code): - util.rename_warning('file_bytes', 2.0, 'source_code') - self.source_code = source_code - @file_bytes.deleter - def file_bytes(self): - util.rename_warning('file_bytes', 2.0, 'source_code') - del self.source_code - - @property - def globals(self): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - return self._locals - @globals.setter - def globals(self, _globals): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - self._locals = _globals - @globals.deleter - def globals(self): - util.attribute_to_function_warning('globals', 2.0, 'get_locals') - del self._locals - - @property - def future_imports(self): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - return self._future_imports - @future_imports.setter - def future_imports(self, _future_imports): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - self._future_imports = _future_imports - @future_imports.deleter - def future_imports(self): - util.attribute_to_function_warning('future_imports', 2.0, 'future_imports') - del self._future_imports + def postinit(self, body=None): + self.body = body def _get_stream(self): - if self.source_code is not None: - return io.BytesIO(self.source_code) - if self.source_file is not None: - stream = open(self.source_file, 'rb') + if self.file_bytes is not None: + return io.BytesIO(self.file_bytes) + if self.file is not None: + stream = open(self.file, 'rb') return stream return None @@ -406,10 +319,10 @@ def block_range(self, lineno): return self.fromlineno, self.tolineno def scope_lookup(self, node, name, offset=0): - if name in self.scope_attrs and name not in self._locals: + if name in self.scope_attrs and name not in self.locals: try: return self, self.getattr(name) - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: return self, () return self._scope_lookup(node, name, offset) @@ -419,24 +332,26 @@ def pytype(self): def display_type(self): return 'Module' - @remove_nodes(node_classes.DelName) def getattr(self, name, context=None, ignore_locals=False): - if name in self.special_attributes: - if name == '__file__': - return [node_classes.const_factory(self.source_file)] + self._locals.get(name, []) - if name == '__path__' and self.package: - return [node_classes.List()] + self._locals.get(name, []) - return std_special_attributes(self, name) - if not ignore_locals and name in self._locals: - return self._locals[name] - if self.package: + result = [] + name_in_locals = name in self.locals + + if name in self.special_attributes and not ignore_locals and not name_in_locals: + result = [self.special_attributes.lookup(name)] + elif not ignore_locals and name_in_locals: + result = self.locals[name] + elif self.package: try: - return [self.import_module(name, relative_only=True)] - except exceptions.AstroidBuildingException: - raise exceptions.NotFoundError(name) - except SyntaxError: - raise exceptions.NotFoundError(name) - raise exceptions.NotFoundError(name) + result = [self.import_module(name, relative_only=True)] + except (exceptions.AstroidBuildingError, SyntaxError): + util.reraise(exceptions.AttributeInferenceError(target=self, + attribute=name, + context=context)) + result = [n for n in result if not isinstance(n, node_classes.DelName)] + if result: + return result + raise exceptions.AttributeInferenceError(target=self, attribute=name, + context=context) def igetattr(self, name, context=None): """inferred getattr""" @@ -447,14 +362,15 @@ def igetattr(self, name, context=None): try: return bases._infer_stmts(self.getattr(name, context), context, frame=self) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) + except exceptions.AttributeInferenceError as error: + util.reraise(exceptions.InferenceError( + error.message, target=self, attribute=name, context=context)) def fully_defined(self): """return True if this module has been built from a .py file and so contains a complete representation including the code """ - return self.source_file is not None and self.source_file.endswith('.py') + return self.file is not None and self.file.endswith('.py') def statement(self): """return the first parent node marked as statement node @@ -473,7 +389,7 @@ def next_sibling(self): if six.PY2: @decorators_mod.cachedproperty def _absolute_import_activated(self): - for stmt in self._locals.get('absolute_import', ()): + for stmt in self.locals.get('absolute_import', ()): if isinstance(stmt, node_classes.ImportFrom) and stmt.modname == '__future__': return True return False @@ -488,9 +404,10 @@ def import_module(self, modname, relative_only=False, level=None): if relative_only and level is None: level = 0 absmodname = self.relative_to_absolute_name(modname, level) + try: return MANAGER.ast_from_module_name(absmodname) - except exceptions.AstroidBuildingException: + except exceptions.AstroidBuildingError: # we only want to import a sub module or package of this module, # skip here if relative_only: @@ -510,11 +427,16 @@ def relative_to_absolute_name(self, modname, level): if level: if self.package: level = level - 1 + if level and self.name.count('.') < level: + raise exceptions.TooManyLevelsError( + level=level, name=self.name) + package_name = self.name.rsplit('.', level)[0] elif self.package: package_name = self.name else: package_name = self.name.rsplit('.', 1)[0] + if package_name: if not modname: return package_name @@ -532,12 +454,12 @@ def wildcard_import_names(self): # to avoid catching too many Exceptions default = [name for name in self.keys() if not name.startswith('_')] try: - all = self['__all__'] + all_values = self['__all__'] except KeyError: return default try: - explicit = next(all.assigned_stmts()) + explicit = next(all_values.assigned_stmts()) except exceptions.InferenceError: return default except AttributeError: @@ -568,7 +490,7 @@ def wildcard_import_names(self): inferred.append(inferred_node.value) return inferred - def _public_names(self): + def public_names(self): """Get the list of the names which are publicly available in this module.""" return [name for name in self.keys() if not name.startswith('_')] @@ -585,44 +507,91 @@ def frame(self): class GeneratorExp(ComprehensionScope): _astroid_fields = ('elt', 'generators') + _other_other_fields = ('locals',) + elt = None + generators = None + + def __init__(self, lineno=None, col_offset=None, parent=None): + self.locals = {} + super(GeneratorExp, self).__init__(lineno, col_offset, parent) - def __init__(self): - self._locals = {} - self.elt = None - self.generators = [] + def postinit(self, elt=None, generators=None): + self.elt = elt + if generators is None: + self.generators = [] + else: + self.generators = generators + + def bool_value(self): + return True class DictComp(ComprehensionScope): _astroid_fields = ('key', 'value', 'generators') + _other_other_fields = ('locals',) + key = None + value = None + generators = None + + def __init__(self, lineno=None, col_offset=None, parent=None): + self.locals = {} + super(DictComp, self).__init__(lineno, col_offset, parent) + + def postinit(self, key=None, value=None, generators=None): + self.key = key + self.value = value + if generators is None: + self.generators = [] + else: + self.generators = generators - def __init__(self): - self._locals = {} - self.key = None - self.value = None - self.generators = [] + def bool_value(self): + return util.Uninferable class SetComp(ComprehensionScope): _astroid_fields = ('elt', 'generators') + _other_other_fields = ('locals',) + elt = None + generators = None - def __init__(self): - self._locals = {} - self.elt = None - self.generators = [] + def __init__(self, lineno=None, col_offset=None, parent=None): + self.locals = {} + super(SetComp, self).__init__(lineno, col_offset, parent) + def postinit(self, elt=None, generators=None): + self.elt = elt + if generators is None: + self.generators = [] + else: + self.generators = generators + + def bool_value(self): + return util.Uninferable -class _ListComp(bases.NodeNG): + +class _ListComp(node_classes.NodeNG): """class representing a ListComp node""" _astroid_fields = ('elt', 'generators') elt = None generators = None + def postinit(self, elt=None, generators=None): + self.elt = elt + self.generators = generators + + def bool_value(self): + return util.Uninferable + if six.PY3: class ListComp(_ListComp, ComprehensionScope): """class representing a ListComp node""" - def __init__(self): - self._locals = {} + _other_other_fields = ('locals',) + + def __init__(self, lineno=None, col_offset=None, parent=None): + self.locals = {} + super(ListComp, self).__init__(lineno, col_offset, parent) else: class ListComp(_ListComp): """class representing a ListComp node""" @@ -654,15 +623,27 @@ def _infer_decorator_callchain(node): class Lambda(mixins.FilterStmtsMixin, LocalsDictNodeNG): _astroid_fields = ('args', 'body',) + _other_other_fields = ('locals',) name = '' # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' - type = 'function' - - def __init__(self): - self._locals = {} + @property + def type(self): + # pylint: disable=no-member + if self.args.args and self.args.args[0].name == 'self': + if isinstance(self.parent.scope(), ClassDef): + return 'method' + return 'function' + + def __init__(self, lineno=None, col_offset=None, parent=None): + self.locals = {} self.args = [] self.body = [] + super(Lambda, self).__init__(lineno, col_offset, parent) + + def postinit(self, args, body): + self.args = args + self.body = body def pytype(self): if 'method' in self.type: @@ -679,6 +660,10 @@ def callable(self): def argnames(self): """return a list of argument names""" + # pylint: disable=no-member; github.com/pycqa/astroid/issues/291 + # args is in fact redefined later on by postinit. Can't be changed + # to None due to a strong interaction between Lambda and FunctionDef. + if self.args.args: # maybe None with builtin functions names = _rec_get_names(self.args.args) else: @@ -691,9 +676,17 @@ def argnames(self): def infer_call_result(self, caller, context=None): """infer what a function is returning when called""" + # pylint: disable=no-member; github.com/pycqa/astroid/issues/291 + # args is in fact redefined later on by postinit. Can't be changed + # to None due to a strong interaction between Lambda and FunctionDef. + return self.body.infer(context) def scope_lookup(self, node, name, offset=0): + # pylint: disable=no-member; github.com/pycqa/astroid/issues/291 + # args is in fact redefined later on by postinit. Can't be changed + # to None due to a strong interaction between Lambda and FunctionDef. + if node in self.args.defaults or node in self.args.kw_defaults: frame = self.parent.frame() # line offset to avoid that def func(f=func) resolve the default @@ -704,40 +697,40 @@ def scope_lookup(self, node, name, offset=0): frame = self return frame._scope_lookup(node, name, offset) + def bool_value(self): + return True -class FunctionDef(bases.Statement, Lambda): +class FunctionDef(node_classes.Statement, Lambda): if six.PY3: _astroid_fields = ('decorators', 'args', 'returns', 'body') returns = None else: _astroid_fields = ('decorators', 'args', 'body') - - special_attributes = set(('__name__', '__doc__', '__dict__')) + decorators = None + special_attributes = objectmodel.FunctionModel() is_function = True # attributes below are set by the builder module or by raw factories - decorators = None + _other_fields = ('name', 'doc') + _other_other_fields = ('locals', '_type') + _type = None - def __init__(self, name, doc): - self._locals = {} - self.args = [] - self.body = [] + def __init__(self, name=None, doc=None, lineno=None, + col_offset=None, parent=None): self.name = name self.doc = doc - self._instance_attrs = {} - - @property - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - return self._instance_attrs - @instance_attrs.setter - def instance_attrs(self, _instance_attrs): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - self._instance_attrs = _instance_attrs - @instance_attrs.deleter - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - del self._instance_attrs + self.instance_attrs = {} + super(FunctionDef, self).__init__(lineno, col_offset, parent) + if parent: + frame = parent.frame() + frame.set_local(name, self) + + # pylint: disable=arguments-differ; different than Lambdas + def postinit(self, args, body, decorators=None, returns=None): + self.args = args + self.body = body + self.decorators = decorators + self.returns = returns @decorators_mod.cachedproperty def extra_decorators(self): @@ -793,46 +786,50 @@ def type(self): if isinstance(frame, ClassDef): if self.name == '__new__': return 'classmethod' + elif sys.version_info >= (3, 6) and self.name == '__init_subclass__': + return 'classmethod' else: type_name = 'method' - if self.decorators: - for node in self.decorators.nodes: - if isinstance(node, node_classes.Name): - if node.name in builtin_descriptors: - return node.name - - if isinstance(node, node_classes.Call): - # Handle the following case: - # @some_decorator(arg1, arg2) - # def func(...) - # - try: - current = next(node.func.infer()) - except exceptions.InferenceError: - continue - _type = _infer_decorator_callchain(current) - if _type is not None: - return _type + if not self.decorators: + return type_name + + for node in self.decorators.nodes: + if isinstance(node, node_classes.Name): + if node.name in builtin_descriptors: + return node.name + if isinstance(node, node_classes.Call): + # Handle the following case: + # @some_decorator(arg1, arg2) + # def func(...) + # try: - for inferred in node.infer(): - # Check to see if this returns a static or a class method. - _type = _infer_decorator_callchain(inferred) - if _type is not None: - return _type + current = next(node.func.infer()) + except exceptions.InferenceError: + continue + _type = _infer_decorator_callchain(current) + if _type is not None: + return _type + + try: + for inferred in node.infer(): + # Check to see if this returns a static or a class method. + _type = _infer_decorator_callchain(inferred) + if _type is not None: + return _type - if not isinstance(inferred, ClassDef): + if not isinstance(inferred, ClassDef): + continue + for ancestor in inferred.ancestors(): + if not isinstance(ancestor, ClassDef): continue - for ancestor in inferred.ancestors(): - if not isinstance(ancestor, ClassDef): - continue - if ancestor.is_subtype_of('%s.classmethod' % BUILTINS): - return 'classmethod' - elif ancestor.is_subtype_of('%s.staticmethod' % BUILTINS): - return 'staticmethod' - except exceptions.InferenceError: - pass + if ancestor.is_subtype_of('%s.classmethod' % BUILTINS): + return 'classmethod' + elif ancestor.is_subtype_of('%s.staticmethod' % BUILTINS): + return 'staticmethod' + except exceptions.InferenceError: + pass return type_name @decorators_mod.cachedproperty @@ -861,19 +858,20 @@ def getattr(self, name, context=None): """this method doesn't look in the instance_attrs dictionary since it's done by an Instance proxy at inference time. """ - if name == '__module__': - return [node_classes.const_factory(self.root().qname())] - if name in self._instance_attrs: - return self._instance_attrs[name] - return std_special_attributes(self, name, False) + if name in self.instance_attrs: + return self.instance_attrs[name] + if name in self.special_attributes: + return [self.special_attributes.lookup(name)] + raise exceptions.AttributeInferenceError(target=self, attribute=name) def igetattr(self, name, context=None): """Inferred getattr, which returns an iterator of inferred statements.""" try: return bases._infer_stmts(self.getattr(name, context), context, frame=self) - except exceptions.NotFoundError: - raise exceptions.InferenceError(name) + except exceptions.AttributeInferenceError as error: + util.reraise(exceptions.InferenceError( + error.message, target=self, attribute=name, context=context)) def is_method(self): """return true if the function node should be considered as a method""" @@ -887,7 +885,6 @@ def decoratornames(self): result = set() decoratornodes = [] if self.decorators is not None: - # pylint: disable=unsupported-binary-operation; damn flow control. decoratornodes += self.decorators.nodes decoratornodes += self.extra_decorators for decnode in decoratornodes: @@ -938,8 +935,7 @@ def is_generator(self): def infer_call_result(self, caller, context=None): """infer what a function is returning when called""" if self.is_generator(): - result = bases.Generator() - result.parent = self + result = bases.Generator(self) yield result return # This is really a gigantic hack to work around metaclass generators @@ -957,7 +953,7 @@ def infer_call_result(self, caller, context=None): c.hide = True c.parent = self class_bases = [next(b.infer(context)) for b in caller.args[1:]] - c.bases = [base for base in class_bases if base != util.YES] + c.bases = [base for base in class_bases if base != util.Uninferable] c._metaclass = metaclass yield c return @@ -970,7 +966,10 @@ def infer_call_result(self, caller, context=None): for inferred in returnnode.value.infer(context): yield inferred except exceptions.InferenceError: - yield util.YES + yield util.Uninferable + + def bool_value(self): + return True class AsyncFunctionDef(FunctionDef): @@ -1008,7 +1007,7 @@ def _is_metaclass(klass, seen=None): if isinstance(baseobj, bases.Instance): # not abstract return False - if baseobj is util.YES: + if baseobj is util.Uninferable: continue if baseobj is klass: continue @@ -1057,7 +1056,25 @@ def _class_type(klass, ancestors=None): return klass._type -class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement): +def get_wrapping_class(node): + """Obtain the class that *wraps* this node + + We consider that a class wraps a node if the class + is a parent for the said node. + """ + + klass = node.frame() + while klass is not None and not isinstance(klass, ClassDef): + if klass.parent is None: + klass = None + else: + klass = klass.parent.frame() + return klass + + + +class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, + node_classes.Statement): # some of the attributes below are set by the builder module or # by a raw factories @@ -1066,8 +1083,7 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement): _astroid_fields = ('decorators', 'bases', 'body') # name decorators = None - special_attributes = set(('__name__', '__doc__', '__dict__', '__module__', - '__bases__', '__mro__', '__subclasses__')) + special_attributes = objectmodel.ClassModel() _type = None _metaclass_hack = False @@ -1075,27 +1091,33 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement): type = property(_class_type, doc="class'type, possible values are 'class' | " "'metaclass' | 'exception'") + _other_fields = ('name', 'doc') + _other_other_fields = ('locals', '_newstyle') + _newstyle = None - def __init__(self, name, doc): - self._instance_attrs = {} - self._locals = {} + def __init__(self, name=None, doc=None, lineno=None, + col_offset=None, parent=None): + self.instance_attrs = {} + self.locals = {} + self.keywords = [] self.bases = [] self.body = [] self.name = name self.doc = doc - - @property - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - return self._instance_attrs - @instance_attrs.setter - def instance_attrs(self, _instance_attrs): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - self._instance_attrs = _instance_attrs - @instance_attrs.deleter - def instance_attrs(self): - util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes') - del self._instance_attrs + super(ClassDef, self).__init__(lineno, col_offset, parent) + if parent is not None: + parent.frame().set_local(name, self) + + # pylint: disable=redefined-outer-name + def postinit(self, bases, body, decorators, newstyle=None, metaclass=None, keywords=None): + self.keywords = keywords + self.bases = bases + self.body = body + self.decorators = decorators + if newstyle is not None: + self._newstyle = newstyle + if metaclass is not None: + self._metaclass = metaclass def _newstyle_impl(self, context=None): if context is None: @@ -1106,7 +1128,7 @@ def _newstyle_impl(self, context=None): if base._newstyle_impl(context): self._newstyle = True break - klass = self._explicit_metaclass() + klass = self.declared_metaclass() # could be any callable, we'd need to infer the result of klass(name, # bases, dict). punt if it's not a class node. if klass is not None and isinstance(klass, ClassDef): @@ -1124,8 +1146,8 @@ def _newstyle_impl(self, context=None): def blockstart_tolineno(self): if self.bases: return self.bases[-1].tolineno - else: - return self.fromlineno + + return self.fromlineno def block_range(self, lineno): """return block line numbers. @@ -1158,7 +1180,7 @@ def _infer_type_call(self, caller, context): isinstance(name_node.value, six.string_types)): name = name_node.value else: - return util.YES + return util.Uninferable result = ClassDef(name, None) @@ -1168,9 +1190,9 @@ def _infer_type_call(self, caller, context): result.bases = class_bases.itered() else: # There is currently no AST node that can represent an 'unknown' - # node (YES is not an AST node), therefore we simply return YES here + # node (Uninferable is not an AST node), therefore we simply return Uninferable here # although we know at least the name of the class. - return util.YES + return util.Uninferable # Get the members of the class try: @@ -1182,7 +1204,7 @@ def _infer_type_call(self, caller, context): for attr, value in members.items: if (isinstance(attr, node_classes.Const) and isinstance(attr.value, six.string_types)): - result._locals[attr.value] = [value] + result.locals[attr.value] = [value] result.parent = caller.parent return result @@ -1197,9 +1219,16 @@ def infer_call_result(self, caller, context=None): yield bases.Instance(self) def scope_lookup(self, node, name, offset=0): - # pylint: disable=redefined-variable-type + # If the name looks like a builtin name, just try to look + # into the upper scope of this class. We might have a + # decorator that it's poorly named after a builtin object + # inside this class. + lookup_upper_frame = ( + isinstance(node.parent, node_classes.Decorators) and + name in MANAGER.astroid_cache[six.moves.builtins.__name__] + ) if any(node == base or base.parent_of(node) - for base in self.bases): + for base in self.bases) or lookup_upper_frame: # Handle the case where we have either a name # in the bases of a class, which exists before # the actual definition or the case where we have @@ -1295,87 +1324,144 @@ def instance_attr_ancestors(self, name, context=None): which have defined in their instance attribute dictionary """ for astroid in self.ancestors(context=context): - if name in astroid._instance_attrs: + if name in astroid.instance_attrs: yield astroid def has_base(self, node): return node in self.bases - @remove_nodes(node_classes.DelAttr) def local_attr(self, name, context=None): """return the list of assign node associated to name in this class locals or in its parents - :raises `NotFoundError`: + :raises `AttributeInferenceError`: if no attribute with this name has been find in this class or its parent classes """ - try: - return self._locals[name] - except KeyError: - for class_node in self.local_attr_ancestors(name, context): - return class_node._locals[name] - raise exceptions.NotFoundError(name) + result = [] + if name in self.locals: + result = self.locals[name] + else: + class_node = next(self.local_attr_ancestors(name, context), ()) + if class_node: + result = class_node.locals[name] + result = [n for n in result if not isinstance(n, node_classes.DelAttr)] + if result: + return result + raise exceptions.AttributeInferenceError(target=self, attribute=name, + context=context) - @remove_nodes(node_classes.DelAttr) def instance_attr(self, name, context=None): """return the astroid nodes associated to name in this class instance attributes dictionary and in its parents - :raises `NotFoundError`: + :raises `AttributeInferenceError`: if no attribute with this name has been find in this class or its parent classes """ - # Return a copy, so we don't modify self._instance_attrs, + # Return a copy, so we don't modify self.instance_attrs, # which could lead to infinite loop. - values = list(self._instance_attrs.get(name, [])) + values = list(self.instance_attrs.get(name, [])) # get all values from parents for class_node in self.instance_attr_ancestors(name, context): - values += class_node._instance_attrs[name] - if not values: - raise exceptions.NotFoundError(name) - return values + values += class_node.instance_attrs[name] + values = [n for n in values if not isinstance(n, node_classes.DelAttr)] + if values: + return values + raise exceptions.AttributeInferenceError(target=self, attribute=name, + context=context) def instantiate_class(self): """return Instance of ClassDef node, else return self""" return bases.Instance(self) def instanciate_class(self): - """return Instance of ClassDef node, else return self""" - util.rename_warning('instanciate_class()', 2.0, 'instantiate_class()') + warnings.warn('%s.instanciate_class() is deprecated and slated for ' + 'removal in astroid 2.0, use %s.instantiate_class() ' + 'instead.' % (type(self).__name__, type(self).__name__), + PendingDeprecationWarning, stacklevel=2) return self.instantiate_class() - def getattr(self, name, context=None): - """this method doesn't look in the instance_attrs dictionary since it's - done by an Instance proxy at inference time. + def getattr(self, name, context=None, class_context=True): + """Get an attribute from this class, using Python's attribute semantic + + This method doesn't look in the instance_attrs dictionary + since it's done by an Instance proxy at inference time. It + may return a Uninferable object if the attribute has not been actually + found but a __getattr__ or __getattribute__ method is defined. + If *class_context* is given, then it's considered that the + attribute is accessed from a class context, + e.g. ClassDef.attribute, otherwise it might have been accessed + from an instance as well. If *class_context* is used in that + case, then a lookup in the implicit metaclass and the explicit + metaclass will be done. - It may return a YES object if the attribute has not been actually - found but a __getattr__ or __getattribute__ method is defined """ - values = self._locals.get(name, []) - if name in self.special_attributes: - if name == '__module__': - return [node_classes.const_factory(self.root().qname())] + values + values = self.locals.get(name, []) + if name in self.special_attributes and class_context and not values: + result = [self.special_attributes.lookup(name)] if name == '__bases__': - node = node_classes.Tuple() - elts = list(self._inferred_bases(context)) - node.elts = elts - return [node] + values - if name == '__mro__' and self.newstyle: - mro = self.mro() - node = node_classes.Tuple() - node.elts = mro - return [node] - return std_special_attributes(self, name) - # don't modify the list in self._locals! + # Need special treatment, since they are mutable + # and we need to return all the values. + result += values + return result + + # don't modify the list in self.locals! values = list(values) for classnode in self.ancestors(recurs=True, context=context): - values += classnode._locals.get(name, []) + values += classnode.locals.get(name, []) + + if class_context: + values += self._metaclass_lookup_attribute(name, context) + if not values: - raise exceptions.NotFoundError(name) + raise exceptions.AttributeInferenceError(target=self, attribute=name, + context=context) return values - def igetattr(self, name, context=None): + def _metaclass_lookup_attribute(self, name, context): + """Search the given name in the implicit and the explicit metaclass.""" + attrs = set() + implicit_meta = self.implicit_metaclass() + metaclass = self.metaclass() + for cls in {implicit_meta, metaclass}: + if cls and cls != self and isinstance(cls, ClassDef): + cls_attributes = self._get_attribute_from_metaclass( + cls, name, context) + attrs.update(set(cls_attributes)) + return attrs + + def _get_attribute_from_metaclass(self, cls, name, context): + try: + attrs = cls.getattr(name, context=context, + class_context=True) + except exceptions.AttributeInferenceError: + return + + for attr in bases._infer_stmts(attrs, context, frame=cls): + if not isinstance(attr, FunctionDef): + yield attr + continue + + if bases._is_property(attr): + # TODO(cpopa): don't use a private API. + for inferred in attr.infer_call_result(self, context): + yield inferred + continue + if attr.type == 'classmethod': + # If the method is a classmethod, then it will + # be bound to the metaclass, not to the class + # from where the attribute is retrieved. + # get_wrapping_class could return None, so just + # default to the current class. + frame = get_wrapping_class(attr) or self + yield bases.BoundMethod(attr, frame) + elif attr.type == 'staticmethod': + yield attr + else: + yield bases.BoundMethod(attr, self) + + def igetattr(self, name, context=None, class_context=True): """inferred getattr, need special treatment in class to handle descriptors """ @@ -1384,25 +1470,26 @@ def igetattr(self, name, context=None): context = contextmod.copy_context(context) context.lookupname = name try: - for inferred in bases._infer_stmts(self.getattr(name, context), - context, frame=self): - # yield YES object instead of descriptors when necessary + attrs = self.getattr(name, context, class_context=class_context) + for inferred in bases._infer_stmts(attrs, context, frame=self): + # yield Uninferable object instead of descriptors when necessary if (not isinstance(inferred, node_classes.Const) and isinstance(inferred, bases.Instance)): try: inferred._proxied.getattr('__get__', context) - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: yield inferred else: - yield util.YES + yield util.Uninferable else: yield function_to_method(inferred, self) - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError as error: if not name.startswith('__') and self.has_dynamic_getattr(context): - # class handle some dynamic attributes, return a YES object - yield util.YES + # class handle some dynamic attributes, return a Uninferable object + yield util.Uninferable else: - raise exceptions.InferenceError(name) + util.reraise(exceptions.InferenceError( + error.message, target=self, attribute=name, context=context)) def has_dynamic_getattr(self, context=None): """ @@ -1419,15 +1506,43 @@ def _valid_getattr(node): try: return _valid_getattr(self.getattr('__getattr__', context)[0]) - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: #if self.newstyle: XXX cause an infinite recursion error try: getattribute = self.getattr('__getattribute__', context)[0] return _valid_getattr(getattribute) - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: pass return False + def getitem(self, index, context=None): + """Return the inference of a subscript. + + This is basically looking up the method in the metaclass and calling it. + """ + try: + methods = dunder_lookup.lookup(self, '__getitem__') + except exceptions.AttributeInferenceError as exc: + util.reraise( + exceptions.AstroidTypeError( + node=self, error=exc, + context=context + ) + ) + + method = methods[0] + + # Create a new callcontext for providing index as an argument. + if context: + new_context = context.clone() + else: + new_context = contextmod.InferenceContext() + + new_context.callcontext = contextmod.CallContext(args=[index]) + new_context.boundnode = self + + return next(method.infer_call_result(self, new_context)) + def methods(self): """return an iterator on all methods defined in the class and its ancestors @@ -1458,11 +1573,10 @@ def implicit_metaclass(self): return builtin_lookup('type')[1][0] _metaclass = None - def _explicit_metaclass(self): - """ Return the explicit defined metaclass - for the current class. + def declared_metaclass(self): + """Return the explicit declared metaclass for the current class. - An explicit defined metaclass is defined + An explicit declared metaclass is defined either by passing the ``metaclass`` keyword argument in the class definition line (Python 3) or (Python 2) by having a ``__metaclass__`` class attribute, or if there are @@ -1482,18 +1596,18 @@ def _explicit_metaclass(self): # Expects this from Py3k TreeRebuilder try: return next(node for node in self._metaclass.infer() - if node is not util.YES) + if node is not util.Uninferable) except (exceptions.InferenceError, StopIteration): return None if six.PY3: return None - if '__metaclass__' in self._locals: - assignment = self._locals['__metaclass__'][-1] + if '__metaclass__' in self.locals: + assignment = self.locals['__metaclass__'][-1] elif self.bases: return None - elif '__metaclass__' in self.root()._locals: - assignments = [ass for ass in self.root()._locals['__metaclass__'] + elif '__metaclass__' in self.root().locals: + assignments = [ass for ass in self.root().locals['__metaclass__'] if ass.lineno < self.lineno] if not assignments: return None @@ -1505,7 +1619,7 @@ def _explicit_metaclass(self): inferred = next(assignment.infer()) except exceptions.InferenceError: return - if inferred is util.YES: # don't expose this + if inferred is util.Uninferable: # don't expose this return None return inferred @@ -1514,7 +1628,7 @@ def _find_metaclass(self, seen=None): seen = set() seen.add(self) - klass = self._explicit_metaclass() + klass = self.declared_metaclass() if klass is None: for parent in self.ancestors(): if parent not in seen: @@ -1537,7 +1651,7 @@ def has_metaclass_hack(self): def _islots(self): """ Return an iterator with the inferred slots. """ - if '__slots__' not in self._locals: + if '__slots__' not in self.locals: return for slots in self.igetattr('__slots__'): # check if __slots__ is a valid type @@ -1545,7 +1659,7 @@ def _islots(self): try: slots.getattr(meth) break - except exceptions.NotFoundError: + except exceptions.AttributeInferenceError: continue else: continue @@ -1564,7 +1678,7 @@ def _islots(self): values = [item[0] for item in slots.items] else: values = slots.itered() - if values is util.YES: + if values is util.Uninferable: continue if not values: # Stop the iteration, because the class @@ -1574,7 +1688,7 @@ def _islots(self): for elt in values: try: for inferred in elt.infer(): - if inferred is util.YES: + if inferred is util.Uninferable: continue if (not isinstance(inferred, node_classes.Const) or not isinstance(inferred.value, @@ -1599,7 +1713,6 @@ def _slots(self): if exc.args and exc.args[0] not in ('', None): return exc.args[0] return None - # pylint: disable=unsupported-binary-operation; false positive return [first] + list(slots) # Cached, because inferring them all the time is expensive @@ -1672,22 +1785,15 @@ def _inferred_bases(self, context=None): for base in baseobj.bases: yield base - def mro(self, context=None): - """Get the method resolution order, using C3 linearization. - - It returns the list of ancestors sorted by the mro. - This will raise `NotImplementedError` for old-style classes, since - they don't have the concept of MRO. - """ - if not self.newstyle: - raise NotImplementedError( - "Could not obtain mro for old-style classes.") - - bases = list(self._inferred_bases(context=context)) + def _compute_mro(self, context=None): + inferred_bases = list(self._inferred_bases(context=context)) bases_mro = [] - for base in bases: + for base in inferred_bases: + if base is self: + continue + try: - mro = base.mro(context=context) + mro = base._compute_mro(context=context) bases_mro.append(mro) except NotImplementedError: # Some classes have in their ancestors both newstyle and @@ -1698,19 +1804,29 @@ def mro(self, context=None): ancestors = list(base.ancestors(context=context)) bases_mro.append(ancestors) - unmerged_mro = ([[self]] + bases_mro + [bases]) - _verify_duplicates_mro(unmerged_mro) - return _c3_merge(unmerged_mro) + unmerged_mro = ([[self]] + bases_mro + [inferred_bases]) + _verify_duplicates_mro(unmerged_mro, self, context) + return _c3_merge(unmerged_mro, self, context) + + def mro(self, context=None): + """Get the method resolution order, using C3 linearization. + + It returns the list of ancestors sorted by the mro. + This will raise `NotImplementedError` for old-style classes, since + they don't have the concept of MRO. + """ + + if not self.newstyle: + raise NotImplementedError( + "Could not obtain mro for old-style classes.") + + return self._compute_mro(context=context) -def get_locals(node): - '''Stub function for forwards compatibility.''' - return node._locals + def bool_value(self): + return True -def get_attributes(node): - '''Stub function for forwards compatibility.''' - return node._instance_attrs # Backwards-compatibility aliases -Class = node_classes.proxy_alias('Class', ClassDef) -Function = node_classes.proxy_alias('Function', FunctionDef) -GenExpr = node_classes.proxy_alias('GenExpr', GeneratorExp) +Class = util.proxy_alias('Class', ClassDef) +Function = util.proxy_alias('Function', FunctionDef) +GenExpr = util.proxy_alias('GenExpr', GeneratorExp) diff --git a/pymode/libs/astroid/test_utils.py b/pymode/libs/astroid/test_utils.py index 9e45abcf..e7e64b17 100644 --- a/pymode/libs/astroid/test_utils.py +++ b/pymode/libs/astroid/test_utils.py @@ -1,172 +1,18 @@ +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + """Utility functions for test code that uses astroid ASTs as input.""" +import contextlib import functools import sys +import warnings from astroid import nodes -from astroid import builder -# The name of the transient function that is used to -# wrap expressions to be extracted when calling -# extract_node. -_TRANSIENT_FUNCTION = '__' - -# The comment used to select a statement to be extracted -# when calling extract_node. -_STATEMENT_SELECTOR = '#@' - -def _extract_expressions(node): - """Find expressions in a call to _TRANSIENT_FUNCTION and extract them. - - The function walks the AST recursively to search for expressions that - are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an - expression, it completely removes the function call node from the tree, - replacing it by the wrapped expression inside the parent. - - :param node: An astroid node. - :type node: astroid.bases.NodeNG - :yields: The sequence of wrapped expressions on the modified tree - expression can be found. - """ - if (isinstance(node, nodes.Call) - and isinstance(node.func, nodes.Name) - and node.func.name == _TRANSIENT_FUNCTION): - real_expr = node.args[0] - real_expr.parent = node.parent - # Search for node in all _astng_fields (the fields checked when - # get_children is called) of its parent. Some of those fields may - # be lists or tuples, in which case the elements need to be checked. - # When we find it, replace it by real_expr, so that the AST looks - # like no call to _TRANSIENT_FUNCTION ever took place. - for name in node.parent._astroid_fields: - child = getattr(node.parent, name) - if isinstance(child, (list, tuple)): - for idx, compound_child in enumerate(child): - if compound_child is node: - child[idx] = real_expr - elif child is node: - setattr(node.parent, name, real_expr) - yield real_expr - else: - for child in node.get_children(): - for result in _extract_expressions(child): - yield result - - -def _find_statement_by_line(node, line): - """Extracts the statement on a specific line from an AST. - - If the line number of node matches line, it will be returned; - otherwise its children are iterated and the function is called - recursively. - - :param node: An astroid node. - :type node: astroid.bases.NodeNG - :param line: The line number of the statement to extract. - :type line: int - :returns: The statement on the line, or None if no statement for the line - can be found. - :rtype: astroid.bases.NodeNG or None - """ - if isinstance(node, (nodes.ClassDef, nodes.FunctionDef)): - # This is an inaccuracy in the AST: the nodes that can be - # decorated do not carry explicit information on which line - # the actual definition (class/def), but .fromline seems to - # be close enough. - node_line = node.fromlineno - else: - node_line = node.lineno - - if node_line == line: - return node - - for child in node.get_children(): - result = _find_statement_by_line(child, line) - if result: - return result - - return None - -def extract_node(code, module_name=''): - """Parses some Python code as a module and extracts a designated AST node. - - Statements: - To extract one or more statement nodes, append #@ to the end of the line - - Examples: - >>> def x(): - >>> def y(): - >>> return 1 #@ - - The return statement will be extracted. - - >>> class X(object): - >>> def meth(self): #@ - >>> pass - - The funcion object 'meth' will be extracted. - - Expressions: - To extract arbitrary expressions, surround them with the fake - function call __(...). After parsing, the surrounded expression - will be returned and the whole AST (accessible via the returned - node's parent attribute) will look like the function call was - never there in the first place. - - Examples: - >>> a = __(1) - - The const node will be extracted. - - >>> def x(d=__(foo.bar)): pass - - The node containing the default argument will be extracted. - - >>> def foo(a, b): - >>> return 0 < __(len(a)) < b - - The node containing the function call 'len' will be extracted. - - If no statements or expressions are selected, the last toplevel - statement will be returned. - - If the selected statement is a discard statement, (i.e. an expression - turned into a statement), the wrapped expression is returned instead. - - For convenience, singleton lists are unpacked. - - :param str code: A piece of Python code that is parsed as - a module. Will be passed through textwrap.dedent first. - :param str module_name: The name of the module. - :returns: The designated node from the parse tree, or a list of nodes. - :rtype: astroid.bases.NodeNG, or a list of nodes. - """ - def _extract(node): - if isinstance(node, nodes.Expr): - return node.value - else: - return node - - requested_lines = [] - for idx, line in enumerate(code.splitlines()): - if line.strip().endswith(_STATEMENT_SELECTOR): - requested_lines.append(idx + 1) - - tree = builder.parse(code, module_name=module_name) - extracted = [] - if requested_lines: - for line in requested_lines: - extracted.append(_find_statement_by_line(tree, line)) - - # Modifies the tree. - extracted.extend(_extract_expressions(tree)) - - if not extracted: - extracted.append(tree.body[-1]) - - extracted = [_extract(node) for node in extracted] - if len(extracted) == 1: - return extracted[0] - else: - return extracted +from astroid import util def require_version(minver=None, maxver=None): @@ -178,24 +24,38 @@ def parse(string, default=None): try: return tuple(int(v) for v in string.split('.')) except ValueError: - raise ValueError('%s is not a correct version : should be X.Y[.Z].' % version) + util.reraise(ValueError('%s is not a correct version : should be X.Y[.Z].' % string)) def check_require_version(f): current = sys.version_info[:3] if parse(minver, "0") < current <= parse(maxver, "4"): return f - else: - str_version = '.'.join(str(v) for v in sys.version_info) - @functools.wraps(f) - def new_f(self, *args, **kwargs): - if minver is not None: - self.skipTest('Needs Python > %s. Current version is %s.' % (minver, str_version)) - elif maxver is not None: - self.skipTest('Needs Python <= %s. Current version is %s.' % (maxver, str_version)) - return new_f + + str_version = '.'.join(str(v) for v in sys.version_info) + @functools.wraps(f) + def new_f(self, *args, **kwargs): + if minver is not None: + self.skipTest('Needs Python > %s. Current version is %s.' + % (minver, str_version)) + elif maxver is not None: + self.skipTest('Needs Python <= %s. Current version is %s.' + % (maxver, str_version)) + return new_f return check_require_version def get_name_node(start_from, name, index=0): return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index] + + +@contextlib.contextmanager +def enable_warning(warning): + warnings.simplefilter('always', warning) + try: + yield + finally: + # Reset it to default value, so it will take + # into account the values from the -W flag. + warnings.simplefilter('default', warning) + \ No newline at end of file diff --git a/pymode/libs/astroid/tests/resources.py b/pymode/libs/astroid/tests/resources.py deleted file mode 100644 index 7988d053..00000000 --- a/pymode/libs/astroid/tests/resources.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2014 Google, Inc. All rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -import os -import sys - -import pkg_resources - -from astroid import builder -from astroid import MANAGER -from astroid.bases import BUILTINS - - -DATA_DIR = 'testdata/python{}/'.format(sys.version_info[0]) - -def find(name): - return pkg_resources.resource_filename( - 'astroid.tests', os.path.normpath(os.path.join(DATA_DIR, name))) - - -def build_file(path, modname=None): - return builder.AstroidBuilder().file_build(find(path), modname) - - -class SysPathSetup(object): - def setUp(self): - sys.path.insert(0, find('')) - - def tearDown(self): - del sys.path[0] - datadir = find('') - for key in list(sys.path_importer_cache): - if key.startswith(datadir): - del sys.path_importer_cache[key] - - -class AstroidCacheSetupMixin(object): - """Mixin for handling the astroid cache problems. - - When clearing the astroid cache, some tests fails due to - cache inconsistencies, where some objects had a different - builtins object referenced. - This saves the builtins module and makes sure to add it - back to the astroid_cache after the tests finishes. - The builtins module is special, since some of the - transforms for a couple of its objects (str, bytes etc) - are executed only once, so astroid_bootstrapping will be - useless for retrieving the original builtins module. - """ - - @classmethod - def setUpClass(cls): - cls._builtins = MANAGER.astroid_cache.get(BUILTINS) - - @classmethod - def tearDownClass(cls): - if cls._builtins: - MANAGER.astroid_cache[BUILTINS] = cls._builtins diff --git a/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg b/pymode/libs/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg deleted file mode 100644 index f62599c7b10469b9eadabb31e9a42128a769c7cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1222 zcmWIWW@Zs#U|`^2V0WyvGL3P1+yvw;0%Bnx&aEt{EJ)OkkI&4@EQycTE2vDq{ik!f z_N!x_=Tq1;5?GSh74)7l32E~11UgKbs2I`Asd9`*h35;;UlWH_UOO6HYHA|00t?gX z;%fG=d001TTw@jTTsqTI^OvXQ%%iGRmNP4titd`3CYJVV<;$19c1~rT%G&wsg1;w&+sQ$d~(!s_JietmCU zt#fD2clU>H2n{g5U>x$C3CR?Y$GxZZOpXTX?t_}->h7-V>F4IJAM76*_t<%}h{;@`zS&LcdYtZG(rN*BxefrA0=WeO(-#dQ{Rhs@f zH_wS}{_3UWW$+{@h&$+WP|)W|+K-EkK5y#YsHJsMzvH~8uJ>8Sljx37u41p@1UiHr zh(TV1JEkPRAU-FxEHww@oYQM{R_J&&P!l5%%OYz|Ni9gtOG(X3u8hyg z%*!qYneiB(Zb4+-Rhb34#ffRD7&;CGJDSu1Rc;4j6deKHkRbf*tLy3GspENt7ZMAb zgAA@1KltQ*#&>JbhqXK_cs!mootAjf_@v3ZxLCMbYpqDoC(%!zyp4=LU)pK&sW`Zl zTj+A*ET_MF{{A`qcZZC(x6!BW3qNg1;w&+sQ$d~(!s_JietmCU zt#fD2clU>H2n{g5U>x$C3CR?Y$GxZZOpXTX?t_}->h7-V>F4IJAM76*_t<%}h{;@`zS&LcdYtZG(rN*BxefrA0=WeO(-#dQ{Rhs@f zH_wS}{_3UWW$+{@h&$+WP|)W|+K-EkK5y#YsHJsMzvH~8uJ>8Sljx37u41p@1UiHr zh(TV1JEkPRAU-FxEHww@oYQM{R_J&&P!l5%%OYz|Ni9gtOG(X3u8hyg z%*!qYneiB(Zb4+-Rhb34#ffRD7&;CGJDSu1Rc;4j6deKHkRbf*tLy3GspENt7ZMAb zgAA@1KltQ*#&>JbhqXK_cs!mootAjf_@v3ZxLCMbYpqDoC(%!zyp4=LU)pK&sW`Zl zTj+A*ET_MF{{A`qcZZC(x6!BW3qN> (2) -c = ~b -c = not b -d = [c] -e = d[:] -e = d[a:b:c] -raise_string(*args, **kwargs) -print >> stream, 'bonjour' -print >> stream, 'salut', - -def make_class(any, base=data.module.YO, *args, **kwargs): - """check base is correctly resolved to Concrete0""" - - - class Aaaa(base): - """dynamic class""" - - - return Aaaa -from os.path import abspath -import os as myos - - -class A: - pass - - - -class A(A): - pass - - -def generator(): - """A generator.""" - yield - -def not_a_generator(): - """A function that contains generator, but is not one.""" - - def generator(): - yield - genl = lambda : (yield) - -def with_metaclass(meta, *bases): - return meta('NewBase', bases, {}) - - -class NotMetaclass(with_metaclass(Metaclass)): - pass - - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py deleted file mode 100644 index e1d6e4a1..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/noendingnewline.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - - -class TestCase(unittest.TestCase): - - def setUp(self): - unittest.TestCase.setUp(self) - - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testIt(self): - self.a = 10 - self.xxx() - - - def xxx(self): - if False: - pass - print 'a' - - if False: - pass - pass - - if False: - pass - print 'rara' - - -if __name__ == '__main__': - print 'test2' - unittest.main() - - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py b/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py deleted file mode 100644 index 813469fe..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/nonregr.py +++ /dev/null @@ -1,57 +0,0 @@ -from __future__ import generators, print_function - -try: - enumerate = enumerate -except NameError: - - def enumerate(iterable): - """emulates the python2.3 enumerate() function""" - i = 0 - for val in iterable: - yield i, val - i += 1 - -def toto(value): - for k, v in value: - print(v.get('yo')) - - -import imp -fp, mpath, desc = imp.find_module('optparse',a) -s_opt = imp.load_module('std_optparse', fp, mpath, desc) - -class OptionParser(s_opt.OptionParser): - - def parse_args(self, args=None, values=None, real_optparse=False): - if real_optparse: - pass -## return super(OptionParser, self).parse_args() - else: - import optcomp - optcomp.completion(self) - - -class Aaa(object): - """docstring""" - def __init__(self): - self.__setattr__('a','b') - pass - - def one_public(self): - """docstring""" - pass - - def another_public(self): - """docstring""" - pass - -class Ccc(Aaa): - """docstring""" - - class Ddd(Aaa): - """docstring""" - pass - - class Eee(Ddd): - """docstring""" - pass diff --git a/pymode/libs/astroid/tests/testdata/python2/data/notall.py b/pymode/libs/astroid/tests/testdata/python2/data/notall.py deleted file mode 100644 index 7be27b18..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/notall.py +++ /dev/null @@ -1,7 +0,0 @@ -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print('yo') - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py deleted file mode 100644 index 575d18b1..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""package's __init__ file""" - - -from . import subpackage diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py b/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py deleted file mode 100644 index 33ed117c..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/absimport.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import absolute_import, print_function -import import_package_subpackage_module # fail -print(import_package_subpackage_module) - -from . import hello as hola - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py b/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py deleted file mode 100644 index b154c844..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -"""hello module""" - diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py b/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py deleted file mode 100644 index ad442c16..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable-msg=I0011,C0301,W0611 -"""I found some of my scripts trigger off an AttributeError in pylint -0.8.1 (with common 0.12.0 and astroid 0.13.1). - -Traceback (most recent call last): - File "/usr/bin/pylint", line 4, in ? - lint.Run(sys.argv[1:]) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__ - linter.check(args) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check - self.check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file - astroid = self._check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file - self.check_astroid_module(astroid, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module - self.astroid_events(astroid, [checker for checker in checkers - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events - checker.visit(astroid) - File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit - method(node) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import - self._check_module_attrs(node, module, name_parts[1:]) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs - self.add_message('E0611', args=(name, module.name), -AttributeError: Import instance has no attribute 'name' - - -You can reproduce it by: -(1) create package structure like the following: - -package/ - __init__.py - subpackage/ - __init__.py - module.py - -(2) in package/__init__.py write: - -import subpackage - -(3) run pylint with a script importing package.subpackage.module. -""" -__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $' -import package.subpackage.module diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py deleted file mode 100644 index dc4782e6..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py b/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py deleted file mode 100644 index 4b7244ba..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/package/subpackage/module.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage.module""" diff --git a/pymode/libs/astroid/tests/testdata/python2/data/recursion.py b/pymode/libs/astroid/tests/testdata/python2/data/recursion.py deleted file mode 100644 index 85f65134..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/recursion.py +++ /dev/null @@ -1,3 +0,0 @@ -""" For issue #25 """ -class Base(object): - pass \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py b/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py deleted file mode 100644 index ddacb477..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/suppliermodule_test.py +++ /dev/null @@ -1,13 +0,0 @@ -""" file suppliermodule.py """ - -class NotImplemented(Exception): - pass - -class Interface: - def get_value(self): - raise NotImplemented() - - def set_value(self, value): - raise NotImplemented() - -class DoNothing : pass diff --git a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py deleted file mode 100644 index 713e5591..00000000 --- a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/__init__.py +++ /dev/null @@ -1 +0,0 @@ -x = "șțîâ" \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py b/pymode/libs/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg b/pymode/libs/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg deleted file mode 100644 index f62599c7b10469b9eadabb31e9a42128a769c7cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1222 zcmWIWW@Zs#U|`^2V0WyvGL3P1+yvw;0%Bnx&aEt{EJ)OkkI&4@EQycTE2vDq{ik!f z_N!x_=Tq1;5?GSh74)7l32E~11UgKbs2I`Asd9`*h35;;UlWH_UOO6HYHA|00t?gX z;%fG=d001TTw@jTTsqTI^OvXQ%%iGRmNP4titd`3CYJVV<;$19c1~rT%G&wsg1;w&+sQ$d~(!s_JietmCU zt#fD2clU>H2n{g5U>x$C3CR?Y$GxZZOpXTX?t_}->h7-V>F4IJAM76*_t<%}h{;@`zS&LcdYtZG(rN*BxefrA0=WeO(-#dQ{Rhs@f zH_wS}{_3UWW$+{@h&$+WP|)W|+K-EkK5y#YsHJsMzvH~8uJ>8Sljx37u41p@1UiHr zh(TV1JEkPRAU-FxEHww@oYQM{R_J&&P!l5%%OYz|Ni9gtOG(X3u8hyg z%*!qYneiB(Zb4+-Rhb34#ffRD7&;CGJDSu1Rc;4j6deKHkRbf*tLy3GspENt7ZMAb zgAA@1KltQ*#&>JbhqXK_cs!mootAjf_@v3ZxLCMbYpqDoC(%!zyp4=LU)pK&sW`Zl zTj+A*ET_MF{{A`qcZZC(x6!BW3qNg1;w&+sQ$d~(!s_JietmCU zt#fD2clU>H2n{g5U>x$C3CR?Y$GxZZOpXTX?t_}->h7-V>F4IJAM76*_t<%}h{;@`zS&LcdYtZG(rN*BxefrA0=WeO(-#dQ{Rhs@f zH_wS}{_3UWW$+{@h&$+WP|)W|+K-EkK5y#YsHJsMzvH~8uJ>8Sljx37u41p@1UiHr zh(TV1JEkPRAU-FxEHww@oYQM{R_J&&P!l5%%OYz|Ni9gtOG(X3u8hyg z%*!qYneiB(Zb4+-Rhb34#ffRD7&;CGJDSu1Rc;4j6deKHkRbf*tLy3GspENt7ZMAb zgAA@1KltQ*#&>JbhqXK_cs!mootAjf_@v3ZxLCMbYpqDoC(%!zyp4=LU)pK&sW`Zl zTj+A*ET_MF{{A`qcZZC(x6!BW3qN> (2) -c = ~b -c = not b -d = [c] -e = d[:] -e = d[a:b:c] -raise_string(*args, **kwargs) -print('bonjour', file=stream) -print('salut', end=' ', file=stream) - -def make_class(any, base=data.module.YO, *args, **kwargs): - """check base is correctly resolved to Concrete0""" - - - class Aaaa(base): - """dynamic class""" - - - return Aaaa -from os.path import abspath -import os as myos - - -class A: - pass - - - -class A(A): - pass - - -def generator(): - """A generator.""" - yield - -def not_a_generator(): - """A function that contains generator, but is not one.""" - - def generator(): - yield - genl = lambda : (yield) - -def with_metaclass(meta, *bases): - return meta('NewBase', bases, {}) - - -class NotMetaclass(with_metaclass(Metaclass)): - pass - - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py b/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py deleted file mode 100644 index e17b92cc..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/noendingnewline.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - - -class TestCase(unittest.TestCase): - - def setUp(self): - unittest.TestCase.setUp(self) - - - def tearDown(self): - unittest.TestCase.tearDown(self) - - def testIt(self): - self.a = 10 - self.xxx() - - - def xxx(self): - if False: - pass - print('a') - - if False: - pass - pass - - if False: - pass - print('rara') - - -if __name__ == '__main__': - print('test2') - unittest.main() - - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py b/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py deleted file mode 100644 index 78765c85..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/nonregr.py +++ /dev/null @@ -1,57 +0,0 @@ - - -try: - enumerate = enumerate -except NameError: - - def enumerate(iterable): - """emulates the python2.3 enumerate() function""" - i = 0 - for val in iterable: - yield i, val - i += 1 - -def toto(value): - for k, v in value: - print(v.get('yo')) - - -import imp -fp, mpath, desc = imp.find_module('optparse',a) -s_opt = imp.load_module('std_optparse', fp, mpath, desc) - -class OptionParser(s_opt.OptionParser): - - def parse_args(self, args=None, values=None, real_optparse=False): - if real_optparse: - pass -## return super(OptionParser, self).parse_args() - else: - import optcomp - optcomp.completion(self) - - -class Aaa(object): - """docstring""" - def __init__(self): - self.__setattr__('a','b') - pass - - def one_public(self): - """docstring""" - pass - - def another_public(self): - """docstring""" - pass - -class Ccc(Aaa): - """docstring""" - - class Ddd(Aaa): - """docstring""" - pass - - class Eee(Ddd): - """docstring""" - pass diff --git a/pymode/libs/astroid/tests/testdata/python3/data/notall.py b/pymode/libs/astroid/tests/testdata/python3/data/notall.py deleted file mode 100644 index 9d35aa3a..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/notall.py +++ /dev/null @@ -1,8 +0,0 @@ - -name = 'a' -_bla = 2 -other = 'o' -class Aaa: pass - -def func(): print('yo') - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py deleted file mode 100644 index 575d18b1..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""package's __init__ file""" - - -from . import subpackage diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py b/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py deleted file mode 100644 index 33ed117c..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/absimport.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import absolute_import, print_function -import import_package_subpackage_module # fail -print(import_package_subpackage_module) - -from . import hello as hola - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py b/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py deleted file mode 100644 index b154c844..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -"""hello module""" - diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py b/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py deleted file mode 100644 index ad442c16..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable-msg=I0011,C0301,W0611 -"""I found some of my scripts trigger off an AttributeError in pylint -0.8.1 (with common 0.12.0 and astroid 0.13.1). - -Traceback (most recent call last): - File "/usr/bin/pylint", line 4, in ? - lint.Run(sys.argv[1:]) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__ - linter.check(args) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check - self.check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file - astroid = self._check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file - self.check_astroid_module(astroid, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module - self.astroid_events(astroid, [checker for checker in checkers - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events - checker.visit(astroid) - File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit - method(node) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import - self._check_module_attrs(node, module, name_parts[1:]) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs - self.add_message('E0611', args=(name, module.name), -AttributeError: Import instance has no attribute 'name' - - -You can reproduce it by: -(1) create package structure like the following: - -package/ - __init__.py - subpackage/ - __init__.py - module.py - -(2) in package/__init__.py write: - -import subpackage - -(3) run pylint with a script importing package.subpackage.module. -""" -__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $' -import package.subpackage.module diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py deleted file mode 100644 index dc4782e6..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py b/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py deleted file mode 100644 index 4b7244ba..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/package/subpackage/module.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage.module""" diff --git a/pymode/libs/astroid/tests/testdata/python3/data/recursion.py b/pymode/libs/astroid/tests/testdata/python3/data/recursion.py deleted file mode 100644 index 85f65134..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/recursion.py +++ /dev/null @@ -1,3 +0,0 @@ -""" For issue #25 """ -class Base(object): - pass \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py b/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py deleted file mode 100644 index ddacb477..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/suppliermodule_test.py +++ /dev/null @@ -1,13 +0,0 @@ -""" file suppliermodule.py """ - -class NotImplemented(Exception): - pass - -class Interface: - def get_value(self): - raise NotImplemented() - - def set_value(self, value): - raise NotImplemented() - -class DoNothing : pass diff --git a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py deleted file mode 100644 index 713e5591..00000000 --- a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/__init__.py +++ /dev/null @@ -1 +0,0 @@ -x = "șțîâ" \ No newline at end of file diff --git a/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py b/pymode/libs/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/astroid/tests/unittest_brain.py b/pymode/libs/astroid/tests/unittest_brain.py deleted file mode 100644 index 9dbbe1d0..00000000 --- a/pymode/libs/astroid/tests/unittest_brain.py +++ /dev/null @@ -1,506 +0,0 @@ -# Copyright 2013 Google Inc. All Rights Reserved. -# -# This file is part of astroid. -# -# logilab-astng is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# logilab-astng 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with logilab-astng. If not, see . -"""Tests for basic functionality in astroid.brain.""" -import sys -import unittest - -import six - -from astroid import MANAGER -from astroid import bases -from astroid import builder -from astroid import nodes -from astroid import test_utils -from astroid import util -import astroid - - -try: - import nose # pylint: disable=unused-import - HAS_NOSE = True -except ImportError: - HAS_NOSE = False - -try: - import multiprocessing # pylint: disable=unused-import - HAS_MULTIPROCESSING = True -except ImportError: - HAS_MULTIPROCESSING = False - -try: - import enum # pylint: disable=unused-import - HAS_ENUM = True -except ImportError: - HAS_ENUM = False - -try: - import dateutil # pylint: disable=unused-import - HAS_DATEUTIL = True -except ImportError: - HAS_DATEUTIL = False - -try: - import numpy # pylint: disable=unused-import - HAS_NUMPY = True -except ImportError: - HAS_NUMPY = False - -try: - import pytest # pylint: disable=unused-import - HAS_PYTEST = True -except ImportError: - HAS_PYTEST = False - - -class HashlibTest(unittest.TestCase): - def test_hashlib(self): - """Tests that brain extensions for hashlib work.""" - hashlib_module = MANAGER.ast_from_module_name('hashlib') - for class_name in ['md5', 'sha1']: - class_obj = hashlib_module[class_name] - self.assertIn('update', class_obj) - self.assertIn('digest', class_obj) - self.assertIn('hexdigest', class_obj) - self.assertIn('block_size', class_obj) - self.assertIn('digest_size', class_obj) - self.assertEqual(len(class_obj['__init__'].args.args), 2) - self.assertEqual(len(class_obj['__init__'].args.defaults), 1) - self.assertEqual(len(class_obj['update'].args.args), 2) - self.assertEqual(len(class_obj['digest'].args.args), 1) - self.assertEqual(len(class_obj['hexdigest'].args.args), 1) - - -class NamedTupleTest(unittest.TestCase): - - def test_namedtuple_base(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - class X(namedtuple("X", ["a", "b", "c"])): - pass - """) - self.assertEqual( - [anc.name for anc in klass.ancestors()], - ['X', 'tuple', 'object']) - for anc in klass.ancestors(): - self.assertFalse(anc.parent is None) - - def test_namedtuple_inference(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - name = "X" - fields = ["a", "b", "c"] - class X(namedtuple(name, fields)): - pass - """) - for base in klass.ancestors(): - if base.name == 'X': - break - self.assertSetEqual({"a", "b", "c"}, set(base._instance_attrs)) - - def test_namedtuple_inference_failure(self): - klass = test_utils.extract_node(""" - from collections import namedtuple - - def foo(fields): - return __(namedtuple("foo", fields)) - """) - self.assertIs(util.YES, next(klass.infer())) - - @unittest.skipIf(sys.version_info[0] > 2, - 'namedtuple inference is broken on Python 3') - def test_namedtuple_advanced_inference(self): - # urlparse return an object of class ParseResult, which has a - # namedtuple call and a mixin as base classes - result = test_utils.extract_node(""" - import urlparse - - result = __(urlparse.urlparse('gopher://')) - """) - instance = next(result.infer()) - self.assertEqual(len(instance.getattr('scheme')), 1) - self.assertEqual(len(instance.getattr('port')), 1) - with self.assertRaises(astroid.NotFoundError): - instance.getattr('foo') - self.assertEqual(len(instance.getattr('geturl')), 1) - self.assertEqual(instance.name, 'ParseResult') - - def test_namedtuple_instance_attrs(self): - result = test_utils.extract_node(''' - from collections import namedtuple - namedtuple('a', 'a b c')(1, 2, 3) #@ - ''') - inferred = next(result.infer()) - for name, attr in inferred._instance_attrs.items(): - self.assertEqual(attr[0].attrname, name) - - def test_namedtuple_uninferable_fields(self): - node = test_utils.extract_node(''' - x = [A] * 2 - from collections import namedtuple - l = namedtuple('a', x) - l(1) - ''') - inferred = next(node.infer()) - self.assertIs(util.YES, inferred) - - -class ModuleExtenderTest(unittest.TestCase): - def testExtensionModules(self): - transformer = MANAGER._transform - for extender, _ in transformer.transforms[nodes.Module]: - n = nodes.Module('__main__', None) - extender(n) - - -@unittest.skipUnless(HAS_NOSE, "This test requires nose library.") -class NoseBrainTest(unittest.TestCase): - - def test_nose_tools(self): - methods = test_utils.extract_node(""" - from nose.tools import assert_equal - from nose.tools import assert_equals - from nose.tools import assert_true - assert_equal = assert_equal #@ - assert_true = assert_true #@ - assert_equals = assert_equals #@ - """) - assert_equal = next(methods[0].value.infer()) - assert_true = next(methods[1].value.infer()) - assert_equals = next(methods[2].value.infer()) - - self.assertIsInstance(assert_equal, astroid.BoundMethod) - self.assertIsInstance(assert_true, astroid.BoundMethod) - self.assertIsInstance(assert_equals, astroid.BoundMethod) - self.assertEqual(assert_equal.qname(), - 'unittest.case.TestCase.assertEqual') - self.assertEqual(assert_true.qname(), - 'unittest.case.TestCase.assertTrue') - self.assertEqual(assert_equals.qname(), - 'unittest.case.TestCase.assertEqual') - - -class SixBrainTest(unittest.TestCase): - - def test_attribute_access(self): - ast_nodes = test_utils.extract_node(''' - import six - six.moves.http_client #@ - six.moves.urllib_parse #@ - six.moves.urllib_error #@ - six.moves.urllib.request #@ - ''') - http_client = next(ast_nodes[0].infer()) - self.assertIsInstance(http_client, nodes.Module) - self.assertEqual(http_client.name, - 'http.client' if six.PY3 else 'httplib') - - urllib_parse = next(ast_nodes[1].infer()) - if six.PY3: - self.assertIsInstance(urllib_parse, nodes.Module) - self.assertEqual(urllib_parse.name, 'urllib.parse') - else: - # On Python 2, this is a fake module, the same behaviour - # being mimicked in brain's tip for six.moves. - self.assertIsInstance(urllib_parse, astroid.Instance) - urljoin = next(urllib_parse.igetattr('urljoin')) - urlencode = next(urllib_parse.igetattr('urlencode')) - if six.PY2: - # In reality it's a function, but our implementations - # transforms it into a method. - self.assertIsInstance(urljoin, astroid.BoundMethod) - self.assertEqual(urljoin.qname(), 'urlparse.urljoin') - self.assertIsInstance(urlencode, astroid.BoundMethod) - self.assertEqual(urlencode.qname(), 'urllib.urlencode') - else: - self.assertIsInstance(urljoin, nodes.FunctionDef) - self.assertEqual(urljoin.qname(), 'urllib.parse.urljoin') - self.assertIsInstance(urlencode, nodes.FunctionDef) - self.assertEqual(urlencode.qname(), 'urllib.parse.urlencode') - - urllib_error = next(ast_nodes[2].infer()) - if six.PY3: - self.assertIsInstance(urllib_error, nodes.Module) - self.assertEqual(urllib_error.name, 'urllib.error') - else: - # On Python 2, this is a fake module, the same behaviour - # being mimicked in brain's tip for six.moves. - self.assertIsInstance(urllib_error, astroid.Instance) - urlerror = next(urllib_error.igetattr('URLError')) - self.assertIsInstance(urlerror, nodes.ClassDef) - content_too_short = next(urllib_error.igetattr('ContentTooShortError')) - self.assertIsInstance(content_too_short, nodes.ClassDef) - - urllib_request = next(ast_nodes[3].infer()) - if six.PY3: - self.assertIsInstance(urllib_request, nodes.Module) - self.assertEqual(urllib_request.name, 'urllib.request') - else: - self.assertIsInstance(urllib_request, astroid.Instance) - urlopen = next(urllib_request.igetattr('urlopen')) - urlretrieve = next(urllib_request.igetattr('urlretrieve')) - if six.PY2: - # In reality it's a function, but our implementations - # transforms it into a method. - self.assertIsInstance(urlopen, astroid.BoundMethod) - self.assertEqual(urlopen.qname(), 'urllib2.urlopen') - self.assertIsInstance(urlretrieve, astroid.BoundMethod) - self.assertEqual(urlretrieve.qname(), 'urllib.urlretrieve') - else: - self.assertIsInstance(urlopen, nodes.FunctionDef) - self.assertEqual(urlopen.qname(), 'urllib.request.urlopen') - self.assertIsInstance(urlretrieve, nodes.FunctionDef) - self.assertEqual(urlretrieve.qname(), 'urllib.request.urlretrieve') - - def test_from_imports(self): - ast_node = test_utils.extract_node(''' - from six.moves import http_client - http_client.HTTPSConnection #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.ClassDef) - if six.PY3: - qname = 'http.client.HTTPSConnection' - else: - qname = 'httplib.HTTPSConnection' - self.assertEqual(inferred.qname(), qname) - - -@unittest.skipUnless(HAS_MULTIPROCESSING, - 'multiprocesing is required for this test, but ' - 'on some platforms it is missing ' - '(Jython for instance)') -class MultiprocessingBrainTest(unittest.TestCase): - - def test_multiprocessing_module_attributes(self): - # Test that module attributes are working, - # especially on Python 3.4+, where they are obtained - # from a context. - module = test_utils.extract_node(""" - import multiprocessing - """) - module = module.do_import_module('multiprocessing') - cpu_count = next(module.igetattr('cpu_count')) - if sys.version_info < (3, 4): - self.assertIsInstance(cpu_count, nodes.FunctionDef) - else: - self.assertIsInstance(cpu_count, astroid.BoundMethod) - - def test_module_name(self): - module = test_utils.extract_node(""" - import multiprocessing - multiprocessing.SyncManager() - """) - inferred_sync_mgr = next(module.infer()) - module = inferred_sync_mgr.root() - self.assertEqual(module.name, 'multiprocessing.managers') - - def test_multiprocessing_manager(self): - # Test that we have the proper attributes - # for a multiprocessing.managers.SyncManager - module = builder.parse(""" - import multiprocessing - manager = multiprocessing.Manager() - queue = manager.Queue() - joinable_queue = manager.JoinableQueue() - event = manager.Event() - rlock = manager.RLock() - bounded_semaphore = manager.BoundedSemaphore() - condition = manager.Condition() - barrier = manager.Barrier() - pool = manager.Pool() - list = manager.list() - dict = manager.dict() - value = manager.Value() - array = manager.Array() - namespace = manager.Namespace() - """) - queue = next(module['queue'].infer()) - self.assertEqual(queue.qname(), - "{}.Queue".format(six.moves.queue.__name__)) - - joinable_queue = next(module['joinable_queue'].infer()) - self.assertEqual(joinable_queue.qname(), - "{}.Queue".format(six.moves.queue.__name__)) - - event = next(module['event'].infer()) - event_name = "threading.{}".format("Event" if six.PY3 else "_Event") - self.assertEqual(event.qname(), event_name) - - rlock = next(module['rlock'].infer()) - rlock_name = "threading._RLock" - self.assertEqual(rlock.qname(), rlock_name) - - bounded_semaphore = next(module['bounded_semaphore'].infer()) - semaphore_name = "threading.{}".format( - "BoundedSemaphore" if six.PY3 else "_BoundedSemaphore") - self.assertEqual(bounded_semaphore.qname(), semaphore_name) - - pool = next(module['pool'].infer()) - pool_name = "multiprocessing.pool.Pool" - self.assertEqual(pool.qname(), pool_name) - - for attr in ('list', 'dict'): - obj = next(module[attr].infer()) - self.assertEqual(obj.qname(), - "{}.{}".format(bases.BUILTINS, attr)) - - array = next(module['array'].infer()) - self.assertEqual(array.qname(), "array.array") - - manager = next(module['manager'].infer()) - # Verify that we have these attributes - self.assertTrue(manager.getattr('start')) - self.assertTrue(manager.getattr('shutdown')) - - -@unittest.skipUnless(HAS_ENUM, - 'The enum module was only added in Python 3.4. Support for ' - 'older Python versions may be available through the enum34 ' - 'compatibility module.') -class EnumBrainTest(unittest.TestCase): - - def test_simple_enum(self): - module = builder.parse(""" - import enum - - class MyEnum(enum.Enum): - one = "one" - two = "two" - - def mymethod(self, x): - return 5 - - """) - - enum = next(module['MyEnum'].infer()) - one = enum['one'] - self.assertEqual(one.pytype(), '.MyEnum.one') - - property_type = '{}.property'.format(bases.BUILTINS) - for propname in ('name', 'value'): - prop = next(iter(one.getattr(propname))) - self.assertIn(property_type, prop.decoratornames()) - - meth = one.getattr('mymethod')[0] - self.assertIsInstance(meth, astroid.FunctionDef) - - def test_looks_like_enum_false_positive(self): - # Test that a class named Enumeration is not considered a builtin enum. - module = builder.parse(''' - class Enumeration(object): - def __init__(self, name, enum_list): - pass - test = 42 - ''') - enum = module['Enumeration'] - test = next(enum.igetattr('test')) - self.assertEqual(test.value, 42) - - def test_enum_multiple_base_classes(self): - module = builder.parse(""" - import enum - - class Mixin: - pass - - class MyEnum(Mixin, enum.Enum): - one = 1 - """) - enum = next(module['MyEnum'].infer()) - one = enum['one'] - - clazz = one.getattr('__class__')[0] - self.assertTrue(clazz.is_subtype_of('.Mixin'), - 'Enum instance should share base classes with generating class') - - def test_int_enum(self): - module = builder.parse(""" - import enum - - class MyEnum(enum.IntEnum): - one = 1 - """) - - enum = next(module['MyEnum'].infer()) - one = enum['one'] - - clazz = one.getattr('__class__')[0] - int_type = '{}.{}'.format(bases.BUILTINS, 'int') - self.assertTrue(clazz.is_subtype_of(int_type), - 'IntEnum based enums should be a subtype of int') - - def test_enum_func_form_is_class_not_instance(self): - cls, instance = test_utils.extract_node(''' - from enum import Enum - f = Enum('Audience', ['a', 'b', 'c']) - f #@ - f(1) #@ - ''') - inferred_cls = next(cls.infer()) - self.assertIsInstance(inferred_cls, bases.Instance) - inferred_instance = next(instance.infer()) - self.assertIsInstance(inferred_instance, bases.Instance) - self.assertIsInstance(next(inferred_instance.igetattr('name')), nodes.Const) - self.assertIsInstance(next(inferred_instance.igetattr('value')), nodes.Const) - - -@unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.") -class DateutilBrainTest(unittest.TestCase): - def test_parser(self): - module = builder.parse(""" - from dateutil.parser import parse - d = parse('2000-01-01') - """) - d_type = next(module['d'].infer()) - self.assertEqual(d_type.qname(), "datetime.datetime") - - -@unittest.skipUnless(HAS_NUMPY, "This test requires the numpy library.") -class NumpyBrainTest(unittest.TestCase): - - def test_numpy(self): - node = test_utils.extract_node(''' - import numpy - numpy.ones #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.FunctionDef) - - -@unittest.skipUnless(HAS_PYTEST, "This test requires the pytest library.") -class PytestBrainTest(unittest.TestCase): - - def test_pytest(self): - ast_node = test_utils.extract_node(''' - import pytest - pytest #@ - ''') - module = next(ast_node.infer()) - attrs = ['deprecated_call', 'warns', 'exit', 'fail', 'skip', - 'importorskip', 'xfail', 'mark', 'raises', 'freeze_includes', - 'set_trace', 'fixture', 'yield_fixture'] - if pytest.__version__.split('.')[0] == '3': - attrs += ['approx', 'register_assert_rewrite'] - - for attr in attrs: - self.assertIn(attr, module) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_builder.py b/pymode/libs/astroid/tests/unittest_builder.py deleted file mode 100644 index 920f36e8..00000000 --- a/pymode/libs/astroid/tests/unittest_builder.py +++ /dev/null @@ -1,774 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""tests for the astroid builder and rebuilder module""" - -import os -import sys -import unittest - -import six - -from astroid import builder -from astroid import exceptions -from astroid import manager -from astroid import nodes -from astroid import test_utils -from astroid import util -from astroid.tests import resources - -MANAGER = manager.AstroidManager() -BUILTINS = six.moves.builtins.__name__ - - -class FromToLineNoTest(unittest.TestCase): - - def setUp(self): - self.astroid = resources.build_file('data/format.py') - - def test_callfunc_lineno(self): - stmts = self.astroid.body - # on line 4: - # function('aeozrijz\ - # earzer', hop) - discard = stmts[0] - self.assertIsInstance(discard, nodes.Expr) - self.assertEqual(discard.fromlineno, 4) - self.assertEqual(discard.tolineno, 5) - callfunc = discard.value - self.assertIsInstance(callfunc, nodes.Call) - self.assertEqual(callfunc.fromlineno, 4) - self.assertEqual(callfunc.tolineno, 5) - name = callfunc.func - self.assertIsInstance(name, nodes.Name) - self.assertEqual(name.fromlineno, 4) - self.assertEqual(name.tolineno, 4) - strarg = callfunc.args[0] - self.assertIsInstance(strarg, nodes.Const) - if hasattr(sys, 'pypy_version_info'): - lineno = 4 - else: - lineno = 5 # no way for this one in CPython (is 4 actually) - self.assertEqual(strarg.fromlineno, lineno) - self.assertEqual(strarg.tolineno, lineno) - namearg = callfunc.args[1] - self.assertIsInstance(namearg, nodes.Name) - self.assertEqual(namearg.fromlineno, 5) - self.assertEqual(namearg.tolineno, 5) - # on line 10: - # fonction(1, - # 2, - # 3, - # 4) - discard = stmts[2] - self.assertIsInstance(discard, nodes.Expr) - self.assertEqual(discard.fromlineno, 10) - self.assertEqual(discard.tolineno, 13) - callfunc = discard.value - self.assertIsInstance(callfunc, nodes.Call) - self.assertEqual(callfunc.fromlineno, 10) - self.assertEqual(callfunc.tolineno, 13) - name = callfunc.func - self.assertIsInstance(name, nodes.Name) - self.assertEqual(name.fromlineno, 10) - self.assertEqual(name.tolineno, 10) - for i, arg in enumerate(callfunc.args): - self.assertIsInstance(arg, nodes.Const) - self.assertEqual(arg.fromlineno, 10+i) - self.assertEqual(arg.tolineno, 10+i) - - def test_function_lineno(self): - stmts = self.astroid.body - # on line 15: - # def definition(a, - # b, - # c): - # return a + b + c - function = stmts[3] - self.assertIsInstance(function, nodes.FunctionDef) - self.assertEqual(function.fromlineno, 15) - self.assertEqual(function.tolineno, 18) - return_ = function.body[0] - self.assertIsInstance(return_, nodes.Return) - self.assertEqual(return_.fromlineno, 18) - self.assertEqual(return_.tolineno, 18) - if sys.version_info < (3, 0): - self.assertEqual(function.blockstart_tolineno, 17) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - def test_decorated_function_lineno(self): - astroid = builder.parse(''' - @decorator - def function( - arg): - print (arg) - ''', __name__) - function = astroid['function'] - self.assertEqual(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now - self.assertEqual(function.tolineno, 5) - self.assertEqual(function.decorators.fromlineno, 2) - self.assertEqual(function.decorators.tolineno, 2) - if sys.version_info < (3, 0): - self.assertEqual(function.blockstart_tolineno, 4) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - - def test_class_lineno(self): - stmts = self.astroid.body - # on line 20: - # class debile(dict, - # object): - # pass - class_ = stmts[4] - self.assertIsInstance(class_, nodes.ClassDef) - self.assertEqual(class_.fromlineno, 20) - self.assertEqual(class_.tolineno, 22) - self.assertEqual(class_.blockstart_tolineno, 21) - pass_ = class_.body[0] - self.assertIsInstance(pass_, nodes.Pass) - self.assertEqual(pass_.fromlineno, 22) - self.assertEqual(pass_.tolineno, 22) - - def test_if_lineno(self): - stmts = self.astroid.body - # on line 20: - # if aaaa: pass - # else: - # aaaa,bbbb = 1,2 - # aaaa,bbbb = bbbb,aaaa - if_ = stmts[5] - self.assertIsInstance(if_, nodes.If) - self.assertEqual(if_.fromlineno, 24) - self.assertEqual(if_.tolineno, 27) - self.assertEqual(if_.blockstart_tolineno, 24) - self.assertEqual(if_.orelse[0].fromlineno, 26) - self.assertEqual(if_.orelse[1].tolineno, 27) - - def test_for_while_lineno(self): - for code in (''' - for a in range(4): - print (a) - break - else: - print ("bouh") - ''', ''' - while a: - print (a) - break - else: - print ("bouh") - '''): - astroid = builder.parse(code, __name__) - stmt = astroid.body[0] - self.assertEqual(stmt.fromlineno, 2) - self.assertEqual(stmt.tolineno, 6) - self.assertEqual(stmt.blockstart_tolineno, 2) - self.assertEqual(stmt.orelse[0].fromlineno, 6) # XXX - self.assertEqual(stmt.orelse[0].tolineno, 6) - - def test_try_except_lineno(self): - astroid = builder.parse(''' - try: - print (a) - except: - pass - else: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 7) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.orelse[0].fromlineno, 7) # XXX - self.assertEqual(try_.orelse[0].tolineno, 7) - hdlr = try_.handlers[0] - self.assertEqual(hdlr.fromlineno, 4) - self.assertEqual(hdlr.tolineno, 5) - self.assertEqual(hdlr.blockstart_tolineno, 4) - - - def test_try_finally_lineno(self): - astroid = builder.parse(''' - try: - print (a) - finally: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 5) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.finalbody[0].fromlineno, 5) # XXX - self.assertEqual(try_.finalbody[0].tolineno, 5) - - - def test_try_finally_25_lineno(self): - astroid = builder.parse(''' - try: - print (a) - except: - pass - finally: - print ("bouh") - ''', __name__) - try_ = astroid.body[0] - self.assertEqual(try_.fromlineno, 2) - self.assertEqual(try_.tolineno, 7) - self.assertEqual(try_.blockstart_tolineno, 2) - self.assertEqual(try_.finalbody[0].fromlineno, 7) # XXX - self.assertEqual(try_.finalbody[0].tolineno, 7) - - - def test_with_lineno(self): - astroid = builder.parse(''' - from __future__ import with_statement - with file("/tmp/pouet") as f: - print (f) - ''', __name__) - with_ = astroid.body[1] - self.assertEqual(with_.fromlineno, 3) - self.assertEqual(with_.tolineno, 4) - self.assertEqual(with_.blockstart_tolineno, 3) - - -class BuilderTest(unittest.TestCase): - - def setUp(self): - self.builder = builder.AstroidBuilder() - - def test_data_build_null_bytes(self): - with self.assertRaises(exceptions.AstroidBuildingException): - self.builder.string_build('\x00') - - def test_data_build_invalid_x_escape(self): - with self.assertRaises(exceptions.AstroidBuildingException): - self.builder.string_build('"\\x1"') - - def test_missing_newline(self): - """check that a file with no trailing new line is parseable""" - resources.build_file('data/noendingnewline.py') - - def test_missing_file(self): - with self.assertRaises(exceptions.AstroidBuildingException): - resources.build_file('data/inexistant.py') - - def test_inspect_build0(self): - """test astroid tree build from a living object""" - builtin_ast = MANAGER.ast_from_module_name(BUILTINS) - if six.PY2: - fclass = builtin_ast['file'] - self.assertIn('name', fclass) - self.assertIn('mode', fclass) - self.assertIn('read', fclass) - self.assertTrue(fclass.newstyle) - self.assertTrue(fclass.pytype(), '%s.type' % BUILTINS) - self.assertIsInstance(fclass['read'], nodes.FunctionDef) - # check builtin function has args.args == None - dclass = builtin_ast['dict'] - self.assertIsNone(dclass['has_key'].args.args) - # just check type and object are there - builtin_ast.getattr('type') - objectastroid = builtin_ast.getattr('object')[0] - self.assertIsInstance(objectastroid.getattr('__new__')[0], nodes.FunctionDef) - # check open file alias - builtin_ast.getattr('open') - # check 'help' is there (defined dynamically by site.py) - builtin_ast.getattr('help') - # check property has __init__ - pclass = builtin_ast['property'] - self.assertIn('__init__', pclass) - self.assertIsInstance(builtin_ast['None'], nodes.Const) - self.assertIsInstance(builtin_ast['True'], nodes.Const) - self.assertIsInstance(builtin_ast['False'], nodes.Const) - if six.PY3: - self.assertIsInstance(builtin_ast['Exception'], nodes.ClassDef) - self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ClassDef) - else: - self.assertIsInstance(builtin_ast['Exception'], nodes.ImportFrom) - self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ImportFrom) - - def test_inspect_build1(self): - time_ast = MANAGER.ast_from_module_name('time') - self.assertTrue(time_ast) - self.assertEqual(time_ast['time'].args.defaults, []) - - if os.name == 'java': - test_inspect_build1 = unittest.expectedFailure(test_inspect_build1) - - def test_inspect_build2(self): - """test astroid tree build from a living object""" - try: - from mx import DateTime - except ImportError: - self.skipTest('test skipped: mxDateTime is not available') - else: - dt_ast = self.builder.inspect_build(DateTime) - dt_ast.getattr('DateTime') - # this one is failing since DateTimeType.__module__ = 'builtins' ! - #dt_ast.getattr('DateTimeType') - - def test_inspect_build3(self): - self.builder.inspect_build(unittest) - - @test_utils.require_version(maxver='3.0') - def test_inspect_build_instance(self): - """test astroid tree build from a living object""" - import exceptions - builtin_ast = self.builder.inspect_build(exceptions) - fclass = builtin_ast['OSError'] - # things like OSError.strerror are now (2.5) data descriptors on the - # class instead of entries in the __dict__ of an instance - container = fclass - self.assertIn('errno', container) - self.assertIn('strerror', container) - self.assertIn('filename', container) - - def test_inspect_build_type_object(self): - builtin_ast = MANAGER.ast_from_module_name(BUILTINS) - - inferred = list(builtin_ast.igetattr('object')) - self.assertEqual(len(inferred), 1) - inferred = inferred[0] - self.assertEqual(inferred.name, 'object') - inferred.as_string() # no crash test - - inferred = list(builtin_ast.igetattr('type')) - self.assertEqual(len(inferred), 1) - inferred = inferred[0] - self.assertEqual(inferred.name, 'type') - inferred.as_string() # no crash test - - def test_inspect_transform_module(self): - # ensure no cached version of the time module - MANAGER._mod_file_cache.pop(('time', None), None) - MANAGER.astroid_cache.pop('time', None) - def transform_time(node): - if node.name == 'time': - node.transformed = True - MANAGER.register_transform(nodes.Module, transform_time) - try: - time_ast = MANAGER.ast_from_module_name('time') - self.assertTrue(getattr(time_ast, 'transformed', False)) - finally: - MANAGER.unregister_transform(nodes.Module, transform_time) - - def test_package_name(self): - """test base properties and method of a astroid module""" - datap = resources.build_file('data/__init__.py', 'data') - self.assertEqual(datap.name, 'data') - self.assertEqual(datap.package, 1) - datap = resources.build_file('data/__init__.py', 'data.__init__') - self.assertEqual(datap.name, 'data') - self.assertEqual(datap.package, 1) - - def test_yield_parent(self): - """check if we added discard nodes as yield parent (w/ compiler)""" - code = """ - def yiell(): #@ - yield 0 - if noe: - yield more - """ - func = test_utils.extract_node(code) - self.assertIsInstance(func, nodes.FunctionDef) - stmt = func.body[0] - self.assertIsInstance(stmt, nodes.Expr) - self.assertIsInstance(stmt.value, nodes.Yield) - self.assertIsInstance(func.body[1].body[0], nodes.Expr) - self.assertIsInstance(func.body[1].body[0].value, nodes.Yield) - - def test_object(self): - obj_ast = self.builder.inspect_build(object) - self.assertIn('__setattr__', obj_ast) - - def test_newstyle_detection(self): - data = ''' - class A: - "old style" - - class B(A): - "old style" - - class C(object): - "new style" - - class D(C): - "new style" - - __metaclass__ = type - - class E(A): - "old style" - - class F: - "new style" - ''' - mod_ast = builder.parse(data, __name__) - if six.PY3: - self.assertTrue(mod_ast['A'].newstyle) - self.assertTrue(mod_ast['B'].newstyle) - self.assertTrue(mod_ast['E'].newstyle) - else: - self.assertFalse(mod_ast['A'].newstyle) - self.assertFalse(mod_ast['B'].newstyle) - self.assertFalse(mod_ast['E'].newstyle) - self.assertTrue(mod_ast['C'].newstyle) - self.assertTrue(mod_ast['D'].newstyle) - self.assertTrue(mod_ast['F'].newstyle) - - def test_globals(self): - data = ''' - CSTE = 1 - - def update_global(): - global CSTE - CSTE += 1 - - def global_no_effect(): - global CSTE2 - print (CSTE) - ''' - astroid = builder.parse(data, __name__) - self.assertEqual(len(astroid.getattr('CSTE')), 2) - self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssignName) - self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2) - self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6) - with self.assertRaises(exceptions.NotFoundError): - astroid.getattr('CSTE2') - with self.assertRaises(exceptions.InferenceError): - next(astroid['global_no_effect'].ilookup('CSTE2')) - - @unittest.skipIf(os.name == 'java', - 'This test is skipped on Jython, because the ' - 'socket object is patched later on with the ' - 'methods we are looking for. Since we do not ' - 'understand setattr in for loops yet, we skip this') - def test_socket_build(self): - import socket - astroid = self.builder.module_build(socket) - # XXX just check the first one. Actually 3 objects are inferred (look at - # the socket module) but the last one as those attributes dynamically - # set and astroid is missing this. - for fclass in astroid.igetattr('socket'): - self.assertIn('connect', fclass) - self.assertIn('send', fclass) - self.assertIn('close', fclass) - break - - def test_gen_expr_var_scope(self): - data = 'l = list(n for n in range(10))\n' - astroid = builder.parse(data, __name__) - # n unavailable outside gen expr scope - self.assertNotIn('n', astroid) - # test n is inferable anyway - n = test_utils.get_name_node(astroid, 'n') - self.assertIsNot(n.scope(), astroid) - self.assertEqual([i.__class__ for i in n.infer()], - [util.YES.__class__]) - - def test_no_future_imports(self): - mod = builder.parse("import sys") - self.assertEqual(set(), mod._future_imports) - - def test_future_imports(self): - mod = builder.parse("from __future__ import print_function") - self.assertEqual(set(['print_function']), mod._future_imports) - - def test_two_future_imports(self): - mod = builder.parse(""" - from __future__ import print_function - from __future__ import absolute_import - """) - self.assertEqual(set(['print_function', 'absolute_import']), mod._future_imports) - - def test_inferred_build(self): - code = ''' - class A: pass - A.type = "class" - - def A_assign_type(self): - print (self) - A.assign_type = A_assign_type - ''' - astroid = builder.parse(code) - lclass = list(astroid.igetattr('A')) - self.assertEqual(len(lclass), 1) - lclass = lclass[0] - self.assertIn('assign_type', lclass._locals) - self.assertIn('type', lclass._locals) - - def test_augassign_attr(self): - builder.parse(""" - class Counter: - v = 0 - def inc(self): - self.v += 1 - """, __name__) - # TODO: Check self.v += 1 generate AugAssign(AssAttr(...)), - # not AugAssign(GetAttr(AssName...)) - - def test_inferred_dont_pollute(self): - code = ''' - def func(a=None): - a.custom_attr = 0 - def func2(a={}): - a.custom_attr = 0 - ''' - builder.parse(code) - nonetype = nodes.const_factory(None) - self.assertNotIn('custom_attr', nonetype._locals) - self.assertNotIn('custom_attr', nonetype._instance_attrs) - nonetype = nodes.const_factory({}) - self.assertNotIn('custom_attr', nonetype._locals) - self.assertNotIn('custom_attr', nonetype._instance_attrs) - - def test_asstuple(self): - code = 'a, b = range(2)' - astroid = builder.parse(code) - self.assertIn('b', astroid._locals) - code = ''' - def visit_if(self, node): - node.test, body = node.tests[0] - ''' - astroid = builder.parse(code) - self.assertIn('body', astroid['visit_if']._locals) - - def test_build_constants(self): - '''test expected values of constants after rebuilding''' - code = ''' - def func(): - return None - return - return 'None' - ''' - astroid = builder.parse(code) - none, nothing, chain = [ret.value for ret in astroid.body[0].body] - self.assertIsInstance(none, nodes.Const) - self.assertIsNone(none.value) - self.assertIsNone(nothing) - self.assertIsInstance(chain, nodes.Const) - self.assertEqual(chain.value, 'None') - - def test_not_implemented(self): - node = test_utils.extract_node(''' - NotImplemented #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, NotImplemented) - - -class FileBuildTest(unittest.TestCase): - def setUp(self): - self.module = resources.build_file('data/module.py', 'data.module') - - def test_module_base_props(self): - """test base properties and method of a astroid module""" - module = self.module - self.assertEqual(module.name, 'data.module') - self.assertEqual(module.doc, "test module for astroid\n") - self.assertEqual(module.fromlineno, 0) - self.assertIsNone(module.parent) - self.assertEqual(module.frame(), module) - self.assertEqual(module.root(), module) - self.assertEqual(module.source_file, os.path.abspath(resources.find('data/module.py'))) - self.assertEqual(module.pure_python, 1) - self.assertEqual(module.package, 0) - self.assertFalse(module.is_statement) - self.assertEqual(module.statement(), module) - self.assertEqual(module.statement(), module) - - def test_module_locals(self): - """test the 'locals' dictionary of a astroid module""" - module = self.module - _locals = module._locals - self.assertIs(_locals, module._globals) - keys = sorted(_locals.keys()) - should = ['MY_DICT', 'NameNode', 'YO', 'YOUPI', - '__revision__', 'global_access', 'modutils', 'four_args', - 'os', 'redirect'] - should.sort() - self.assertEqual(keys, sorted(should)) - - def test_function_base_props(self): - """test base properties and method of a astroid function""" - module = self.module - function = module['global_access'] - self.assertEqual(function.name, 'global_access') - self.assertEqual(function.doc, 'function test') - self.assertEqual(function.fromlineno, 11) - self.assertTrue(function.parent) - self.assertEqual(function.frame(), function) - self.assertEqual(function.parent.frame(), module) - self.assertEqual(function.root(), module) - self.assertEqual([n.name for n in function.args.args], ['key', 'val']) - self.assertEqual(function.type, 'function') - - def test_function_locals(self): - """test the 'locals' dictionary of a astroid function""" - _locals = self.module['global_access']._locals - self.assertEqual(len(_locals), 4) - keys = sorted(_locals.keys()) - self.assertEqual(keys, ['i', 'key', 'local', 'val']) - - def test_class_base_props(self): - """test base properties and method of a astroid class""" - module = self.module - klass = module['YO'] - self.assertEqual(klass.name, 'YO') - self.assertEqual(klass.doc, 'hehe') - self.assertEqual(klass.fromlineno, 25) - self.assertTrue(klass.parent) - self.assertEqual(klass.frame(), klass) - self.assertEqual(klass.parent.frame(), module) - self.assertEqual(klass.root(), module) - self.assertEqual(klass.basenames, []) - if six.PY3: - self.assertTrue(klass.newstyle) - else: - self.assertFalse(klass.newstyle) - - def test_class_locals(self): - """test the 'locals' dictionary of a astroid class""" - module = self.module - klass1 = module['YO'] - locals1 = klass1._locals - keys = sorted(locals1.keys()) - self.assertEqual(keys, ['__init__', 'a']) - klass2 = module['YOUPI'] - locals2 = klass2._locals - keys = locals2.keys() - self.assertEqual(sorted(keys), - ['__init__', 'class_attr', 'class_method', - 'method', 'static_method']) - - def test_class_instance_attrs(self): - module = self.module - klass1 = module['YO'] - klass2 = module['YOUPI'] - self.assertEqual(list(klass1._instance_attrs.keys()), ['yo']) - self.assertEqual(list(klass2._instance_attrs.keys()), ['member']) - - def test_class_basenames(self): - module = self.module - klass1 = module['YO'] - klass2 = module['YOUPI'] - self.assertEqual(klass1.basenames, []) - self.assertEqual(klass2.basenames, ['YO']) - - def test_method_base_props(self): - """test base properties and method of a astroid method""" - klass2 = self.module['YOUPI'] - # "normal" method - method = klass2['method'] - self.assertEqual(method.name, 'method') - self.assertEqual([n.name for n in method.args.args], ['self']) - self.assertEqual(method.doc, 'method test') - self.assertEqual(method.fromlineno, 47) - self.assertEqual(method.type, 'method') - # class method - method = klass2['class_method'] - self.assertEqual([n.name for n in method.args.args], ['cls']) - self.assertEqual(method.type, 'classmethod') - # static method - method = klass2['static_method'] - self.assertEqual(method.args.args, []) - self.assertEqual(method.type, 'staticmethod') - - def test_method_locals(self): - """test the 'locals' dictionary of a astroid method""" - method = self.module['YOUPI']['method'] - _locals = method._locals - keys = sorted(_locals) - if sys.version_info < (3, 0): - self.assertEqual(len(_locals), 5) - self.assertEqual(keys, ['a', 'autre', 'b', 'local', 'self']) - else:# ListComp variables are no more accessible outside - self.assertEqual(len(_locals), 3) - self.assertEqual(keys, ['autre', 'local', 'self']) - - -class ModuleBuildTest(resources.SysPathSetup, FileBuildTest): - - def setUp(self): - super(ModuleBuildTest, self).setUp() - abuilder = builder.AstroidBuilder() - try: - import data.module - except ImportError: - # Make pylint happy. - self.skipTest('Unable to load data.module') - else: - self.module = abuilder.module_build(data.module, 'data.module') - -@unittest.skipIf(six.PY3, "guess_encoding not used on Python 3") -class TestGuessEncoding(unittest.TestCase): - def setUp(self): - self.guess_encoding = builder._guess_encoding - - def testEmacs(self): - e = self.guess_encoding('# -*- coding: UTF-8 -*-') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding('# -*- coding:UTF-8 -*-') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(''' - ### -*- coding: ISO-8859-1 -*- - ''') - self.assertEqual(e, 'ISO-8859-1') - e = self.guess_encoding(''' - - ### -*- coding: ISO-8859-1 -*- - ''') - self.assertIsNone(e) - - def testVim(self): - e = self.guess_encoding('# vim:fileencoding=UTF-8') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(''' - ### vim:fileencoding=ISO-8859-1 - ''') - self.assertEqual(e, 'ISO-8859-1') - e = self.guess_encoding(''' - - ### vim:fileencoding= ISO-8859-1 - ''') - self.assertIsNone(e) - - def test_wrong_coding(self): - # setting "coding" varaible - e = self.guess_encoding("coding = UTF-8") - self.assertIsNone(e) - # setting a dictionnary entry - e = self.guess_encoding("coding:UTF-8") - self.assertIsNone(e) - # setting an arguement - e = self.guess_encoding("def do_something(a_word_with_coding=None):") - self.assertIsNone(e) - - def testUTF8(self): - e = self.guess_encoding('\xef\xbb\xbf any UTF-8 data') - self.assertEqual(e, 'UTF-8') - e = self.guess_encoding(' any UTF-8 data \xef\xbb\xbf') - self.assertIsNone(e) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_inference.py b/pymode/libs/astroid/tests/unittest_inference.py deleted file mode 100644 index 86497727..00000000 --- a/pymode/libs/astroid/tests/unittest_inference.py +++ /dev/null @@ -1,2130 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""tests for the astroid inference capabilities -""" -import sys -from functools import partial -import unittest -import warnings - -import six - -from astroid import InferenceError, builder, nodes -from astroid.builder import parse -from astroid.inference import infer_end as inference_infer_end -from astroid.bases import Instance, BoundMethod, UnboundMethod,\ - path_wrapper, BUILTINS -from astroid import arguments -from astroid import objects -from astroid import test_utils -from astroid import util -from astroid.tests import resources - - -def get_node_of_class(start_from, klass): - return next(start_from.nodes_of_class(klass)) - -builder = builder.AstroidBuilder() - -if sys.version_info < (3, 0): - EXC_MODULE = 'exceptions' -else: - EXC_MODULE = BUILTINS - - -class InferenceUtilsTest(unittest.TestCase): - - def test_path_wrapper(self): - def infer_default(self, *args): - raise InferenceError - infer_default = path_wrapper(infer_default) - infer_end = path_wrapper(inference_infer_end) - with self.assertRaises(InferenceError): - next(infer_default(1)) - self.assertEqual(next(infer_end(1)), 1) - - -def _assertInferElts(node_type, self, node, elts): - inferred = next(node.infer()) - self.assertIsInstance(inferred, node_type) - self.assertEqual(sorted(elt.value for elt in inferred.elts), - elts) - -def partialmethod(func, arg): - """similar to functools.partial but return a lambda instead of a class so returned value may be - turned into a method. - """ - return lambda *args, **kwargs: func(arg, *args, **kwargs) - -class InferenceTest(resources.SysPathSetup, unittest.TestCase): - - # additional assertInfer* method for builtin types - - def assertInferConst(self, node, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected) - - def assertInferDict(self, node, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - - elts = set([(key.value, value.value) - for (key, value) in inferred.items]) - self.assertEqual(sorted(elts), sorted(expected.items())) - - assertInferTuple = partialmethod(_assertInferElts, nodes.Tuple) - assertInferList = partialmethod(_assertInferElts, nodes.List) - assertInferSet = partialmethod(_assertInferElts, nodes.Set) - assertInferFrozenSet = partialmethod(_assertInferElts, objects.FrozenSet) - - CODE = ''' - class C(object): - "new style" - attr = 4 - - def meth1(self, arg1, optarg=0): - var = object() - print ("yo", arg1, optarg) - self.iattr = "hop" - return var - - def meth2(self): - self.meth1(*self.meth3) - - def meth3(self, d=attr): - b = self.attr - c = self.iattr - return b, c - - ex = Exception("msg") - v = C().meth1(1) - m_unbound = C.meth1 - m_bound = C().meth1 - a, b, c = ex, 1, "bonjour" - [d, e, f] = [ex, 1.0, ("bonjour", v)] - g, h = f - i, (j, k) = "glup", f - - a, b= b, a # Gasp ! - ''' - - ast = parse(CODE, __name__) - - def test_infer_abstract_property_return_values(self): - module = parse(''' - import abc - - class A(object): - @abc.abstractproperty - def test(self): - return 42 - - a = A() - x = a.test - ''') - inferred = next(module['x'].infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_module_inference(self): - inferred = self.ast.infer() - obj = next(inferred) - self.assertEqual(obj.name, __name__) - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_class_inference(self): - inferred = self.ast['C'].infer() - obj = next(inferred) - self.assertEqual(obj.name, 'C') - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_function_inference(self): - inferred = self.ast['C']['meth1'].infer() - obj = next(inferred) - self.assertEqual(obj.name, 'meth1') - self.assertEqual(obj.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_builtin_name_inference(self): - inferred = self.ast['C']['meth1']['var'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_tupleassign_name_inference(self): - inferred = self.ast['a'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['b'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['c'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_listassign_name_inference(self): - inferred = self.ast['d'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['e'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1.0) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['f'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Tuple) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_advanced_tupleassign_name_inference1(self): - inferred = self.ast['g'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['h'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_advanced_tupleassign_name_inference2(self): - inferred = self.ast['i'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, u"glup") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['j'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "bonjour") - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast['k'].infer() - var = next(inferred) - self.assertEqual(var.name, 'object') - self.assertEqual(var.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_swap_assign_inference(self): - inferred = self.ast._locals['a'][1].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 1) - self.assertRaises(StopIteration, partial(next, inferred)) - inferred = self.ast._locals['b'][1].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference1(self): - inferred = self.ast['ex'].infer() - exc = next(inferred) - self.assertIsInstance(exc, Instance) - self.assertEqual(exc.name, 'Exception') - self.assertEqual(exc.root().name, EXC_MODULE) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference2(self): - inferred = get_node_of_class(self.ast['C']['meth2'], nodes.Attribute).infer() - meth1 = next(inferred) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.root().name, __name__) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference3(self): - inferred = self.ast['C']['meth3']['b'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, 4) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_getattr_inference4(self): - inferred = self.ast['C']['meth3']['c'].infer() - const = next(inferred) - self.assertIsInstance(const, nodes.Const) - self.assertEqual(const.value, "hop") - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_callfunc_inference(self): - inferred = self.ast['v'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, Instance) - self.assertEqual(meth1.name, 'object') - self.assertEqual(meth1.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_unbound_method_inference(self): - inferred = self.ast['m_unbound'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, UnboundMethod) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.parent.frame().name, 'C') - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_bound_method_inference(self): - inferred = self.ast['m_bound'].infer() - meth1 = next(inferred) - self.assertIsInstance(meth1, BoundMethod) - self.assertEqual(meth1.name, 'meth1') - self.assertEqual(meth1.parent.frame().name, 'C') - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_args_default_inference1(self): - optarg = test_utils.get_name_node(self.ast['C']['meth1'], 'optarg') - inferred = optarg.infer() - obj1 = next(inferred) - self.assertIsInstance(obj1, nodes.Const) - self.assertEqual(obj1.value, 0) - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_args_default_inference2(self): - inferred = self.ast['C']['meth3'].ilookup('d') - obj1 = next(inferred) - self.assertIsInstance(obj1, nodes.Const) - self.assertEqual(obj1.value, 4) - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_inference_restrictions(self): - inferred = test_utils.get_name_node(self.ast['C']['meth1'], 'arg1').infer() - obj1 = next(inferred) - self.assertIs(obj1, util.YES, obj1) - self.assertRaises(StopIteration, partial(next, inferred)) - - def test_ancestors_inference(self): - code = ''' - class A(object): #@ - pass - - class A(A): #@ - pass - ''' - a1, a2 = test_utils.extract_node(code, __name__) - a2_ancestors = list(a2.ancestors()) - self.assertEqual(len(a2_ancestors), 2) - self.assertIs(a2_ancestors[0], a1) - - def test_ancestors_inference2(self): - code = ''' - class A(object): #@ - pass - - class B(A): #@ - pass - - class A(B): #@ - pass - ''' - a1, b, a2 = test_utils.extract_node(code, __name__) - a2_ancestors = list(a2.ancestors()) - self.assertEqual(len(a2_ancestors), 3) - self.assertIs(a2_ancestors[0], b) - self.assertIs(a2_ancestors[1], a1) - - def test_f_arg_f(self): - code = ''' - def f(f=1): - return f - - a = f() - ''' - ast = parse(code, __name__) - a = ast['a'] - a_inferred = a.inferred() - self.assertEqual(a_inferred[0].value, 1) - self.assertEqual(len(a_inferred), 1) - - def test_infered_warning(self): - code = ''' - def f(f=1): - return f - - a = f() - ''' - ast = parse(code, __name__) - a = ast['a'] - - warnings.simplefilter('always') - with warnings.catch_warnings(record=True) as w: - a.infered() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - - def test_exc_ancestors(self): - code = ''' - def f(): - raise __(NotImplementedError) - ''' - error = test_utils.extract_node(code, __name__) - nie = error.inferred()[0] - self.assertIsInstance(nie, nodes.ClassDef) - nie_ancestors = [c.name for c in nie.ancestors()] - if sys.version_info < (3, 0): - self.assertEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object']) - else: - self.assertEqual(nie_ancestors, ['RuntimeError', 'Exception', 'BaseException', 'object']) - - def test_except_inference(self): - code = ''' - try: - print (hop) - except NameError as ex: - ex1 = ex - except Exception as ex: - ex2 = ex - raise - ''' - ast = parse(code, __name__) - ex1 = ast['ex1'] - ex1_infer = ex1.infer() - ex1 = next(ex1_infer) - self.assertIsInstance(ex1, Instance) - self.assertEqual(ex1.name, 'NameError') - self.assertRaises(StopIteration, partial(next, ex1_infer)) - ex2 = ast['ex2'] - ex2_infer = ex2.infer() - ex2 = next(ex2_infer) - self.assertIsInstance(ex2, Instance) - self.assertEqual(ex2.name, 'Exception') - self.assertRaises(StopIteration, partial(next, ex2_infer)) - - def test_del1(self): - code = ''' - del undefined_attr - ''' - delete = test_utils.extract_node(code, __name__) - self.assertRaises(InferenceError, delete.infer) - - def test_del2(self): - code = ''' - a = 1 - b = a - del a - c = a - a = 2 - d = a - ''' - ast = parse(code, __name__) - n = ast['b'] - n_infer = n.infer() - inferred = next(n_infer) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 1) - self.assertRaises(StopIteration, partial(next, n_infer)) - n = ast['c'] - n_infer = n.infer() - self.assertRaises(InferenceError, partial(next, n_infer)) - n = ast['d'] - n_infer = n.infer() - inferred = next(n_infer) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 2) - self.assertRaises(StopIteration, partial(next, n_infer)) - - def test_builtin_types(self): - code = ''' - l = [1] - t = (2,) - d = {} - s = '' - s2 = '_' - ''' - ast = parse(code, __name__) - n = ast['l'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.List) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.getitem(0).value, 1) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'list') - self.assertIn('append', inferred._proxied._locals) - n = ast['t'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.getitem(0).value, 2) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'tuple') - n = ast['d'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Dict) - self.assertIsInstance(inferred, Instance) - self.assertIsInstance(inferred._proxied, nodes.ClassDef) - self.assertEqual(inferred._proxied.name, 'dict') - self.assertIn('get', inferred._proxied._locals) - n = ast['s'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'str') - self.assertIn('lower', inferred._proxied._locals) - n = ast['s2'] - inferred = next(n.infer()) - self.assertEqual(inferred.getitem(0).value, '_') - - code = 's = {1}' - ast = parse(code, __name__) - n = ast['s'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Set) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'set') - self.assertIn('remove', inferred._proxied._locals) - - @test_utils.require_version(maxver='3.0') - def test_unicode_type(self): - code = '''u = u""''' - ast = parse(code, __name__) - n = ast['u'] - inferred = next(n.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'unicode') - self.assertIn('lower', inferred._proxied._locals) - - @unittest.expectedFailure - def test_descriptor_are_callable(self): - code = ''' - class A: - statm = staticmethod(open) - clsm = classmethod('whatever') - ''' - ast = parse(code, __name__) - statm = next(ast['A'].igetattr('statm')) - self.assertTrue(statm.callable()) - clsm = next(ast['A'].igetattr('clsm')) - self.assertFalse(clsm.callable()) - - def test_bt_ancestor_crash(self): - code = ''' - class Warning(Warning): - pass - ''' - ast = parse(code, __name__) - w = ast['Warning'] - ancestors = w.ancestors() - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'Warning') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'Exception') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'BaseException') - self.assertEqual(ancestor.root().name, EXC_MODULE) - ancestor = next(ancestors) - self.assertEqual(ancestor.name, 'object') - self.assertEqual(ancestor.root().name, BUILTINS) - self.assertRaises(StopIteration, partial(next, ancestors)) - - def test_qqch(self): - code = ''' - from astroid.modutils import load_module_from_name - xxx = load_module_from_name('__pkginfo__') - ''' - ast = parse(code, __name__) - xxx = ast['xxx'] - self.assertSetEqual({n.__class__ for n in xxx.inferred()}, - {nodes.Const, util.YES.__class__}) - - def test_method_argument(self): - code = ''' - class ErudiEntitySchema: - """a entity has a type, a set of subject and or object relations""" - def __init__(self, e_type, **kwargs): - kwargs['e_type'] = e_type.capitalize().encode() - - def meth(self, e_type, *args, **kwargs): - kwargs['e_type'] = e_type.capitalize().encode() - print(args) - ''' - ast = parse(code, __name__) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'e_type') - self.assertEqual([n.__class__ for n in arg.infer()], - [util.YES.__class__]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'kwargs') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Dict]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'e_type') - self.assertEqual([n.__class__ for n in arg.infer()], - [util.YES.__class__]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'args') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Tuple]) - arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'kwargs') - self.assertEqual([n.__class__ for n in arg.infer()], - [nodes.Dict]) - - def test_tuple_then_list(self): - code = ''' - def test_view(rql, vid, tags=()): - tags = list(tags) - __(tags).append(vid) - ''' - name = test_utils.extract_node(code, __name__) - it = name.infer() - tags = next(it) - self.assertIsInstance(tags, nodes.List) - self.assertEqual(tags.elts, []) - with self.assertRaises(StopIteration): - next(it) - - def test_mulassign_inference(self): - code = ''' - def first_word(line): - """Return the first word of a line""" - - return line.split()[0] - - def last_word(line): - """Return last word of a line""" - - return line.split()[-1] - - def process_line(word_pos): - """Silly function: returns (ok, callable) based on argument. - - For test purpose only. - """ - - if word_pos > 0: - return (True, first_word) - elif word_pos < 0: - return (True, last_word) - else: - return (False, None) - - if __name__ == '__main__': - - line_number = 0 - for a_line in file('test_callable.py'): - tupletest = process_line(line_number) - (ok, fct) = process_line(line_number) - if ok: - fct(a_line) - ''' - ast = parse(code, __name__) - self.assertEqual(len(list(ast['process_line'].infer_call_result(None))), 3) - self.assertEqual(len(list(ast['tupletest'].infer())), 3) - values = ['FunctionDef(first_word)', 'FunctionDef(last_word)', 'Const(NoneType)'] - self.assertEqual([str(inferred) - for inferred in ast['fct'].infer()], values) - - def test_float_complex_ambiguity(self): - code = ''' - def no_conjugate_member(magic_flag): #@ - """should not raise E1101 on something.conjugate""" - if magic_flag: - something = 1.0 - else: - something = 1.0j - if isinstance(something, float): - return something - return __(something).conjugate() - ''' - func, retval = test_utils.extract_node(code, __name__) - self.assertEqual( - [i.value for i in func.ilookup('something')], - [1.0, 1.0j]) - self.assertEqual( - [i.value for i in retval.infer()], - [1.0, 1.0j]) - - def test_lookup_cond_branches(self): - code = ''' - def no_conjugate_member(magic_flag): - """should not raise E1101 on something.conjugate""" - something = 1.0 - if magic_flag: - something = 1.0j - return something.conjugate() - ''' - ast = parse(code, __name__) - values = [i.value for i in test_utils.get_name_node(ast, 'something', -1).infer()] - self.assertEqual(values, [1.0, 1.0j]) - - - def test_simple_subscript(self): - code = ''' - class A(object): - def __getitem__(self, index): - return index + 42 - [1, 2, 3][0] #@ - (1, 2, 3)[1] #@ - (1, 2, 3)[-1] #@ - [1, 2, 3][0] + (2, )[0] + (3, )[-1] #@ - e = {'key': 'value'} - e['key'] #@ - "first"[0] #@ - list([1, 2, 3])[-1] #@ - tuple((4, 5, 6))[2] #@ - A()[0] #@ - A()[-1] #@ - ''' - ast_nodes = test_utils.extract_node(code, __name__) - expected = [1, 2, 3, 6, 'value', 'f', 3, 6, 42, 41] - for node, expected_value in zip(ast_nodes, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - def test_invalid_subscripts(self): - ast_nodes = test_utils.extract_node(''' - class NoGetitem(object): - pass - class InvalidGetitem(object): - def __getitem__(self): pass - class InvalidGetitem2(object): - __getitem__ = 42 - NoGetitem()[4] #@ - InvalidGetitem()[5] #@ - InvalidGetitem2()[10] #@ - [1, 2, 3][None] #@ - 'lala'['bala'] #@ - ''') - for node in ast_nodes[:3]: - self.assertRaises(InferenceError, next, node.infer()) - for node in ast_nodes[3:]: - self.assertEqual(next(node.infer()), util.YES) - - def test_bytes_subscript(self): - node = test_utils.extract_node('''b'a'[0]''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - if six.PY2: - self.assertEqual(inferred.value, 'a') - else: - self.assertEqual(inferred.value, 97) - - #def test_simple_tuple(self): - #"""test case for a simple tuple value""" - ## XXX tuple inference is not implemented ... - #code = """ -#a = (1,) -#b = (22,) -#some = a + b -#""" - #ast = builder.string_build(code, __name__, __file__) - #self.assertEqual(ast['some'].infer.next().as_string(), "(1, 22)") - - def test_simple_for(self): - code = ''' - for a in [1, 2, 3]: - print (a) - for b,c in [(1,2), (3,4)]: - print (b) - print (c) - - print ([(d,e) for e,d in ([1,2], [3,4])]) - ''' - ast = parse(code, __name__) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'a', -1).infer()], [1, 2, 3]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'b', -1).infer()], [1, 3]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'c', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3]) - - def test_simple_for_genexpr(self): - code = ''' - print ((d,e) for e,d in ([1,2], [3,4])) - ''' - ast = parse(code, __name__) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4]) - self.assertEqual([i.value for i in - test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3]) - - - def test_builtin_help(self): - code = ''' - help() - ''' - # XXX failing since __builtin__.help assignment has - # been moved into a function... - node = test_utils.extract_node(code, __name__) - inferred = list(node.func.infer()) - self.assertEqual(len(inferred), 1, inferred) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(inferred[0].name, "_Helper") - - def test_builtin_open(self): - code = ''' - open("toto.txt") - ''' - node = test_utils.extract_node(code, __name__).func - inferred = list(node.infer()) - self.assertEqual(len(inferred), 1) - if hasattr(sys, 'pypy_version_info'): - self.assertIsInstance(inferred[0], nodes.ClassDef) - self.assertEqual(inferred[0].name, 'file') - else: - self.assertIsInstance(inferred[0], nodes.FunctionDef) - self.assertEqual(inferred[0].name, 'open') - - def test_callfunc_context_func(self): - code = ''' - def mirror(arg=None): - return arg - - un = mirror(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('un')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 1) - - def test_callfunc_context_lambda(self): - code = ''' - mirror = lambda x=None: x - - un = mirror(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('mirror')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Lambda) - inferred = list(ast.igetattr('un')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 1) - - def test_factory_method(self): - code = ''' - class Super(object): - @classmethod - def instance(cls): - return cls() - - class Sub(Super): - def method(self): - print ('method called') - - sub = Sub.instance() - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('sub')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(inferred[0]._proxied.name, 'Sub') - - - def test_import_as(self): - code = ''' - import os.path as osp - print (osp.dirname(__file__)) - - from os.path import exists as e - assert e(__file__) - - from new import code as make_code - print (make_code) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('osp')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Module) - self.assertEqual(inferred[0].name, 'os.path') - inferred = list(ast.igetattr('e')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - self.assertEqual(inferred[0].name, 'exists') - if sys.version_info >= (3, 0): - self.skipTest(' module has been removed') - inferred = list(ast.igetattr('make_code')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], Instance) - self.assertEqual(str(inferred[0]), - 'Instance of %s.type' % BUILTINS) - - def _test_const_inferred(self, node, value): - inferred = list(node.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, value) - - def test_unary_not(self): - for code in ('a = not (1,); b = not ()', - 'a = not {1:2}; b = not {}'): - ast = builder.string_build(code, __name__, __file__) - self._test_const_inferred(ast['a'], False) - self._test_const_inferred(ast['b'], True) - - @test_utils.require_version(minver='3.5') - def test_matmul(self): - node = test_utils.extract_node(''' - class Array: - def __matmul__(self, other): - return 42 - Array() @ Array() #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_binary_op_int_add(self): - ast = builder.string_build('a = 1 + 2', __name__, __file__) - self._test_const_inferred(ast['a'], 3) - - def test_binary_op_int_sub(self): - ast = builder.string_build('a = 1 - 2', __name__, __file__) - self._test_const_inferred(ast['a'], -1) - - def test_binary_op_float_div(self): - ast = builder.string_build('a = 1 / 2.', __name__, __file__) - self._test_const_inferred(ast['a'], 1 / 2.) - - def test_binary_op_str_mul(self): - ast = builder.string_build('a = "*" * 40', __name__, __file__) - self._test_const_inferred(ast['a'], "*" * 40) - - def test_binary_op_bitand(self): - ast = builder.string_build('a = 23&20', __name__, __file__) - self._test_const_inferred(ast['a'], 23&20) - - def test_binary_op_bitor(self): - ast = builder.string_build('a = 23|8', __name__, __file__) - self._test_const_inferred(ast['a'], 23|8) - - def test_binary_op_bitxor(self): - ast = builder.string_build('a = 23^9', __name__, __file__) - self._test_const_inferred(ast['a'], 23^9) - - def test_binary_op_shiftright(self): - ast = builder.string_build('a = 23 >>1', __name__, __file__) - self._test_const_inferred(ast['a'], 23>>1) - - def test_binary_op_shiftleft(self): - ast = builder.string_build('a = 23 <<1', __name__, __file__) - self._test_const_inferred(ast['a'], 23<<1) - - - def test_binary_op_list_mul(self): - for code in ('a = [[]] * 2', 'a = 2 * [[]]'): - ast = builder.string_build(code, __name__, __file__) - inferred = list(ast['a'].infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.List) - self.assertEqual(len(inferred[0].elts), 2) - self.assertIsInstance(inferred[0].elts[0], nodes.List) - self.assertIsInstance(inferred[0].elts[1], nodes.List) - - def test_binary_op_list_mul_none(self): - 'test correct handling on list multiplied by None' - ast = builder.string_build('a = [1] * None\nb = [1] * "r"') - inferred = ast['a'].inferred() - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - inferred = ast['b'].inferred() - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - - def test_binary_op_list_mul_int(self): - 'test correct handling on list multiplied by int when there are more than one' - code = ''' - from ctypes import c_int - seq = [c_int()] * 4 - ''' - ast = parse(code, __name__) - inferred = ast['seq'].inferred() - self.assertEqual(len(inferred), 1) - listval = inferred[0] - self.assertIsInstance(listval, nodes.List) - self.assertEqual(len(listval.itered()), 4) - - def test_binary_op_tuple_add(self): - ast = builder.string_build('a = (1,) + (2,)', __name__, __file__) - inferred = list(ast['a'].infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Tuple) - self.assertEqual(len(inferred[0].elts), 2) - self.assertEqual(inferred[0].elts[0].value, 1) - self.assertEqual(inferred[0].elts[1].value, 2) - - def test_binary_op_custom_class(self): - code = ''' - class myarray: - def __init__(self, array): - self.array = array - def __mul__(self, x): - return myarray([2,4,6]) - def astype(self): - return "ASTYPE" - - def randint(maximum): - if maximum is not None: - return myarray([1,2,3]) * 2 - else: - return int(5) - - x = randint(1) - ''' - ast = parse(code, __name__) - inferred = list(ast.igetattr('x')) - self.assertEqual(len(inferred), 2) - value = [str(v) for v in inferred] - # The __name__ trick here makes it work when invoked directly - # (__name__ == '__main__') and through pytest (__name__ == - # 'unittest_inference') - self.assertEqual(value, ['Instance of %s.myarray' % __name__, - 'Instance of %s.int' % BUILTINS]) - - def test_nonregr_lambda_arg(self): - code = ''' - def f(g = lambda: None): - __(g()).x -''' - callfuncnode = test_utils.extract_node(code) - inferred = list(callfuncnode.infer()) - self.assertEqual(len(inferred), 2, inferred) - inferred.remove(util.YES) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertIsNone(inferred[0].value) - - def test_nonregr_getitem_empty_tuple(self): - code = ''' - def f(x): - a = ()[x] - ''' - ast = parse(code, __name__) - inferred = list(ast['f'].ilookup('a')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0], util.YES) - - def test_nonregr_instance_attrs(self): - """non regression for instance_attrs infinite loop : pylint / #4""" - - code = """ - class Foo(object): - - def set_42(self): - self.attr = 42 - - class Bar(Foo): - - def __init__(self): - self.attr = 41 - """ - ast = parse(code, __name__) - foo_class = ast['Foo'] - bar_class = ast['Bar'] - bar_self = ast['Bar']['__init__']['self'] - assattr = bar_class._instance_attrs['attr'][0] - self.assertEqual(len(foo_class._instance_attrs['attr']), 1) - self.assertEqual(len(bar_class._instance_attrs['attr']), 1) - self.assertEqual(bar_class._instance_attrs, {'attr': [assattr]}) - # call 'instance_attr' via 'Instance.getattr' to trigger the bug: - instance = bar_self.inferred()[0] - instance.getattr('attr') - self.assertEqual(len(bar_class._instance_attrs['attr']), 1) - self.assertEqual(len(foo_class._instance_attrs['attr']), 1) - self.assertEqual(bar_class._instance_attrs, {'attr': [assattr]}) - - def test_python25_generator_exit(self): - # pylint: disable=redefined-variable-type - buffer = six.StringIO() - sys.stderr = buffer - try: - data = "b = {}[str(0)+''].a" - ast = builder.string_build(data, __name__, __file__) - list(ast['b'].infer()) - output = buffer.getvalue() - finally: - sys.stderr = sys.__stderr__ - # I have no idea how to test for this in another way... - msg = ("Exception exceptions.RuntimeError: " - "'generator ignored GeneratorExit' in " - "ignored") - self.assertNotIn("RuntimeError", output, msg) - - def test_python25_no_relative_import(self): - ast = resources.build_file('data/package/absimport.py') - self.assertTrue(ast.absolute_import_activated(), True) - inferred = next(test_utils.get_name_node(ast, 'import_package_subpackage_module').infer()) - # failed to import since absolute_import is activated - self.assertIs(inferred, util.YES) - - def test_nonregr_absolute_import(self): - ast = resources.build_file('data/absimp/string.py', 'data.absimp.string') - self.assertTrue(ast.absolute_import_activated(), True) - inferred = next(test_utils.get_name_node(ast, 'string').infer()) - self.assertIsInstance(inferred, nodes.Module) - self.assertEqual(inferred.name, 'string') - self.assertIn('ascii_letters', inferred._locals) - - def test_mechanize_open(self): - try: - import mechanize # pylint: disable=unused-variable - except ImportError: - self.skipTest('require mechanize installed') - data = ''' - from mechanize import Browser - print(Browser) - b = Browser() - ''' - ast = parse(data, __name__) - browser = next(test_utils.get_name_node(ast, 'Browser').infer()) - self.assertIsInstance(browser, nodes.ClassDef) - bopen = list(browser.igetattr('open')) - self.skipTest('the commit said: "huum, see that later"') - self.assertEqual(len(bopen), 1) - self.assertIsInstance(bopen[0], nodes.FunctionDef) - self.assertTrue(bopen[0].callable()) - b = next(test_utils.get_name_node(ast, 'b').infer()) - self.assertIsInstance(b, Instance) - bopen = list(b.igetattr('open')) - self.assertEqual(len(bopen), 1) - self.assertIsInstance(bopen[0], BoundMethod) - self.assertTrue(bopen[0].callable()) - - def test_property(self): - code = ''' - from smtplib import SMTP - class SendMailController(object): - - @property - def smtp(self): - return SMTP(mailhost, port) - - @property - def me(self): - return self - - my_smtp = SendMailController().smtp - my_me = SendMailController().me - ''' - decorators = set(['%s.property' % BUILTINS]) - ast = parse(code, __name__) - self.assertEqual(ast['SendMailController']['smtp'].decoratornames(), - decorators) - propinferred = list(ast.body[2].value.infer()) - self.assertEqual(len(propinferred), 1) - propinferred = propinferred[0] - self.assertIsInstance(propinferred, Instance) - self.assertEqual(propinferred.name, 'SMTP') - self.assertEqual(propinferred.root().name, 'smtplib') - self.assertEqual(ast['SendMailController']['me'].decoratornames(), - decorators) - propinferred = list(ast.body[3].value.infer()) - self.assertEqual(len(propinferred), 1) - propinferred = propinferred[0] - self.assertIsInstance(propinferred, Instance) - self.assertEqual(propinferred.name, 'SendMailController') - self.assertEqual(propinferred.root().name, __name__) - - def test_im_func_unwrap(self): - code = ''' - class EnvBasedTC: - def pactions(self): - pass - pactions = EnvBasedTC.pactions.im_func - print (pactions) - - class EnvBasedTC2: - pactions = EnvBasedTC.pactions.im_func - print (pactions) - ''' - ast = parse(code, __name__) - pactions = test_utils.get_name_node(ast, 'pactions') - inferred = list(pactions.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - pactions = test_utils.get_name_node(ast['EnvBasedTC2'], 'pactions') - inferred = list(pactions.infer()) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - - def test_augassign(self): - code = ''' - a = 1 - a += 2 - print (a) - ''' - ast = parse(code, __name__) - inferred = list(test_utils.get_name_node(ast, 'a').infer()) - - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.Const) - self.assertEqual(inferred[0].value, 3) - - def test_nonregr_func_arg(self): - code = ''' - def foo(self, bar): - def baz(): - pass - def qux(): - return baz - spam = bar(None, qux) - print (spam) - ''' - ast = parse(code, __name__) - inferred = list(test_utils.get_name_node(ast['foo'], 'spam').infer()) - self.assertEqual(len(inferred), 1) - self.assertIs(inferred[0], util.YES) - - def test_nonregr_func_global(self): - code = ''' - active_application = None - - def get_active_application(): - global active_application - return active_application - - class Application(object): - def __init__(self): - global active_application - active_application = self - - class DataManager(object): - def __init__(self, app=None): - self.app = get_active_application() - def test(self): - p = self.app - print (p) - ''' - ast = parse(code, __name__) - inferred = list(Instance(ast['DataManager']).igetattr('app')) - self.assertEqual(len(inferred), 2, inferred) # None / Instance(Application) - inferred = list(test_utils.get_name_node(ast['DataManager']['test'], 'p').infer()) - self.assertEqual(len(inferred), 2, inferred) - for node in inferred: - if isinstance(node, Instance) and node.name == 'Application': - break - else: - self.fail('expected to find an instance of Application in %s' % inferred) - - def test_list_inference(self): - """#20464""" - code = ''' - from unknown import Unknown - A = [] - B = [] - - def test(): - xyz = [ - Unknown - ] + A + B - return xyz - - Z = test() - ''' - ast = parse(code, __name__) - inferred = next(ast['Z'].infer()) - self.assertIsInstance(inferred, nodes.List) - self.assertEqual(len(inferred.elts), 1) - self.assertIs(inferred.elts[0], util.YES) - - def test__new__(self): - code = ''' - class NewTest(object): - "doc" - def __new__(cls, arg): - self = object.__new__(cls) - self.arg = arg - return self - - n = NewTest() - ''' - ast = parse(code, __name__) - self.assertRaises(InferenceError, list, ast['NewTest'].igetattr('arg')) - n = next(ast['n'].infer()) - inferred = list(n.igetattr('arg')) - self.assertEqual(len(inferred), 1, inferred) - - def test__new__bound_methods(self): - node = test_utils.extract_node(''' - class cls(object): pass - cls().__new__(cls) #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred._proxied, node.root()['cls']) - - def test_two_parents_from_same_module(self): - code = ''' - from data import nonregr - class Xxx(nonregr.Aaa, nonregr.Ccc): - "doc" - ''' - ast = parse(code, __name__) - parents = list(ast['Xxx'].ancestors()) - self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object - - def test_pluggable_inference(self): - code = ''' - from collections import namedtuple - A = namedtuple('A', ['a', 'b']) - B = namedtuple('B', 'a b') - ''' - ast = parse(code, __name__) - aclass = ast['A'].inferred()[0] - self.assertIsInstance(aclass, nodes.ClassDef) - self.assertIn('a', aclass._instance_attrs) - self.assertIn('b', aclass._instance_attrs) - bclass = ast['B'].inferred()[0] - self.assertIsInstance(bclass, nodes.ClassDef) - self.assertIn('a', bclass._instance_attrs) - self.assertIn('b', bclass._instance_attrs) - - def test_infer_arguments(self): - code = ''' - class A(object): - def first(self, arg1, arg2): - return arg1 - @classmethod - def method(cls, arg1, arg2): - return arg2 - @classmethod - def empty(cls): - return 2 - @staticmethod - def static(arg1, arg2): - return arg1 - def empty_method(self): - return [] - x = A().first(1, []) - y = A.method(1, []) - z = A.static(1, []) - empty = A.empty() - empty_list = A().empty_method() - ''' - ast = parse(code, __name__) - int_node = ast['x'].inferred()[0] - self.assertIsInstance(int_node, nodes.Const) - self.assertEqual(int_node.value, 1) - list_node = ast['y'].inferred()[0] - self.assertIsInstance(list_node, nodes.List) - int_node = ast['z'].inferred()[0] - self.assertIsInstance(int_node, nodes.Const) - self.assertEqual(int_node.value, 1) - empty = ast['empty'].inferred()[0] - self.assertIsInstance(empty, nodes.Const) - self.assertEqual(empty.value, 2) - empty_list = ast['empty_list'].inferred()[0] - self.assertIsInstance(empty_list, nodes.List) - - def test_infer_variable_arguments(self): - code = ''' - def test(*args, **kwargs): - vararg = args - kwarg = kwargs - ''' - ast = parse(code, __name__) - func = ast['test'] - vararg = func.body[0].value - kwarg = func.body[1].value - - kwarg_inferred = kwarg.inferred()[0] - self.assertIsInstance(kwarg_inferred, nodes.Dict) - self.assertIs(kwarg_inferred.parent, func.args) - - vararg_inferred = vararg.inferred()[0] - self.assertIsInstance(vararg_inferred, nodes.Tuple) - self.assertIs(vararg_inferred.parent, func.args) - - def test_infer_nested(self): - code = """ - def nested(): - from threading import Thread - - class NestedThread(Thread): - def __init__(self): - Thread.__init__(self) - """ - # Test that inferring Thread.__init__ looks up in - # the nested scope. - ast = parse(code, __name__) - callfunc = next(ast.nodes_of_class(nodes.Call)) - func = callfunc.func - inferred = func.inferred()[0] - self.assertIsInstance(inferred, UnboundMethod) - - def test_instance_binary_operations(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - a = A() - b = A() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util.YES) - self.assertIsInstance(mul, nodes.Const) - self.assertEqual(mul.value, 42) - - def test_instance_binary_operations_parent(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - class B(A): - pass - a = B() - b = B() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util. YES) - self.assertIsInstance(mul, nodes.Const) - self.assertEqual(mul.value, 42) - - def test_instance_binary_operations_multiple_methods(self): - code = """ - class A(object): - def __mul__(self, other): - return 42 - class B(A): - def __mul__(self, other): - return [42] - a = B() - b = B() - sub = a - b - mul = a * b - """ - ast = parse(code, __name__) - sub = ast['sub'].inferred()[0] - mul = ast['mul'].inferred()[0] - self.assertIs(sub, util.YES) - self.assertIsInstance(mul, nodes.List) - self.assertIsInstance(mul.elts[0], nodes.Const) - self.assertEqual(mul.elts[0].value, 42) - - def test_infer_call_result_crash(self): - code = """ - class A(object): - def __mul__(self, other): - return type.__new__() - - a = A() - b = A() - c = a * b - """ - ast = parse(code, __name__) - node = ast['c'] - self.assertEqual(node.inferred(), [util.YES]) - - def test_infer_empty_nodes(self): - # Should not crash when trying to infer EmptyNodes. - node = nodes.EmptyNode() - self.assertEqual(node.inferred(), [util.YES]) - - def test_infinite_loop_for_decorators(self): - # Issue https://bitbucket.org/logilab/astroid/issue/50 - # A decorator that returns itself leads to an infinite loop. - code = """ - def decorator(): - def wrapper(): - return decorator() - return wrapper - - @decorator() - def do_a_thing(): - pass - """ - ast = parse(code, __name__) - node = ast['do_a_thing'] - self.assertEqual(node.type, 'function') - - def test_no_infinite_ancestor_loop(self): - klass = test_utils.extract_node(""" - import datetime - - def method(self): - datetime.datetime = something() - - class something(datetime.datetime): #@ - pass - """) - self.assertIn( - 'object', - [base.name for base in klass.ancestors()]) - - def test_stop_iteration_leak(self): - code = """ - class Test: - def __init__(self): - self.config = {0: self.config[0]} - self.config[0].test() #@ - """ - ast = test_utils.extract_node(code, __name__) - expr = ast.func.expr - self.assertRaises(InferenceError, next, expr.infer()) - - def test_tuple_builtin_inference(self): - code = """ - var = (1, 2) - tuple() #@ - tuple([1]) #@ - tuple({2}) #@ - tuple("abc") #@ - tuple({1: 2}) #@ - tuple(var) #@ - tuple(tuple([1])) #@ - - tuple(None) #@ - tuple(1) #@ - tuple(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferTuple(ast[0], []) - self.assertInferTuple(ast[1], [1]) - self.assertInferTuple(ast[2], [2]) - self.assertInferTuple(ast[3], ["a", "b", "c"]) - self.assertInferTuple(ast[4], [1]) - self.assertInferTuple(ast[5], [1, 2]) - self.assertInferTuple(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS)) - - def test_frozenset_builtin_inference(self): - code = """ - var = (1, 2) - frozenset() #@ - frozenset([1, 2, 1]) #@ - frozenset({2, 3, 1}) #@ - frozenset("abcab") #@ - frozenset({1: 2}) #@ - frozenset(var) #@ - frozenset(tuple([1])) #@ - - frozenset(set(tuple([4, 5, set([2])]))) #@ - frozenset(None) #@ - frozenset(1) #@ - frozenset(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferFrozenSet(ast[0], []) - self.assertInferFrozenSet(ast[1], [1, 2]) - self.assertInferFrozenSet(ast[2], [1, 2, 3]) - self.assertInferFrozenSet(ast[3], ["a", "b", "c"]) - self.assertInferFrozenSet(ast[4], [1]) - self.assertInferFrozenSet(ast[5], [1, 2]) - self.assertInferFrozenSet(ast[6], [1]) - - for node in ast[7:]: - infered = next(node.infer()) - self.assertIsInstance(infered, Instance) - self.assertEqual(infered.qname(), "{}.frozenset".format(BUILTINS)) - - def test_set_builtin_inference(self): - code = """ - var = (1, 2) - set() #@ - set([1, 2, 1]) #@ - set({2, 3, 1}) #@ - set("abcab") #@ - set({1: 2}) #@ - set(var) #@ - set(tuple([1])) #@ - - set(set(tuple([4, 5, set([2])]))) #@ - set(None) #@ - set(1) #@ - set(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - - self.assertInferSet(ast[0], []) - self.assertInferSet(ast[1], [1, 2]) - self.assertInferSet(ast[2], [1, 2, 3]) - self.assertInferSet(ast[3], ["a", "b", "c"]) - self.assertInferSet(ast[4], [1]) - self.assertInferSet(ast[5], [1, 2]) - self.assertInferSet(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.set".format(BUILTINS)) - - def test_list_builtin_inference(self): - code = """ - var = (1, 2) - list() #@ - list([1, 2, 1]) #@ - list({2, 3, 1}) #@ - list("abcab") #@ - list({1: 2}) #@ - list(var) #@ - list(tuple([1])) #@ - - list(list(tuple([4, 5, list([2])]))) #@ - list(None) #@ - list(1) #@ - list(1, 2) #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferList(ast[0], []) - self.assertInferList(ast[1], [1, 1, 2]) - self.assertInferList(ast[2], [1, 2, 3]) - self.assertInferList(ast[3], ["a", "a", "b", "b", "c"]) - self.assertInferList(ast[4], [1]) - self.assertInferList(ast[5], [1, 2]) - self.assertInferList(ast[6], [1]) - - for node in ast[7:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.list".format(BUILTINS)) - - @test_utils.require_version('3.0') - def test_builtin_inference_py3k(self): - code = """ - list(b"abc") #@ - tuple(b"abc") #@ - set(b"abc") #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferList(ast[0], [97, 98, 99]) - self.assertInferTuple(ast[1], [97, 98, 99]) - self.assertInferSet(ast[2], [97, 98, 99]) - - def test_dict_inference(self): - code = """ - dict() #@ - dict(a=1, b=2, c=3) #@ - dict([(1, 2), (2, 3)]) #@ - dict([[1, 2], [2, 3]]) #@ - dict([(1, 2), [2, 3]]) #@ - dict([('a', 2)], b=2, c=3) #@ - dict({1: 2}) #@ - dict({'c': 2}, a=4, b=5) #@ - def func(): - return dict(a=1, b=2) - func() #@ - var = {'x': 2, 'y': 3} - dict(var, a=1, b=2) #@ - - dict([1, 2, 3]) #@ - dict([(1, 2), (1, 2, 3)]) #@ - dict({1: 2}, {1: 2}) #@ - dict({1: 2}, (1, 2)) #@ - dict({1: 2}, (1, 2), a=4) #@ - dict([(1, 2), ([4, 5], 2)]) #@ - dict([None, None]) #@ - - def using_unknown_kwargs(**kwargs): - return dict(**kwargs) - using_unknown_kwargs(a=1, b=2) #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferDict(ast[0], {}) - self.assertInferDict(ast[1], {'a': 1, 'b': 2, 'c': 3}) - for i in range(2, 5): - self.assertInferDict(ast[i], {1: 2, 2: 3}) - self.assertInferDict(ast[5], {'a': 2, 'b': 2, 'c': 3}) - self.assertInferDict(ast[6], {1: 2}) - self.assertInferDict(ast[7], {'c': 2, 'a': 4, 'b': 5}) - self.assertInferDict(ast[8], {'a': 1, 'b': 2}) - self.assertInferDict(ast[9], {'x': 2, 'y': 3, 'a': 1, 'b': 2}) - - for node in ast[10:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS)) - - def test_dict_inference_kwargs(self): - ast_node = test_utils.extract_node('''dict(a=1, b=2, **{'c': 3})''') - self.assertInferDict(ast_node, {'a': 1, 'b': 2, 'c': 3}) - - @test_utils.require_version('3.5') - def test_dict_inference_for_multiple_starred(self): - pairs = [ - ('dict(a=1, **{"b": 2}, **{"c":3})', {'a':1, 'b':2, 'c':3}), - ('dict(a=1, **{"b": 2}, d=4, **{"c":3})', {'a':1, 'b':2, 'c':3, 'd':4}), - ('dict({"a":1}, b=2, **{"c":3})', {'a':1, 'b':2, 'c':3}), - ] - for code, expected_value in pairs: - node = test_utils.extract_node(code) - self.assertInferDict(node, expected_value) - - def test_dict_invalid_args(self): - invalid_values = [ - 'dict(*1)', - 'dict(**lala)', - 'dict(**[])', - ] - for invalid in invalid_values: - ast_node = test_utils.extract_node(invalid) - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS)) - - def test_str_methods(self): - code = """ - ' '.decode() #@ - - ' '.encode() #@ - ' '.join('abcd') #@ - ' '.replace('a', 'b') #@ - ' '.format('a') #@ - ' '.capitalize() #@ - ' '.title() #@ - ' '.lower() #@ - ' '.upper() #@ - ' '.swapcase() #@ - ' '.strip() #@ - ' '.rstrip() #@ - ' '.lstrip() #@ - ' '.rjust() #@ - ' '.ljust() #@ - ' '.center() #@ - - ' '.index() #@ - ' '.find() #@ - ' '.count() #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferConst(ast[0], u'') - for i in range(1, 16): - self.assertInferConst(ast[i], '') - for i in range(16, 19): - self.assertInferConst(ast[i], 0) - - def test_unicode_methods(self): - code = """ - u' '.encode() #@ - - u' '.decode() #@ - u' '.join('abcd') #@ - u' '.replace('a', 'b') #@ - u' '.format('a') #@ - u' '.capitalize() #@ - u' '.title() #@ - u' '.lower() #@ - u' '.upper() #@ - u' '.swapcase() #@ - u' '.strip() #@ - u' '.rstrip() #@ - u' '.lstrip() #@ - u' '.rjust() #@ - u' '.ljust() #@ - u' '.center() #@ - - u' '.index() #@ - u' '.find() #@ - u' '.count() #@ - """ - ast = test_utils.extract_node(code, __name__) - self.assertInferConst(ast[0], '') - for i in range(1, 16): - self.assertInferConst(ast[i], u'') - for i in range(16, 19): - self.assertInferConst(ast[i], 0) - - def test_scope_lookup_same_attributes(self): - code = ''' - import collections - class Second(collections.Counter): - def collections(self): - return "second" - - ''' - ast = parse(code, __name__) - bases = ast['Second'].bases[0] - inferred = next(bases.infer()) - self.assertTrue(inferred) - self.assertIsInstance(inferred, nodes.ClassDef) - self.assertEqual(inferred.qname(), 'collections.Counter') - - -class ArgumentsTest(unittest.TestCase): - - @staticmethod - def _get_dict_value(inferred): - items = inferred.items - return sorted((key.value, value.value) for key, value in items) - - @staticmethod - def _get_tuple_value(inferred): - elts = inferred.elts - return tuple(elt.value for elt in elts) - - def test_args(self): - expected_values = [(), (1, ), (2, 3), (4, 5), - (3, ), (), (3, 4, 5), - (), (), (4, ), (4, 5), - (), (3, ), (), (), (3, ), (42, )] - ast_nodes = test_utils.extract_node(''' - def func(*args): - return args - func() #@ - func(1) #@ - func(2, 3) #@ - func(*(4, 5)) #@ - def func(a, b, *args): - return args - func(1, 2, 3) #@ - func(1, 2) #@ - func(1, 2, 3, 4, 5) #@ - def func(a, b, c=42, *args): - return args - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, 3, 4) #@ - func(1, 2, 3, 4, 5) #@ - func = lambda a, b, *args: args - func(1, 2) #@ - func(1, 2, 3) #@ - func = lambda a, b=42, *args: args - func(1) #@ - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, *(42, )) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertEqual(self._get_tuple_value(inferred), expected_value) - - @test_utils.require_version('3.5') - def test_multiple_starred_args(self): - expected_values = [ - (1, 2, 3), - (1, 4, 2, 3, 5, 6, 7), - ] - ast_nodes = test_utils.extract_node(''' - def func(a, b, *args): - return args - func(1, 2, *(1, ), *(2, 3)) #@ - func(1, 2, *(1, ), 4, *(2, 3), 5, *(6, 7)) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertEqual(self._get_tuple_value(inferred), expected_value) - - def test_defaults(self): - expected_values = [42, 3, 41, 42] - ast_nodes = test_utils.extract_node(''' - def func(a, b, c=42, *args): - return c - func(1, 2) #@ - func(1, 2, 3) #@ - func(1, 2, c=41) #@ - func(1, 2, 42, 41) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - @test_utils.require_version('3.0') - def test_kwonly_args(self): - expected_values = [24, 24, 42, 23, 24, 24, 54] - ast_nodes = test_utils.extract_node(''' - def test(*, f, b): return f - test(f=24, b=33) #@ - def test(a, *, f): return f - test(1, f=24) #@ - def test(a, *, f=42): return f - test(1) #@ - test(1, f=23) #@ - def test(a, b, c=42, *args, f=24): - return f - test(1, 2, 3) #@ - test(1, 2, 3, 4) #@ - test(1, 2, 3, 4, 5, f=54) #@ - ''') - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, expected_value) - - def test_kwargs(self): - expected = [ - [('a', 1), ('b', 2), ('c', 3)], - [('a', 1)], - [('a', 'b')], - ] - ast_nodes = test_utils.extract_node(''' - def test(**kwargs): - return kwargs - test(a=1, b=2, c=3) #@ - test(a=1) #@ - test(**{'a': 'b'}) #@ - ''') - for node, expected_value in zip(ast_nodes, expected): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_and_other_named_parameters(self): - ast_nodes = test_utils.extract_node(''' - def test(a=42, b=24, **kwargs): - return kwargs - test(42, 24, c=3, d=4) #@ - test(49, b=24, d=4) #@ - test(a=42, b=33, c=3, d=42) #@ - test(a=42, **{'c':42}) #@ - ''') - expected_values = [ - [('c', 3), ('d', 4)], - [('d', 4)], - [('c', 3), ('d', 42)], - [('c', 42)], - ] - for node, expected_value in zip(ast_nodes, expected_values): - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_access_by_name(self): - expected_values = [42, 42, 42, 24] - ast_nodes = test_utils.extract_node(''' - def test(**kwargs): - return kwargs['f'] - test(f=42) #@ - test(**{'f': 42}) #@ - test(**dict(f=42)) #@ - def test(f=42, **kwargs): - return kwargs['l'] - test(l=24) #@ - ''') - for ast_node, value in zip(ast_nodes, expected_values): - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, value) - - def test_infer_call_result_invalid_dunder_call_on_instance(self): - ast_nodes = test_utils.extract_node(''' - class A: - __call__ = 42 - class B: - __call__ = A() - class C: - __call = None - A() #@ - B() #@ - C() #@ - ''') - for node in ast_nodes: - inferred = next(node.infer()) - self.assertRaises(InferenceError, next, inferred.infer_call_result(node)) - - - def test_subscript_inference_error(self): - # Used to raise StopIteration - ast_node = test_utils.extract_node(''' - class AttributeDict(dict): - def __getitem__(self, name): - return self - flow = AttributeDict() - flow['app'] = AttributeDict() - flow['app']['config'] = AttributeDict() - flow['app']['config']['doffing'] = AttributeDict() #@ - ''') - self.assertIsNone(util.safe_infer(ast_node.targets[0])) - - def test_classmethod_inferred_by_context(self): - ast_node = test_utils.extract_node(''' - class Super(object): - def instance(cls): - return cls() - instance = classmethod(instance) - - class Sub(Super): - def method(self): - return self - - # should see the Sub.instance() is returning a Sub - # instance, not a Super instance - Sub.instance().method() #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, Instance) - self.assertEqual(inferred.name, 'Sub') - - @test_utils.require_version('3.5') - def test_multiple_kwargs(self): - expected_value = [ - ('a', 1), - ('b', 2), - ('c', 3), - ('d', 4), - ('f', 42), - ] - ast_node = test_utils.extract_node(''' - def test(**kwargs): - return kwargs - test(a=1, b=2, **{'c': 3}, **{'d': 4}, f=42) #@ - ''') - inferred = next(ast_node.infer()) - self.assertIsInstance(inferred, nodes.Dict) - value = self._get_dict_value(inferred) - self.assertEqual(value, expected_value) - - def test_kwargs_are_overriden(self): - ast_nodes = test_utils.extract_node(''' - def test(f): - return f - test(f=23, **{'f': 34}) #@ - def test(f=None): - return f - test(f=23, **{'f':23}) #@ - ''') - for ast_node in ast_nodes: - inferred = next(ast_node.infer()) - self.assertEqual(inferred, util.YES) - - def test_fail_to_infer_args(self): - ast_nodes = test_utils.extract_node(''' - def test(a, **kwargs): return a - test(*missing) #@ - test(*object) #@ - test(*1) #@ - - - def test(**kwargs): return kwargs - test(**miss) #@ - test(**(1, 2)) #@ - test(**1) #@ - test(**{misss:1}) #@ - test(**{object:1}) #@ - test(**{1:1}) #@ - test(**{'a':1, 'a':1}) #@ - - def test(a): return a - test() #@ - test(1, 2, 3) #@ - - from unknown import unknown - test(*unknown) #@ - def test(*args): return args - test(*unknown) #@ - ''') - for node in ast_nodes: - inferred = next(node.infer()) - self.assertEqual(inferred, util.YES) - -class CallSiteTest(unittest.TestCase): - - @staticmethod - def _call_site_from_call(call): - return arguments.CallSite.from_call(call) - - def _test_call_site_pair(self, code, expected_args, expected_keywords): - ast_node = test_utils.extract_node(code) - call_site = self._call_site_from_call(ast_node) - self.assertEqual(len(call_site.positional_arguments), len(expected_args)) - self.assertEqual([arg.value for arg in call_site.positional_arguments], - expected_args) - self.assertEqual(len(call_site.keyword_arguments), len(expected_keywords)) - for keyword, value in expected_keywords.items(): - self.assertIn(keyword, call_site.keyword_arguments) - self.assertEqual(call_site.keyword_arguments[keyword].value, value) - - def _test_call_site(self, pairs): - for pair in pairs: - self._test_call_site_pair(*pair) - - @test_utils.require_version('3.5') - def test_call_site_starred_args(self): - pairs = [ - ( - "f(*(1, 2), *(2, 3), *(3, 4), **{'a':1}, **{'b': 2})", - [1, 2, 2, 3, 3, 4], - {'a': 1, 'b': 2} - ), - ( - "f(1, 2, *(3, 4), 5, *(6, 7), f=24, **{'c':3})", - [1, 2, 3, 4, 5, 6, 7], - {'f':24, 'c': 3}, - ), - # Too many fs passed into. - ( - "f(f=24, **{'f':24})", [], {}, - ), - ] - self._test_call_site(pairs) - - def test_call_site(self): - pairs = [ - ( - "f(1, 2)", [1, 2], {} - ), - ( - "f(1, 2, *(1, 2))", [1, 2, 1, 2], {} - ), - ( - "f(a=1, b=2, c=3)", [], {'a':1, 'b':2, 'c':3} - ) - ] - self._test_call_site(pairs) - - def _test_call_site_valid_arguments(self, values, invalid): - for value in values: - ast_node = test_utils.extract_node(value) - call_site = self._call_site_from_call(ast_node) - self.assertEqual(call_site.has_invalid_arguments(), invalid) - - def test_call_site_valid_arguments(self): - values = [ - "f(*lala)", "f(*1)", "f(*object)", - ] - self._test_call_site_valid_arguments(values, invalid=True) - values = [ - "f()", "f(*(1, ))", "f(1, 2, *(2, 3))", - ] - self._test_call_site_valid_arguments(values, invalid=False) - - def test_duplicated_keyword_arguments(self): - ast_node = test_utils.extract_node('f(f=24, **{"f": 25})') - site = self._call_site_from_call(ast_node) - self.assertIn('f', site.duplicated_keywords) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_lookup.py b/pymode/libs/astroid/tests/unittest_lookup.py deleted file mode 100644 index bd1786d5..00000000 --- a/pymode/libs/astroid/tests/unittest_lookup.py +++ /dev/null @@ -1,352 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""tests for the astroid variable lookup capabilities -""" -import functools -import sys -import unittest - -from astroid import builder -from astroid import exceptions -from astroid import nodes -from astroid import scoped_nodes -from astroid import test_utils -from astroid import util -from astroid.tests import resources - - -class LookupTest(resources.SysPathSetup, unittest.TestCase): - - def setUp(self): - super(LookupTest, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr') - - def test_limit(self): - code = ''' - l = [a - for a,b in list] - - a = 1 - b = a - a = None - - def func(): - c = 1 - ''' - astroid = builder.parse(code, __name__) - # a & b - a = next(astroid.nodes_of_class(nodes.Name)) - self.assertEqual(a.lineno, 2) - if sys.version_info < (3, 0): - self.assertEqual(len(astroid.lookup('b')[1]), 1) - self.assertEqual(len(astroid.lookup('a')[1]), 1) - b = astroid._locals['b'][1] - else: - self.assertEqual(len(astroid.lookup('b')[1]), 1) - self.assertEqual(len(astroid.lookup('a')[1]), 1) - b = astroid._locals['b'][0] - - stmts = a.lookup('a')[1] - self.assertEqual(len(stmts), 1) - self.assertEqual(b.lineno, 6) - b_infer = b.infer() - b_value = next(b_infer) - self.assertEqual(b_value.value, 1) - # c - self.assertRaises(StopIteration, functools.partial(next, b_infer)) - func = astroid._locals['func'][0] - self.assertEqual(len(func.lookup('c')[1]), 1) - - def test_module(self): - astroid = builder.parse('pass', __name__) - # built-in objects - none = next(astroid.ilookup('None')) - self.assertIsNone(none.value) - obj = next(astroid.ilookup('object')) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertEqual(obj.name, 'object') - self.assertRaises(exceptions.InferenceError, - functools.partial(next, astroid.ilookup('YOAA'))) - - # XXX - self.assertEqual(len(list(self.nonregr.ilookup('enumerate'))), 2) - - def test_class_ancestor_name(self): - code = ''' - class A: - pass - - class A(A): - pass - ''' - astroid = builder.parse(code, __name__) - cls1 = astroid._locals['A'][0] - cls2 = astroid._locals['A'][1] - name = next(cls2.nodes_of_class(nodes.Name)) - self.assertEqual(next(name.infer()), cls1) - - ### backport those test to inline code - def test_method(self): - method = self.module['YOUPI']['method'] - my_dict = next(method.ilookup('MY_DICT')) - self.assertTrue(isinstance(my_dict, nodes.Dict), my_dict) - none = next(method.ilookup('None')) - self.assertIsNone(none.value) - self.assertRaises(exceptions.InferenceError, - functools.partial(next, method.ilookup('YOAA'))) - - def test_function_argument_with_default(self): - make_class = self.module2['make_class'] - base = next(make_class.ilookup('base')) - self.assertTrue(isinstance(base, nodes.ClassDef), base.__class__) - self.assertEqual(base.name, 'YO') - self.assertEqual(base.root().name, 'data.module') - - def test_class(self): - klass = self.module['YOUPI'] - my_dict = next(klass.ilookup('MY_DICT')) - self.assertIsInstance(my_dict, nodes.Dict) - none = next(klass.ilookup('None')) - self.assertIsNone(none.value) - obj = next(klass.ilookup('object')) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertEqual(obj.name, 'object') - self.assertRaises(exceptions.InferenceError, - functools.partial(next, klass.ilookup('YOAA'))) - - def test_inner_classes(self): - ddd = list(self.nonregr['Ccc'].ilookup('Ddd')) - self.assertEqual(ddd[0].name, 'Ddd') - - def test_loopvar_hiding(self): - astroid = builder.parse(""" - x = 10 - for x in range(5): - print (x) - - if x > 0: - print ('#' * x) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x'] - # inside the loop, only one possible assignment - self.assertEqual(len(xnames[0].lookup('x')[1]), 1) - # outside the loop, two possible assignments - self.assertEqual(len(xnames[1].lookup('x')[1]), 2) - self.assertEqual(len(xnames[2].lookup('x')[1]), 2) - - def test_list_comps(self): - astroid = builder.parse(""" - print ([ i for i in range(10) ]) - print ([ i for i in range(10) ]) - print ( list( i for i in range(10) ) ) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - self.assertEqual(len(xnames[2].lookup('i')[1]), 1) - self.assertEqual(xnames[2].lookup('i')[1][0].lineno, 4) - - def test_list_comp_target(self): - """test the list comprehension target""" - astroid = builder.parse(""" - ten = [ var for var in range(10) ] - var - """) - var = astroid.body[1].value - if sys.version_info < (3, 0): - self.assertEqual(var.inferred(), [util.YES]) - else: - self.assertRaises(exceptions.UnresolvableName, var.inferred) - - def test_dict_comps(self): - astroid = builder.parse(""" - print ({ i: j for i in range(10) for j in range(10) }) - print ({ i: j for i in range(10) for j in range(10) }) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'j'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - def test_set_comps(self): - astroid = builder.parse(""" - print ({ i for i in range(10) }) - print ({ i for i in range(10) }) - """, __name__) - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i'] - self.assertEqual(len(xnames[0].lookup('i')[1]), 1) - self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2) - self.assertEqual(len(xnames[1].lookup('i')[1]), 1) - self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3) - - def test_set_comp_closure(self): - astroid = builder.parse(""" - ten = { var for var in range(10) } - var - """) - var = astroid.body[1].value - self.assertRaises(exceptions.UnresolvableName, var.inferred) - - def test_generator_attributes(self): - tree = builder.parse(""" - def count(): - "test" - yield 0 - - iterer = count() - num = iterer.next() - """) - next_node = tree.body[2].value.func - gener = next_node.expr.inferred()[0] - if sys.version_info < (3, 0): - self.assertIsInstance(gener.getattr('next')[0], nodes.FunctionDef) - else: - self.assertIsInstance(gener.getattr('__next__')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('send')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('throw')[0], nodes.FunctionDef) - self.assertIsInstance(gener.getattr('close')[0], nodes.FunctionDef) - - def test_explicit___name__(self): - code = ''' - class Pouet: - __name__ = "pouet" - p1 = Pouet() - - class PouetPouet(Pouet): pass - p2 = Pouet() - - class NoName: pass - p3 = NoName() - ''' - astroid = builder.parse(code, __name__) - p1 = next(astroid['p1'].infer()) - self.assertTrue(p1.getattr('__name__')) - p2 = next(astroid['p2'].infer()) - self.assertTrue(p2.getattr('__name__')) - self.assertTrue(astroid['NoName'].getattr('__name__')) - p3 = next(astroid['p3'].infer()) - self.assertRaises(exceptions.NotFoundError, p3.getattr, '__name__') - - def test_function_module_special(self): - astroid = builder.parse(''' - def initialize(linter): - """initialize linter with checkers in this package """ - package_load(linter, __path__[0]) - ''', 'data.__init__') - path = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == '__path__'][0] - self.assertEqual(len(path.lookup('__path__')[1]), 1) - - def test_builtin_lookup(self): - self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ()) - intstmts = scoped_nodes.builtin_lookup('int')[1] - self.assertEqual(len(intstmts), 1) - self.assertIsInstance(intstmts[0], nodes.ClassDef) - self.assertEqual(intstmts[0].name, 'int') - self.assertIs(intstmts[0], nodes.const_factory(1)._proxied) - - def test_decorator_arguments_lookup(self): - code = ''' - def decorator(value): - def wrapper(function): - return function - return wrapper - - class foo: - member = 10 #@ - - @decorator(member) #This will cause pylint to complain - def test(self): - pass - ''' - member = test_utils.extract_node(code, __name__).targets[0] - it = member.infer() - obj = next(it) - self.assertIsInstance(obj, nodes.Const) - self.assertEqual(obj.value, 10) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_inner_decorator_member_lookup(self): - code = ''' - class FileA: - def decorator(bla): - return bla - - @__(decorator) - def funcA(): - return 4 - ''' - decname = test_utils.extract_node(code, __name__) - it = decname.infer() - obj = next(it) - self.assertIsInstance(obj, nodes.FunctionDef) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_static_method_lookup(self): - code = ''' - class FileA: - @staticmethod - def funcA(): - return 4 - - - class Test: - FileA = [1,2,3] - - def __init__(self): - print (FileA.funcA()) - ''' - astroid = builder.parse(code, __name__) - it = astroid['Test']['__init__'].ilookup('FileA') - obj = next(it) - self.assertIsInstance(obj, nodes.ClassDef) - self.assertRaises(StopIteration, functools.partial(next, it)) - - def test_global_delete(self): - code = ''' - def run2(): - f = Frobble() - - class Frobble: - pass - Frobble.mumble = True - - del Frobble - - def run1(): - f = Frobble() - ''' - astroid = builder.parse(code, __name__) - stmts = astroid['run2'].lookup('Frobbel')[1] - self.assertEqual(len(stmts), 0) - stmts = astroid['run1'].lookup('Frobbel')[1] - self.assertEqual(len(stmts), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_manager.py b/pymode/libs/astroid/tests/unittest_manager.py deleted file mode 100644 index 452b759e..00000000 --- a/pymode/libs/astroid/tests/unittest_manager.py +++ /dev/null @@ -1,216 +0,0 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -import os -import platform -import sys -import unittest - -import six - -from astroid import exceptions -from astroid import manager -from astroid.tests import resources - - -BUILTINS = six.moves.builtins.__name__ - - -def _get_file_from_object(obj): - if platform.python_implementation() == 'Jython': - return obj.__file__.split("$py.class")[0] + ".py" - if sys.version_info > (3, 0): - return obj.__file__ - if not obj.__file__.endswith(".py"): - return obj.__file__[:-1] - return obj.__file__ - - -class AstroidManagerTest(resources.SysPathSetup, - resources.AstroidCacheSetupMixin, - unittest.TestCase): - - def setUp(self): - super(AstroidManagerTest, self).setUp() - self.manager = manager.AstroidManager() - self.manager.clear_cache(self._builtins) # take care of borg - - def test_ast_from_file(self): - filepath = unittest.__file__ - astroid = self.manager.ast_from_file(filepath) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_cache(self): - filepath = unittest.__file__ - self.manager.ast_from_file(filepath) - astroid = self.manager.ast_from_file('unhandledName', 'unittest') - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_astro_builder(self): - filepath = unittest.__file__ - astroid = self.manager.ast_from_file(filepath, None, True, True) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_file_name_astro_builder_exception(self): - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_file, 'unhandledName') - - def test_do_not_expose_main(self): - obj = self.manager.ast_from_module_name('__main__') - self.assertEqual(obj.name, '__main__') - self.assertEqual(obj.items(), []) - - def test_ast_from_module_name(self): - astroid = self.manager.ast_from_module_name('unittest') - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_module_name_not_python_source(self): - astroid = self.manager.ast_from_module_name('time') - self.assertEqual(astroid.name, 'time') - self.assertIn('time', self.manager.astroid_cache) - self.assertEqual(astroid.pure_python, False) - - def test_ast_from_module_name_astro_builder_exception(self): - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_module_name, - 'unhandledModule') - - def _test_ast_from_zip(self, archive): - origpath = sys.path[:] - sys.modules.pop('mypypa', None) - archive_path = resources.find(archive) - sys.path.insert(0, archive_path) - try: - module = self.manager.ast_from_module_name('mypypa') - self.assertEqual(module.name, 'mypypa') - end = os.path.join(archive, 'mypypa') - self.assertTrue(module.source_file.endswith(end), - "%s doesn't endswith %s" % (module.source_file, end)) - finally: - # remove the module, else after importing egg, we don't get the zip - if 'mypypa' in self.manager.astroid_cache: - del self.manager.astroid_cache['mypypa'] - del self.manager._mod_file_cache[('mypypa', None)] - if archive_path in sys.path_importer_cache: - del sys.path_importer_cache[archive_path] - sys.path = origpath - - def test_ast_from_module_name_egg(self): - self._test_ast_from_zip( - os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.egg')]) - ) - - def test_ast_from_module_name_zip(self): - self._test_ast_from_zip( - os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.zip')]) - ) - - def test_zip_import_data(self): - """check if zip_import_data works""" - filepath = resources.find('data/MyPyPa-0.1.0-py2.5.zip/mypypa') - astroid = self.manager.zip_import_data(filepath) - self.assertEqual(astroid.name, 'mypypa') - - def test_zip_import_data_without_zipimport(self): - """check if zip_import_data return None without zipimport""" - self.assertEqual(self.manager.zip_import_data('path'), None) - - def test_file_from_module(self): - """check if the unittest filepath is equals to the result of the method""" - self.assertEqual( - _get_file_from_object(unittest), - self.manager.file_from_module_name('unittest', None)[0]) - - def test_file_from_module_name_astro_building_exception(self): - """check if the method launch a exception with a wrong module name""" - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.file_from_module_name, 'unhandledModule', None) - - def test_ast_from_module(self): - astroid = self.manager.ast_from_module(unittest) - self.assertEqual(astroid.pure_python, True) - import time - astroid = self.manager.ast_from_module(time) - self.assertEqual(astroid.pure_python, False) - - def test_ast_from_module_cache(self): - """check if the module is in the cache manager""" - astroid = self.manager.ast_from_module(unittest) - self.assertEqual(astroid.name, 'unittest') - self.assertIn('unittest', self.manager.astroid_cache) - - def test_ast_from_class(self): - astroid = self.manager.ast_from_class(int) - self.assertEqual(astroid.name, 'int') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - - astroid = self.manager.ast_from_class(object) - self.assertEqual(astroid.name, 'object') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - self.assertIn('__setattr__', astroid) - - def test_ast_from_class_with_module(self): - """check if the method works with the module name""" - astroid = self.manager.ast_from_class(int, int.__module__) - self.assertEqual(astroid.name, 'int') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - - astroid = self.manager.ast_from_class(object, object.__module__) - self.assertEqual(astroid.name, 'object') - self.assertEqual(astroid.parent.frame().name, BUILTINS) - self.assertIn('__setattr__', astroid) - - def test_ast_from_class_attr_error(self): - """give a wrong class at the ast_from_class method""" - self.assertRaises(exceptions.AstroidBuildingException, - self.manager.ast_from_class, None) - - def testFailedImportHooks(self): - def hook(modname): - if modname == 'foo.bar': - return unittest - else: - raise exceptions.AstroidBuildingException() - - with self.assertRaises(exceptions.AstroidBuildingException): - self.manager.ast_from_module_name('foo.bar') - self.manager.register_failed_import_hook(hook) - self.assertEqual(unittest, self.manager.ast_from_module_name('foo.bar')) - with self.assertRaises(exceptions.AstroidBuildingException): - self.manager.ast_from_module_name('foo.bar.baz') - del self.manager._failed_import_hooks[0] - - -class BorgAstroidManagerTC(unittest.TestCase): - - def test_borg(self): - """test that the AstroidManager is really a borg, i.e. that two different - instances has same cache""" - first_manager = manager.AstroidManager() - built = first_manager.ast_from_module_name(BUILTINS) - - second_manager = manager.AstroidManager() - second_built = second_manager.ast_from_module_name(BUILTINS) - self.assertIs(built, second_built) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_modutils.py b/pymode/libs/astroid/tests/unittest_modutils.py deleted file mode 100644 index dffc3b8d..00000000 --- a/pymode/libs/astroid/tests/unittest_modutils.py +++ /dev/null @@ -1,269 +0,0 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) any -# later version. -# -# astroid 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 Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -""" -unit tests for module modutils (module manipulation utilities) -""" -import os -import sys -import unittest - -from astroid import modutils -from astroid.tests import resources - - -def _get_file_from_object(obj): - return modutils._path_from_filename(obj.__file__) - - -class ModuleFileTest(unittest.TestCase): - package = "mypypa" - - def tearDown(self): - for k in list(sys.path_importer_cache.keys()): - if 'MyPyPa' in k: - del sys.path_importer_cache[k] - - def test_find_zipped_module(self): - mtype, mfile = modutils._module_file( - [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.zip')]) - self.assertEqual(mtype, modutils.PY_ZIPMODULE) - self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.zip", self.package]) - - def test_find_egg_module(self): - mtype, mfile = modutils._module_file( - [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.egg')]) - self.assertEqual(mtype, modutils.PY_ZIPMODULE) - self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.egg", self.package]) - - -class LoadModuleFromNameTest(unittest.TestCase): - """ load a python module from it's name """ - - def test_knownValues_load_module_from_name_1(self): - self.assertEqual(modutils.load_module_from_name('sys'), sys) - - def test_knownValues_load_module_from_name_2(self): - self.assertEqual(modutils.load_module_from_name('os.path'), os.path) - - def test_raise_load_module_from_name_1(self): - self.assertRaises(ImportError, - modutils.load_module_from_name, 'os.path', use_sys=0) - - -class GetModulePartTest(unittest.TestCase): - """given a dotted name return the module part of the name""" - - def test_knownValues_get_module_part_1(self): - self.assertEqual(modutils.get_module_part('astroid.modutils'), - 'astroid.modutils') - - def test_knownValues_get_module_part_2(self): - self.assertEqual(modutils.get_module_part('astroid.modutils.get_module_part'), - 'astroid.modutils') - - def test_knownValues_get_module_part_3(self): - """relative import from given file""" - self.assertEqual(modutils.get_module_part('node_classes.AssName', - modutils.__file__), 'node_classes') - - def test_knownValues_get_compiled_module_part(self): - self.assertEqual(modutils.get_module_part('math.log10'), 'math') - self.assertEqual(modutils.get_module_part('math.log10', __file__), 'math') - - def test_knownValues_get_builtin_module_part(self): - self.assertEqual(modutils.get_module_part('sys.path'), 'sys') - self.assertEqual(modutils.get_module_part('sys.path', '__file__'), 'sys') - - def test_get_module_part_exception(self): - self.assertRaises(ImportError, modutils.get_module_part, 'unknown.module', - modutils.__file__) - - -class ModPathFromFileTest(unittest.TestCase): - """ given an absolute file path return the python module's path as a list """ - - def test_knownValues_modpath_from_file_1(self): - from xml.etree import ElementTree - self.assertEqual(modutils.modpath_from_file(ElementTree.__file__), - ['xml', 'etree', 'ElementTree']) - - def test_knownValues_modpath_from_file_2(self): - self.assertEqual(modutils.modpath_from_file('unittest_modutils.py', - {os.getcwd(): 'arbitrary.pkg'}), - ['arbitrary', 'pkg', 'unittest_modutils']) - - def test_raise_modpath_from_file_Exception(self): - self.assertRaises(Exception, modutils.modpath_from_file, '/turlututu') - - -class LoadModuleFromPathTest(resources.SysPathSetup, unittest.TestCase): - - def test_do_not_load_twice(self): - modutils.load_module_from_modpath(['data', 'lmfp', 'foo']) - modutils.load_module_from_modpath(['data', 'lmfp']) - self.assertEqual(len(sys.just_once), 1) - del sys.just_once - - -class FileFromModPathTest(resources.SysPathSetup, unittest.TestCase): - """given a mod path (i.e. splited module / package name), return the - corresponding file, giving priority to source file over precompiled file - if it exists""" - - def test_site_packages(self): - filename = _get_file_from_object(modutils) - result = modutils.file_from_modpath(['astroid', 'modutils']) - self.assertEqual(os.path.realpath(result), os.path.realpath(filename)) - - def test_std_lib(self): - from os import path - self.assertEqual(os.path.realpath(modutils.file_from_modpath(['os', 'path']).replace('.pyc', '.py')), - os.path.realpath(path.__file__.replace('.pyc', '.py'))) - - def test_xmlplus(self): - try: - # don't fail if pyxml isn't installed - from xml.dom import ext - except ImportError: - pass - else: - self.assertEqual(os.path.realpath(modutils.file_from_modpath(['xml', 'dom', 'ext']).replace('.pyc', '.py')), - os.path.realpath(ext.__file__.replace('.pyc', '.py'))) - - def test_builtin(self): - self.assertEqual(modutils.file_from_modpath(['sys']), - None) - - - def test_unexisting(self): - self.assertRaises(ImportError, modutils.file_from_modpath, ['turlututu']) - - def test_unicode_in_package_init(self): - # file_from_modpath should not crash when reading an __init__ - # file with unicode characters. - modutils.file_from_modpath(["data", "unicode_package", "core"]) - - -class GetSourceFileTest(unittest.TestCase): - - def test(self): - filename = _get_file_from_object(os.path) - self.assertEqual(modutils.get_source_file(os.path.__file__), - os.path.normpath(filename)) - - def test_raise(self): - self.assertRaises(modutils.NoSourceFile, modutils.get_source_file, 'whatever') - - -class StandardLibModuleTest(resources.SysPathSetup, unittest.TestCase): - """ - return true if the module may be considered as a module from the standard - library - """ - - def test_datetime(self): - # This is an interesting example, since datetime, on pypy, - # is under lib_pypy, rather than the usual Lib directory. - self.assertTrue(modutils.is_standard_module('datetime')) - - def test_builtins(self): - if sys.version_info < (3, 0): - self.assertEqual(modutils.is_standard_module('__builtin__'), True) - self.assertEqual(modutils.is_standard_module('builtins'), False) - else: - self.assertEqual(modutils.is_standard_module('__builtin__'), False) - self.assertEqual(modutils.is_standard_module('builtins'), True) - - def test_builtin(self): - self.assertEqual(modutils.is_standard_module('sys'), True) - self.assertEqual(modutils.is_standard_module('marshal'), True) - - def test_nonstandard(self): - self.assertEqual(modutils.is_standard_module('astroid'), False) - - def test_unknown(self): - self.assertEqual(modutils.is_standard_module('unknown'), False) - - def test_4(self): - self.assertEqual(modutils.is_standard_module('hashlib'), True) - self.assertEqual(modutils.is_standard_module('pickle'), True) - self.assertEqual(modutils.is_standard_module('email'), True) - self.assertEqual(modutils.is_standard_module('io'), sys.version_info >= (2, 6)) - self.assertEqual(modutils.is_standard_module('StringIO'), sys.version_info < (3, 0)) - self.assertEqual(modutils.is_standard_module('unicodedata'), True) - - def test_custom_path(self): - datadir = resources.find('') - if datadir.startswith(modutils.EXT_LIB_DIR): - self.skipTest('known breakage of is_standard_module on installed package') - self.assertEqual(modutils.is_standard_module('data.module', (datadir,)), True) - self.assertEqual(modutils.is_standard_module('data.module', (os.path.abspath(datadir),)), True) - - def test_failing_edge_cases(self): - from xml import etree - # using a subpackage/submodule path as std_path argument - self.assertEqual(modutils.is_standard_module('xml.etree', etree.__path__), False) - # using a module + object name as modname argument - self.assertEqual(modutils.is_standard_module('sys.path'), True) - # this is because only the first package/module is considered - self.assertEqual(modutils.is_standard_module('sys.whatever'), True) - self.assertEqual(modutils.is_standard_module('xml.whatever', etree.__path__), False) - - -class IsRelativeTest(unittest.TestCase): - - - def test_knownValues_is_relative_1(self): - import email - self.assertEqual(modutils.is_relative('utils', email.__path__[0]), - True) - - def test_knownValues_is_relative_2(self): - from xml.etree import ElementTree - self.assertEqual(modutils.is_relative('ElementPath', ElementTree.__file__), - True) - - def test_knownValues_is_relative_3(self): - import astroid - self.assertEqual(modutils.is_relative('astroid', astroid.__path__[0]), - False) - - -class GetModuleFilesTest(unittest.TestCase): - - def test_get_module_files_1(self): - package = resources.find('data/find_test') - modules = set(modutils.get_module_files(package, [])) - expected = ['__init__.py', 'module.py', 'module2.py', - 'noendingnewline.py', 'nonregr.py'] - self.assertEqual(modules, - {os.path.join(package, x) for x in expected}) - - def test_load_module_set_attribute(self): - import xml.etree.ElementTree - import xml - del xml.etree.ElementTree - del sys.modules['xml.etree.ElementTree'] - m = modutils.load_module_from_modpath(['xml', 'etree', 'ElementTree']) - self.assertTrue(hasattr(xml, 'etree')) - self.assertTrue(hasattr(xml.etree, 'ElementTree')) - self.assertTrue(m is xml.etree.ElementTree) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_nodes.py b/pymode/libs/astroid/tests/unittest_nodes.py deleted file mode 100644 index 6fa4b6f3..00000000 --- a/pymode/libs/astroid/tests/unittest_nodes.py +++ /dev/null @@ -1,764 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""tests for specific behaviour of astroid nodes -""" -import os -import sys -import textwrap -import unittest -import warnings - -import six - -from astroid import bases -from astroid import builder -from astroid import context as contextmod -from astroid import exceptions -from astroid import node_classes -from astroid import nodes -from astroid import parse -from astroid import util -from astroid import test_utils -from astroid import transforms -from astroid.tests import resources - - -abuilder = builder.AstroidBuilder() -BUILTINS = six.moves.builtins.__name__ - - -class AsStringTest(resources.SysPathSetup, unittest.TestCase): - - def test_tuple_as_string(self): - def build(string): - return abuilder.string_build(string).body[0].value - - self.assertEqual(build('1,').as_string(), '(1, )') - self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)') - self.assertEqual(build('(1, )').as_string(), '(1, )') - self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)') - - def test_as_string_for_list_containing_uninferable(self): - node = test_utils.extract_node(''' - def foo(arg): - bar = [arg] * 1 - ''') - binop = node.body[0].value - inferred = next(binop.infer()) - self.assertEqual(inferred.as_string(), '[Uninferable]') - self.assertEqual(binop.as_string(), '([arg]) * (1)') - - def test_frozenset_as_string(self): - nodes = test_utils.extract_node(''' - frozenset((1, 2, 3)) #@ - frozenset({1, 2, 3}) #@ - frozenset([1, 2, 3,]) #@ - - frozenset(None) #@ - frozenset(1) #@ - ''') - nodes = [next(node.infer()) for node in nodes] - - self.assertEqual(nodes[0].as_string(), 'frozenset((1, 2, 3))') - self.assertEqual(nodes[1].as_string(), 'frozenset({1, 2, 3})') - self.assertEqual(nodes[2].as_string(), 'frozenset([1, 2, 3])') - - self.assertNotEqual(nodes[3].as_string(), 'frozenset(None)') - self.assertNotEqual(nodes[4].as_string(), 'frozenset(1)') - - @test_utils.require_version(minver='3.0') - def test_func_signature_issue_185(self): - code = textwrap.dedent(''' - def test(a, b, c=42, *, x=42, **kwargs): - print(a, b, c, args) - ''') - node = parse(code) - self.assertEqual(node.as_string().strip(), code.strip()) - def test_varargs_kwargs_as_string(self): - ast = abuilder.string_build('raise_string(*args, **kwargs)').body[0] - self.assertEqual(ast.as_string(), 'raise_string(*args, **kwargs)') - - def test_module_as_string(self): - """check as_string on a whole module prepared to be returned identically - """ - module = resources.build_file('data/module.py', 'data.module') - with open(resources.find('data/module.py'), 'r') as fobj: - self.assertMultiLineEqual(module.as_string(), fobj.read()) - - def test_module2_as_string(self): - """check as_string on a whole module prepared to be returned identically - """ - module2 = resources.build_file('data/module2.py', 'data.module2') - with open(resources.find('data/module2.py'), 'r') as fobj: - self.assertMultiLineEqual(module2.as_string(), fobj.read()) - - def test_as_string(self): - """check as_string for python syntax >= 2.7""" - code = '''one_two = {1, 2} -b = {v: k for (k, v) in enumerate('string')} -cdd = {k for k in b}\n\n''' - ast = abuilder.string_build(code) - self.assertMultiLineEqual(ast.as_string(), code) - - @test_utils.require_version('3.0') - def test_3k_as_string(self): - """check as_string for python 3k syntax""" - code = '''print() - -def function(var): - nonlocal counter - try: - hello - except NameError as nexc: - (*hell, o) = b'hello' - raise AttributeError from nexc -\n''' - ast = abuilder.string_build(code) - self.assertEqual(ast.as_string(), code) - - @test_utils.require_version('3.0') - @unittest.expectedFailure - def test_3k_annotations_and_metaclass(self): - code_annotations = textwrap.dedent(''' - def function(var:int): - nonlocal counter - - class Language(metaclass=Natural): - """natural language""" - ''') - - ast = abuilder.string_build(code_annotations) - self.assertEqual(ast.as_string(), code_annotations) - - def test_ellipsis(self): - ast = abuilder.string_build('a[...]').body[0] - self.assertEqual(ast.as_string(), 'a[...]') - - def test_slices(self): - for code in ('a[0]', 'a[1:3]', 'a[:-1:step]', 'a[:,newaxis]', - 'a[newaxis,:]', 'del L[::2]', 'del A[1]', 'del Br[:]'): - ast = abuilder.string_build(code).body[0] - self.assertEqual(ast.as_string(), code) - - def test_slice_and_subscripts(self): - code = """a[:1] = bord[2:] -a[:1] = bord[2:] -del bree[3:d] -bord[2:] -del av[d::f], a[df:] -a[:1] = bord[2:] -del SRC[::1,newaxis,1:] -tous[vals] = 1010 -del thousand[key] -del a[::2], a[:-1:step] -del Fee.form[left:] -aout.vals = miles.of_stuff -del (ccok, (name.thing, foo.attrib.value)), Fee.form[left:] -if all[1] == bord[0:]: - pass\n\n""" - ast = abuilder.string_build(code) - self.assertEqual(ast.as_string(), code) - - -class _NodeTest(unittest.TestCase): - """test transformation of If Node""" - CODE = None - - @property - def astroid(self): - try: - return self.__class__.__dict__['CODE_Astroid'] - except KeyError: - astroid = builder.parse(self.CODE) - self.__class__.CODE_Astroid = astroid - return astroid - - -class IfNodeTest(_NodeTest): - """test transformation of If Node""" - CODE = """ - if 0: - print() - - if True: - print() - else: - pass - - if "": - print() - elif []: - raise - - if 1: - print() - elif True: - print() - elif func(): - pass - else: - raise - """ - - def test_if_elif_else_node(self): - """test transformation for If node""" - self.assertEqual(len(self.astroid.body), 4) - for stmt in self.astroid.body: - self.assertIsInstance(stmt, nodes.If) - self.assertFalse(self.astroid.body[0].orelse) # simple If - self.assertIsInstance(self.astroid.body[1].orelse[0], nodes.Pass) # If / else - self.assertIsInstance(self.astroid.body[2].orelse[0], nodes.If) # If / elif - self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], nodes.If) - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.block_range(1), (0, 22)) - self.assertEqual(self.astroid.block_range(10), (0, 22)) # XXX (10, 22) ? - self.assertEqual(self.astroid.body[1].block_range(5), (5, 6)) - self.assertEqual(self.astroid.body[1].block_range(6), (6, 6)) - self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8)) - self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8)) - - -class TryExceptNodeTest(_NodeTest): - CODE = """ - try: - print ('pouet') - except IOError: - pass - except UnicodeError: - print() - else: - print() - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 8)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 8)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - self.assertEqual(self.astroid.body[0].block_range(5), (5, 5)) - self.assertEqual(self.astroid.body[0].block_range(6), (6, 6)) - self.assertEqual(self.astroid.body[0].block_range(7), (7, 7)) - self.assertEqual(self.astroid.body[0].block_range(8), (8, 8)) - - -class TryFinallyNodeTest(_NodeTest): - CODE = """ - try: - print ('pouet') - finally: - print ('pouet') - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 4)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 4)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - - -class TryExceptFinallyNodeTest(_NodeTest): - CODE = """ - try: - print('pouet') - except Exception: - print ('oops') - finally: - print ('pouet') - """ - - def test_block_range(self): - # XXX ensure expected values - self.assertEqual(self.astroid.body[0].block_range(1), (1, 6)) - self.assertEqual(self.astroid.body[0].block_range(2), (2, 2)) - self.assertEqual(self.astroid.body[0].block_range(3), (3, 4)) - self.assertEqual(self.astroid.body[0].block_range(4), (4, 4)) - self.assertEqual(self.astroid.body[0].block_range(5), (5, 5)) - self.assertEqual(self.astroid.body[0].block_range(6), (6, 6)) - - -@unittest.skipIf(six.PY3, "Python 2 specific test.") -class TryExcept2xNodeTest(_NodeTest): - CODE = """ - try: - hello - except AttributeError, (retval, desc): - pass - """ - - - def test_tuple_attribute(self): - handler = self.astroid.body[0].handlers[0] - self.assertIsInstance(handler.name, nodes.Tuple) - - -class ImportNodeTest(resources.SysPathSetup, unittest.TestCase): - def setUp(self): - super(ImportNodeTest, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - - def test_import_self_resolve(self): - myos = next(self.module2.igetattr('myos')) - self.assertTrue(isinstance(myos, nodes.Module), myos) - self.assertEqual(myos.name, 'os') - self.assertEqual(myos.qname(), 'os') - self.assertEqual(myos.pytype(), '%s.module' % BUILTINS) - - def test_from_self_resolve(self): - namenode = next(self.module.igetattr('NameNode')) - self.assertTrue(isinstance(namenode, nodes.ClassDef), namenode) - self.assertEqual(namenode.root().name, 'astroid.node_classes') - self.assertEqual(namenode.qname(), 'astroid.node_classes.Name') - self.assertEqual(namenode.pytype(), '%s.type' % BUILTINS) - abspath = next(self.module2.igetattr('abspath')) - self.assertTrue(isinstance(abspath, nodes.FunctionDef), abspath) - self.assertEqual(abspath.root().name, 'os.path') - self.assertEqual(abspath.qname(), 'os.path.abspath') - self.assertEqual(abspath.pytype(), '%s.function' % BUILTINS) - - def test_real_name(self): - from_ = self.module['NameNode'] - self.assertEqual(from_.real_name('NameNode'), 'Name') - imp_ = self.module['os'] - self.assertEqual(imp_.real_name('os'), 'os') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'os.path') - imp_ = self.module['NameNode'] - self.assertEqual(imp_.real_name('NameNode'), 'Name') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'Name') - imp_ = self.module2['YO'] - self.assertEqual(imp_.real_name('YO'), 'YO') - self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'data') - - def test_as_string(self): - ast = self.module['modutils'] - self.assertEqual(ast.as_string(), "from astroid import modutils") - ast = self.module['NameNode'] - self.assertEqual(ast.as_string(), "from astroid.node_classes import Name as NameNode") - ast = self.module['os'] - self.assertEqual(ast.as_string(), "import os.path") - code = """from . import here -from .. import door -from .store import bread -from ..cave import wine\n\n""" - ast = abuilder.string_build(code) - self.assertMultiLineEqual(ast.as_string(), code) - - def test_bad_import_inference(self): - # Explication of bug - '''When we import PickleError from nonexistent, a call to the infer - method of this From node will be made by unpack_infer. - inference.infer_from will try to import this module, which will fail and - raise a InferenceException (by mixins.do_import_module). The infer_name - will catch this exception and yield and YES instead. - ''' - - code = ''' - try: - from pickle import PickleError - except ImportError: - from nonexistent import PickleError - - try: - pass - except PickleError: - pass - ''' - astroid = builder.parse(code) - handler_type = astroid.body[1].handlers[0].type - - excs = list(node_classes.unpack_infer(handler_type)) - # The number of returned object can differ on Python 2 - # and Python 3. In one version, an additional item will - # be returned, from the _pickle module, which is not - # present in the other version. - self.assertIsInstance(excs[0], nodes.ClassDef) - self.assertEqual(excs[0].name, 'PickleError') - self.assertIs(excs[-1], util.YES) - - def test_absolute_import(self): - astroid = resources.build_file('data/absimport.py') - ctx = contextmod.InferenceContext() - # will fail if absolute import failed - ctx.lookupname = 'message' - next(astroid['message'].infer(ctx)) - ctx.lookupname = 'email' - m = next(astroid['email'].infer(ctx)) - self.assertFalse(m.source_file.startswith(os.path.join('data', 'email.py'))) - - def test_more_absolute_import(self): - astroid = resources.build_file('data/module1abs/__init__.py', 'data.module1abs') - self.assertIn('sys', astroid._locals) - - -class CmpNodeTest(unittest.TestCase): - def test_as_string(self): - ast = abuilder.string_build("a == 2").body[0] - self.assertEqual(ast.as_string(), "a == 2") - - -class ConstNodeTest(unittest.TestCase): - - def _test(self, value): - node = nodes.const_factory(value) - self.assertIsInstance(node._proxied, nodes.ClassDef) - self.assertEqual(node._proxied.name, value.__class__.__name__) - self.assertIs(node.value, value) - self.assertTrue(node._proxied.parent) - self.assertEqual(node._proxied.root().name, value.__class__.__module__) - - def test_none(self): - self._test(None) - - def test_bool(self): - self._test(True) - - def test_int(self): - self._test(1) - - def test_float(self): - self._test(1.0) - - def test_complex(self): - self._test(1.0j) - - def test_str(self): - self._test('a') - - def test_unicode(self): - self._test(u'a') - - -class NameNodeTest(unittest.TestCase): - def test_assign_to_True(self): - """test that True and False assignements don't crash""" - code = """ - True = False - def hello(False): - pass - del True - """ - if sys.version_info >= (3, 0): - with self.assertRaises(exceptions.AstroidBuildingException): - builder.parse(code) - else: - ast = builder.parse(code) - assign_true = ast['True'] - self.assertIsInstance(assign_true, nodes.AssignName) - self.assertEqual(assign_true.name, "True") - del_true = ast.body[2].targets[0] - self.assertIsInstance(del_true, nodes.DelName) - self.assertEqual(del_true.name, "True") - - -class ArgumentsNodeTC(unittest.TestCase): - def test_linenumbering(self): - ast = builder.parse(''' - def func(a, - b): pass - x = lambda x: None - ''') - self.assertEqual(ast['func'].args.fromlineno, 2) - self.assertFalse(ast['func'].args.is_statement) - xlambda = next(ast['x'].infer()) - self.assertEqual(xlambda.args.fromlineno, 4) - self.assertEqual(xlambda.args.tolineno, 4) - self.assertFalse(xlambda.args.is_statement) - if sys.version_info < (3, 0): - self.assertEqual(ast['func'].args.tolineno, 3) - else: - self.skipTest('FIXME http://bugs.python.org/issue10445 ' - '(no line number on function args)') - - def test_builtin_fromlineno_missing(self): - cls = test_utils.extract_node(''' - class Foo(Exception): #@ - pass - ''') - new = cls.getattr('__new__')[-1] - self.assertEqual(new.args.fromlineno, 0) - - -class UnboundMethodNodeTest(unittest.TestCase): - - def test_no_super_getattr(self): - # This is a test for issue - # https://bitbucket.org/logilab/astroid/issue/91, which tests - # that UnboundMethod doesn't call super when doing .getattr. - - ast = builder.parse(''' - class A(object): - def test(self): - pass - meth = A.test - ''') - node = next(ast['meth'].infer()) - with self.assertRaises(exceptions.NotFoundError): - node.getattr('__missssing__') - name = node.getattr('__name__')[0] - self.assertIsInstance(name, nodes.Const) - self.assertEqual(name.value, 'test') - - -class BoundMethodNodeTest(unittest.TestCase): - - def test_is_property(self): - ast = builder.parse(''' - import abc - - def cached_property(): - # Not a real decorator, but we don't care - pass - def reify(): - # Same as cached_property - pass - def lazy_property(): - pass - def lazyproperty(): - pass - def lazy(): pass - class A(object): - @property - def builtin_property(self): - return 42 - @abc.abstractproperty - def abc_property(self): - return 42 - @cached_property - def cached_property(self): return 42 - @reify - def reified(self): return 42 - @lazy_property - def lazy_prop(self): return 42 - @lazyproperty - def lazyprop(self): return 42 - def not_prop(self): pass - @lazy - def decorated_with_lazy(self): return 42 - - cls = A() - builtin_property = cls.builtin_property - abc_property = cls.abc_property - cached_p = cls.cached_property - reified = cls.reified - not_prop = cls.not_prop - lazy_prop = cls.lazy_prop - lazyprop = cls.lazyprop - decorated_with_lazy = cls.decorated_with_lazy - ''') - for prop in ('builtin_property', 'abc_property', 'cached_p', 'reified', - 'lazy_prop', 'lazyprop', 'decorated_with_lazy'): - inferred = next(ast[prop].infer()) - self.assertIsInstance(inferred, nodes.Const, prop) - self.assertEqual(inferred.value, 42, prop) - - inferred = next(ast['not_prop'].infer()) - self.assertIsInstance(inferred, bases.BoundMethod) - - -class AliasesTest(unittest.TestCase): - - def setUp(self): - self.transformer = transforms.TransformVisitor() - - def parse_transform(self, code): - module = parse(code, apply_transforms=False) - return self.transformer.visit(module) - - def test_aliases(self): - def test_from(node): - node.names = node.names + [('absolute_import', None)] - return node - - def test_class(node): - node.name = 'Bar' - return node - - def test_function(node): - node.name = 'another_test' - return node - - def test_callfunc(node): - if node.func.name == 'Foo': - node.func.name = 'Bar' - return node - - def test_assname(node): - if node.name == 'foo': - n = nodes.AssignName() - n.name = 'bar' - return n - def test_assattr(node): - if node.attrname == 'a': - node.attrname = 'b' - return node - - def test_getattr(node): - if node.attrname == 'a': - node.attrname = 'b' - return node - - def test_genexpr(node): - if node.elt.value == 1: - node.elt = nodes.Const(2) - return node - - self.transformer.register_transform(nodes.From, test_from) - self.transformer.register_transform(nodes.Class, test_class) - self.transformer.register_transform(nodes.Function, test_function) - self.transformer.register_transform(nodes.CallFunc, test_callfunc) - self.transformer.register_transform(nodes.AssName, test_assname) - self.transformer.register_transform(nodes.AssAttr, test_assattr) - self.transformer.register_transform(nodes.Getattr, test_getattr) - self.transformer.register_transform(nodes.GenExpr, test_genexpr) - - string = ''' - from __future__ import print_function - - class Foo: pass - - def test(a): return a - - foo = Foo() - foo.a = test(42) - foo.a - (1 for _ in range(0, 42)) - ''' - - module = self.parse_transform(string) - - self.assertEqual(len(module.body[0].names), 2) - self.assertIsInstance(module.body[0], nodes.ImportFrom) - self.assertEqual(module.body[1].name, 'Bar') - self.assertIsInstance(module.body[1], nodes.ClassDef) - self.assertEqual(module.body[2].name, 'another_test') - self.assertIsInstance(module.body[2], nodes.FunctionDef) - self.assertEqual(module.body[3].targets[0].name, 'bar') - self.assertIsInstance(module.body[3].targets[0], nodes.AssignName) - self.assertEqual(module.body[3].value.func.name, 'Bar') - self.assertIsInstance(module.body[3].value, nodes.Call) - self.assertEqual(module.body[4].targets[0].attrname, 'b') - self.assertIsInstance(module.body[4].targets[0], nodes.AssignAttr) - self.assertIsInstance(module.body[5], nodes.Expr) - self.assertEqual(module.body[5].value.attrname, 'b') - self.assertIsInstance(module.body[5].value, nodes.Attribute) - self.assertEqual(module.body[6].value.elt.value, 2) - self.assertIsInstance(module.body[6].value, nodes.GeneratorExp) - - @unittest.skipIf(six.PY3, "Python 3 doesn't have Repr nodes.") - def test_repr(self): - def test_backquote(node): - node.value.name = 'bar' - return node - - self.transformer.register_transform(nodes.Backquote, test_backquote) - - module = self.parse_transform('`foo`') - - self.assertEqual(module.body[0].value.value.name, 'bar') - self.assertIsInstance(module.body[0].value, nodes.Repr) - - -class DeprecationWarningsTest(unittest.TestCase): - def test_asstype_warnings(self): - string = ''' - class C: pass - c = C() - with warnings.catch_warnings(record=True) as w: - pass - ''' - module = parse(string) - filter_stmts_mixin = module.body[0] - assign_type_mixin = module.body[1].targets[0] - parent_assign_type_mixin = module.body[2] - - warnings.simplefilter('always') - - with warnings.catch_warnings(record=True) as w: - filter_stmts_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - with warnings.catch_warnings(record=True) as w: - assign_type_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - with warnings.catch_warnings(record=True) as w: - parent_assign_type_mixin.ass_type() - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - - def test_isinstance_warnings(self): - msg_format = ("%r is deprecated and slated for removal in astroid " - "2.0, use %r instead") - for cls in (nodes.Discard, nodes.Backquote, nodes.AssName, - nodes.AssAttr, nodes.Getattr, nodes.CallFunc, nodes.From): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - isinstance(42, cls) - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - actual_msg = msg_format % (cls.__class__.__name__, cls.__wrapped__.__name__) - self.assertEqual(str(w[0].message), actual_msg) - - -@test_utils.require_version('3.5') -class Python35AsyncTest(unittest.TestCase): - - def test_async_await_keywords(self): - async_def, async_for, async_with, await_node = test_utils.extract_node(''' - async def func(): #@ - async for i in range(10): #@ - f = __(await i) - async with test(): #@ - pass - ''') - self.assertIsInstance(async_def, nodes.AsyncFunctionDef) - self.assertIsInstance(async_for, nodes.AsyncFor) - self.assertIsInstance(async_with, nodes.AsyncWith) - self.assertIsInstance(await_node, nodes.Await) - self.assertIsInstance(await_node.value, nodes.Name) - - def _test_await_async_as_string(self, code): - ast_node = parse(code) - self.assertEqual(ast_node.as_string().strip(), code.strip()) - - def test_await_as_string(self): - code = textwrap.dedent(''' - async def function(): - await 42 - ''') - self._test_await_async_as_string(code) - - def test_asyncwith_as_string(self): - code = textwrap.dedent(''' - async def function(): - async with (42): - pass - ''') - self._test_await_async_as_string(code) - - def test_asyncfor_as_string(self): - code = textwrap.dedent(''' - async def function(): - async for i in range(10): - await 42 - ''') - self._test_await_async_as_string(code) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_objects.py b/pymode/libs/astroid/tests/unittest_objects.py deleted file mode 100644 index 62d3f4ff..00000000 --- a/pymode/libs/astroid/tests/unittest_objects.py +++ /dev/null @@ -1,530 +0,0 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . - -import unittest - -from astroid import bases -from astroid import exceptions -from astroid import nodes -from astroid import objects -from astroid import test_utils - - -class ObjectsTest(unittest.TestCase): - - def test_frozenset(self): - node = test_utils.extract_node(""" - frozenset({1: 2, 2: 3}) #@ - """) - infered = next(node.infer()) - self.assertIsInstance(infered, objects.FrozenSet) - - self.assertEqual(infered.pytype(), "%s.frozenset" % bases.BUILTINS) - - itered = infered.itered() - self.assertEqual(len(itered), 2) - self.assertIsInstance(itered[0], nodes.Const) - self.assertEqual([const.value for const in itered], [1, 2]) - - proxied = infered._proxied - self.assertEqual(infered.qname(), "%s.frozenset" % bases.BUILTINS) - self.assertIsInstance(proxied, nodes.ClassDef) - - -class SuperTests(unittest.TestCase): - - def test_inferring_super_outside_methods(self): - ast_nodes = test_utils.extract_node(''' - class Module(object): - pass - class StaticMethod(object): - @staticmethod - def static(): - # valid, but we don't bother with it. - return super(StaticMethod, StaticMethod) #@ - # super outside methods aren't inferred - super(Module, Module) #@ - # no argument super is not recognised outside methods as well. - super() #@ - ''') - in_static = next(ast_nodes[0].value.infer()) - self.assertIsInstance(in_static, bases.Instance) - self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS) - - module_level = next(ast_nodes[1].infer()) - self.assertIsInstance(module_level, bases.Instance) - self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS) - - no_arguments = next(ast_nodes[2].infer()) - self.assertIsInstance(no_arguments, bases.Instance) - self.assertEqual(no_arguments.qname(), "%s.super" % bases.BUILTINS) - - def test_inferring_unbound_super_doesnt_work(self): - node = test_utils.extract_node(''' - class Test(object): - def __init__(self): - super(Test) #@ - ''') - unbounded = next(node.infer()) - self.assertIsInstance(unbounded, bases.Instance) - self.assertEqual(unbounded.qname(), "%s.super" % bases.BUILTINS) - - def test_use_default_inference_on_not_inferring_args(self): - ast_nodes = test_utils.extract_node(''' - class Test(object): - def __init__(self): - super(Lala, self) #@ - super(Test, lala) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.Instance) - self.assertEqual(first.qname(), "%s.super" % bases.BUILTINS) - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.Instance) - self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS) - - @test_utils.require_version(maxver='3.0') - def test_super_on_old_style_class(self): - # super doesn't work on old style class, but leave - # that as an error for pylint. We'll infer Super objects, - # but every call will result in a failure at some point. - node = test_utils.extract_node(''' - class OldStyle: - def __init__(self): - super(OldStyle, self) #@ - ''') - old = next(node.infer()) - self.assertIsInstance(old, objects.Super) - self.assertIsInstance(old.mro_pointer, nodes.ClassDef) - self.assertEqual(old.mro_pointer.name, 'OldStyle') - with self.assertRaises(exceptions.SuperError) as cm: - old.super_mro() - self.assertEqual(str(cm.exception), - "Unable to call super on old-style classes.") - - @test_utils.require_version(minver='3.0') - def test_no_arguments_super(self): - ast_nodes = test_utils.extract_node(''' - class First(object): pass - class Second(First): - def test(self): - super() #@ - @classmethod - def test_classmethod(cls): - super() #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - self.assertIsInstance(first.type, bases.Instance) - self.assertEqual(first.type.name, 'Second') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(first.mro_pointer.name, 'Second') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, objects.Super) - self.assertIsInstance(second.type, nodes.ClassDef) - self.assertEqual(second.type.name, 'Second') - self.assertIsInstance(second.mro_pointer, nodes.ClassDef) - self.assertEqual(second.mro_pointer.name, 'Second') - - def test_super_simple_cases(self): - ast_nodes = test_utils.extract_node(''' - class First(object): pass - class Second(First): pass - class Third(First): - def test(self): - super(Third, self) #@ - super(Second, self) #@ - - # mro position and the type - super(Third, Third) #@ - super(Third, Second) #@ - super(Fourth, Fourth) #@ - - class Fourth(Third): - pass - ''') - - # .type is the object which provides the mro. - # .mro_pointer is the position in the mro from where - # the lookup should be done. - - # super(Third, self) - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - self.assertIsInstance(first.type, bases.Instance) - self.assertEqual(first.type.name, 'Third') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(first.mro_pointer.name, 'Third') - - # super(Second, self) - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, objects.Super) - self.assertIsInstance(second.type, bases.Instance) - self.assertEqual(second.type.name, 'Third') - self.assertIsInstance(first.mro_pointer, nodes.ClassDef) - self.assertEqual(second.mro_pointer.name, 'Second') - - # super(Third, Third) - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, objects.Super) - self.assertIsInstance(third.type, nodes.ClassDef) - self.assertEqual(third.type.name, 'Third') - self.assertIsInstance(third.mro_pointer, nodes.ClassDef) - self.assertEqual(third.mro_pointer.name, 'Third') - - # super(Third, second) - fourth = next(ast_nodes[3].infer()) - self.assertIsInstance(fourth, objects.Super) - self.assertIsInstance(fourth.type, nodes.ClassDef) - self.assertEqual(fourth.type.name, 'Second') - self.assertIsInstance(fourth.mro_pointer, nodes.ClassDef) - self.assertEqual(fourth.mro_pointer.name, 'Third') - - # Super(Fourth, Fourth) - fifth = next(ast_nodes[4].infer()) - self.assertIsInstance(fifth, objects.Super) - self.assertIsInstance(fifth.type, nodes.ClassDef) - self.assertEqual(fifth.type.name, 'Fourth') - self.assertIsInstance(fifth.mro_pointer, nodes.ClassDef) - self.assertEqual(fifth.mro_pointer.name, 'Fourth') - - def test_super_infer(self): - node = test_utils.extract_node(''' - class Super(object): - def __init__(self): - super(Super, self) #@ - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, objects.Super) - reinferred = next(inferred.infer()) - self.assertIsInstance(reinferred, objects.Super) - self.assertIs(inferred, reinferred) - - def test_inferring_invalid_supers(self): - ast_nodes = test_utils.extract_node(''' - class Super(object): - def __init__(self): - # MRO pointer is not a type - super(1, self) #@ - # MRO type is not a subtype - super(Super, 1) #@ - # self is not a subtype of Bupper - super(Bupper, self) #@ - class Bupper(Super): - pass - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, objects.Super) - with self.assertRaises(exceptions.SuperError) as cm: - first.super_mro() - self.assertEqual(str(cm.exception), "The first super argument must be type.") - - for node in ast_nodes[1:]: - inferred = next(node.infer()) - self.assertIsInstance(inferred, objects.Super, node) - with self.assertRaises(exceptions.SuperArgumentTypeError) as cm: - inferred.super_mro() - self.assertEqual(str(cm.exception), - "super(type, obj): obj must be an instance " - "or subtype of type", node) - - def test_proxied(self): - node = test_utils.extract_node(''' - class Super(object): - def __init__(self): - super(Super, self) #@ - ''') - infered = next(node.infer()) - proxied = infered._proxied - self.assertEqual(proxied.qname(), "%s.super" % bases.BUILTINS) - self.assertIsInstance(proxied, nodes.ClassDef) - - def test_super_bound_model(self): - ast_nodes = test_utils.extract_node(''' - class First(object): - def method(self): - pass - @classmethod - def class_method(cls): - pass - class Super_Type_Type(First): - def method(self): - super(Super_Type_Type, Super_Type_Type).method #@ - super(Super_Type_Type, Super_Type_Type).class_method #@ - @classmethod - def class_method(cls): - super(Super_Type_Type, Super_Type_Type).method #@ - super(Super_Type_Type, Super_Type_Type).class_method #@ - - class Super_Type_Object(First): - def method(self): - super(Super_Type_Object, self).method #@ - super(Super_Type_Object, self).class_method #@ - ''') - # Super(type, type) is the same for both functions and classmethods. - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, nodes.FunctionDef) - self.assertEqual(first.name, 'method') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'First') - self.assertEqual(second.type, 'classmethod') - - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, nodes.FunctionDef) - self.assertEqual(third.name, 'method') - - fourth = next(ast_nodes[3].infer()) - self.assertIsInstance(fourth, bases.BoundMethod) - self.assertEqual(fourth.bound.name, 'First') - self.assertEqual(fourth.type, 'classmethod') - - # Super(type, obj) can lead to different attribute bindings - # depending on the type of the place where super was called. - fifth = next(ast_nodes[4].infer()) - self.assertIsInstance(fifth, bases.BoundMethod) - self.assertEqual(fifth.bound.name, 'First') - self.assertEqual(fifth.type, 'method') - - sixth = next(ast_nodes[5].infer()) - self.assertIsInstance(sixth, bases.BoundMethod) - self.assertEqual(sixth.bound.name, 'First') - self.assertEqual(sixth.type, 'classmethod') - - def test_super_getattr_single_inheritance(self): - ast_nodes = test_utils.extract_node(''' - class First(object): - def test(self): pass - class Second(First): - def test2(self): pass - class Third(Second): - test3 = 42 - def __init__(self): - super(Third, self).test2 #@ - super(Third, self).test #@ - # test3 is local, no MRO lookup is done. - super(Third, self).test3 #@ - super(Third, self) #@ - - # Unbounds. - super(Third, Third).test2 #@ - super(Third, Third).test #@ - - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.BoundMethod) - self.assertEqual(first.bound.name, 'Second') - - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'First') - - with self.assertRaises(exceptions.InferenceError): - next(ast_nodes[2].infer()) - fourth = next(ast_nodes[3].infer()) - with self.assertRaises(exceptions.NotFoundError): - fourth.getattr('test3') - with self.assertRaises(exceptions.NotFoundError): - next(fourth.igetattr('test3')) - - first_unbound = next(ast_nodes[4].infer()) - self.assertIsInstance(first_unbound, nodes.FunctionDef) - self.assertEqual(first_unbound.name, 'test2') - self.assertEqual(first_unbound.parent.name, 'Second') - - second_unbound = next(ast_nodes[5].infer()) - self.assertIsInstance(second_unbound, nodes.FunctionDef) - self.assertEqual(second_unbound.name, 'test') - self.assertEqual(second_unbound.parent.name, 'First') - - def test_super_invalid_mro(self): - node = test_utils.extract_node(''' - class A(object): - test = 42 - class Super(A, A): - def __init__(self): - super(Super, self) #@ - ''') - inferred = next(node.infer()) - with self.assertRaises(exceptions.NotFoundError): - next(inferred.getattr('test')) - - def test_super_complex_mro(self): - ast_nodes = test_utils.extract_node(''' - class A(object): - def spam(self): return "A" - def foo(self): return "A" - @staticmethod - def static(self): pass - class B(A): - def boo(self): return "B" - def spam(self): return "B" - class C(A): - def boo(self): return "C" - class E(C, B): - def __init__(self): - super(E, self).boo #@ - super(C, self).boo #@ - super(E, self).spam #@ - super(E, self).foo #@ - super(E, self).static #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.BoundMethod) - self.assertEqual(first.bound.name, 'C') - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.BoundMethod) - self.assertEqual(second.bound.name, 'B') - third = next(ast_nodes[2].infer()) - self.assertIsInstance(third, bases.BoundMethod) - self.assertEqual(third.bound.name, 'B') - fourth = next(ast_nodes[3].infer()) - self.assertEqual(fourth.bound.name, 'A') - static = next(ast_nodes[4].infer()) - self.assertIsInstance(static, nodes.FunctionDef) - self.assertEqual(static.parent.scope().name, 'A') - - def test_super_data_model(self): - ast_nodes = test_utils.extract_node(''' - class X(object): pass - class A(X): - def __init__(self): - super(A, self) #@ - super(A, A) #@ - super(X, A) #@ - ''') - first = next(ast_nodes[0].infer()) - thisclass = first.getattr('__thisclass__')[0] - self.assertIsInstance(thisclass, nodes.ClassDef) - self.assertEqual(thisclass.name, 'A') - selfclass = first.getattr('__self_class__')[0] - self.assertIsInstance(selfclass, nodes.ClassDef) - self.assertEqual(selfclass.name, 'A') - self_ = first.getattr('__self__')[0] - self.assertIsInstance(self_, bases.Instance) - self.assertEqual(self_.name, 'A') - cls = first.getattr('__class__')[0] - self.assertEqual(cls, first._proxied) - - second = next(ast_nodes[1].infer()) - thisclass = second.getattr('__thisclass__')[0] - self.assertEqual(thisclass.name, 'A') - self_ = second.getattr('__self__')[0] - self.assertIsInstance(self_, nodes.ClassDef) - self.assertEqual(self_.name, 'A') - - third = next(ast_nodes[2].infer()) - thisclass = third.getattr('__thisclass__')[0] - self.assertEqual(thisclass.name, 'X') - selfclass = third.getattr('__self_class__')[0] - self.assertEqual(selfclass.name, 'A') - - def assertEqualMro(self, klass, expected_mro): - self.assertEqual( - [member.name for member in klass.super_mro()], - expected_mro) - - def test_super_mro(self): - ast_nodes = test_utils.extract_node(''' - class A(object): pass - class B(A): pass - class C(A): pass - class E(C, B): - def __init__(self): - super(E, self) #@ - super(C, self) #@ - super(B, self) #@ - - super(B, 1) #@ - super(1, B) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertEqualMro(first, ['C', 'B', 'A', 'object']) - second = next(ast_nodes[1].infer()) - self.assertEqualMro(second, ['B', 'A', 'object']) - third = next(ast_nodes[2].infer()) - self.assertEqualMro(third, ['A', 'object']) - - fourth = next(ast_nodes[3].infer()) - with self.assertRaises(exceptions.SuperError): - fourth.super_mro() - fifth = next(ast_nodes[4].infer()) - with self.assertRaises(exceptions.SuperError): - fifth.super_mro() - - def test_super_yes_objects(self): - ast_nodes = test_utils.extract_node(''' - from collections import Missing - class A(object): - def __init__(self): - super(Missing, self) #@ - super(A, Missing) #@ - ''') - first = next(ast_nodes[0].infer()) - self.assertIsInstance(first, bases.Instance) - second = next(ast_nodes[1].infer()) - self.assertIsInstance(second, bases.Instance) - - def test_super_invalid_types(self): - node = test_utils.extract_node(''' - import collections - class A(object): - def __init__(self): - super(A, collections) #@ - ''') - inferred = next(node.infer()) - with self.assertRaises(exceptions.SuperError): - inferred.super_mro() - with self.assertRaises(exceptions.SuperArgumentTypeError): - inferred.super_mro() - - def test_super_pytype_display_type_name(self): - node = test_utils.extract_node(''' - class A(object): - def __init__(self): - super(A, self) #@ - ''') - inferred = next(node.infer()) - self.assertEqual(inferred.pytype(), "%s.super" % bases.BUILTINS) - self.assertEqual(inferred.display_type(), 'Super of') - self.assertEqual(inferred.name, 'A') - - def test_super_properties(self): - node = test_utils.extract_node(''' - class Foo(object): - @property - def dict(self): - return 42 - - class Bar(Foo): - @property - def dict(self): - return super(Bar, self).dict - - Bar().dict - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_peephole.py b/pymode/libs/astroid/tests/unittest_peephole.py deleted file mode 100644 index 78349898..00000000 --- a/pymode/libs/astroid/tests/unittest_peephole.py +++ /dev/null @@ -1,121 +0,0 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . - -"""Tests for the astroid AST peephole optimizer.""" - -import ast -import textwrap -import unittest - -import astroid -from astroid import astpeephole -from astroid import builder -from astroid import manager -from astroid import test_utils -from astroid.tests import resources - - -MANAGER = manager.AstroidManager() - - -class PeepholeOptimizer(unittest.TestCase): - @classmethod - def setUpClass(cls): - MANAGER.optimize_ast = True - - @classmethod - def tearDownClass(cls): - MANAGER.optimize_ast = False - - def setUp(self): - self._optimizer = astpeephole.ASTPeepholeOptimizer() - - @staticmethod - def _get_binops(code): - module = ast.parse(textwrap.dedent(code)) - return [node.value for node in module.body - if isinstance(node, ast.Expr)] - - @test_utils.require_version(maxver='3.0') - def test_optimize_binop_unicode(self): - nodes = self._get_binops(""" - u"a" + u"b" + u"c" - - u"a" + "c" + "b" - u"a" + b"c" - """) - - result = self._optimizer.optimize_binop(nodes[0]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, u"abc") - - self.assertIsNone(self._optimizer.optimize_binop(nodes[1])) - self.assertIsNone(self._optimizer.optimize_binop(nodes[2])) - - def test_optimize_binop(self): - nodes = self._get_binops(""" - "a" + "b" + "c" + "d" - b"a" + b"b" + b"c" + b"d" - "a" + "b" - - "a" + "b" + 1 + object - var = 4 - "a" + "b" + var + "c" - "a" + "b" + "c" - "4" - "a" + "b" + "c" + "d".format() - "a" - "b" - "a" - 1 + 4 + 5 + 6 - """) - - result = self._optimizer.optimize_binop(nodes[0]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, "abcd") - - result = self._optimizer.optimize_binop(nodes[1]) - self.assertIsInstance(result, astroid.Const) - self.assertEqual(result.value, b"abcd") - - for node in nodes[2:]: - self.assertIsNone(self._optimizer.optimize_binop(node)) - - def test_big_binop_crash(self): - # Test that we don't fail on a lot of joined strings - # through the addition operator. - module = resources.build_file('data/joined_strings.py') - element = next(module['x'].infer()) - self.assertIsInstance(element, astroid.Const) - self.assertEqual(len(element.value), 61660) - - def test_optimisation_disabled(self): - try: - MANAGER.optimize_ast = False - module = builder.parse(""" - '1' + '2' + '3' - """) - self.assertIsInstance(module.body[0], astroid.Expr) - self.assertIsInstance(module.body[0].value, astroid.BinOp) - self.assertIsInstance(module.body[0].value.left, astroid.BinOp) - self.assertIsInstance(module.body[0].value.left.left, - astroid.Const) - finally: - MANAGER.optimize_ast = True - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_protocols.py b/pymode/libs/astroid/tests/unittest_protocols.py deleted file mode 100644 index 16745129..00000000 --- a/pymode/libs/astroid/tests/unittest_protocols.py +++ /dev/null @@ -1,176 +0,0 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . - -import contextlib -import unittest - -import astroid -from astroid.test_utils import extract_node, require_version -from astroid import InferenceError -from astroid import nodes -from astroid import util -from astroid.node_classes import AssignName, Const, Name, Starred - - -@contextlib.contextmanager -def _add_transform(manager, node, transform, predicate=None): - manager.register_transform(node, transform, predicate) - try: - yield - finally: - manager.unregister_transform(node, transform, predicate) - - -class ProtocolTests(unittest.TestCase): - - def assertConstNodesEqual(self, nodes_list_expected, nodes_list_got): - self.assertEqual(len(nodes_list_expected), len(nodes_list_got)) - for node in nodes_list_got: - self.assertIsInstance(node, Const) - for node, expected_value in zip(nodes_list_got, nodes_list_expected): - self.assertEqual(expected_value, node.value) - - def assertNameNodesEqual(self, nodes_list_expected, nodes_list_got): - self.assertEqual(len(nodes_list_expected), len(nodes_list_got)) - for node in nodes_list_got: - self.assertIsInstance(node, Name) - for node, expected_name in zip(nodes_list_got, nodes_list_expected): - self.assertEqual(expected_name, node.name) - - def test_assigned_stmts_simple_for(self): - assign_stmts = extract_node(""" - for a in (1, 2, 3): #@ - pass - - for b in range(3): #@ - pass - """) - - for1_assnode = next(assign_stmts[0].nodes_of_class(AssignName)) - assigned = list(for1_assnode.assigned_stmts()) - self.assertConstNodesEqual([1, 2, 3], assigned) - - for2_assnode = next(assign_stmts[1].nodes_of_class(AssignName)) - self.assertRaises(InferenceError, - list, for2_assnode.assigned_stmts()) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_for(self): - assign_stmts = extract_node(""" - for *a, b in ((1, 2, 3), (4, 5, 6, 7)): #@ - pass - """) - - for1_starred = next(assign_stmts.nodes_of_class(Starred)) - assigned = next(for1_starred.assigned_stmts()) - self.assertEqual(assigned, util.YES) - - def _get_starred_stmts(self, code): - assign_stmt = extract_node("{} #@".format(code)) - starred = next(assign_stmt.nodes_of_class(Starred)) - return next(starred.assigned_stmts()) - - def _helper_starred_expected_const(self, code, expected): - stmts = self._get_starred_stmts(code) - self.assertIsInstance(stmts, nodes.List) - stmts = stmts.elts - self.assertConstNodesEqual(expected, stmts) - - def _helper_starred_expected(self, code, expected): - stmts = self._get_starred_stmts(code) - self.assertEqual(expected, stmts) - - def _helper_starred_inference_error(self, code): - assign_stmt = extract_node("{} #@".format(code)) - starred = next(assign_stmt.nodes_of_class(Starred)) - self.assertRaises(InferenceError, list, starred.assigned_stmts()) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_assnames(self): - self._helper_starred_expected_const( - "a, *b = (1, 2, 3, 4) #@", [2, 3, 4]) - self._helper_starred_expected_const( - "*a, b = (1, 2, 3) #@", [1, 2]) - self._helper_starred_expected_const( - "a, *b, c = (1, 2, 3, 4, 5) #@", - [2, 3, 4]) - self._helper_starred_expected_const( - "a, *b = (1, 2) #@", [2]) - self._helper_starred_expected_const( - "*b, a = (1, 2) #@", [1]) - self._helper_starred_expected_const( - "[*b] = (1, 2) #@", [1, 2]) - - @require_version(minver='3.0') - def test_assigned_stmts_starred_yes(self): - # Not something iterable and known - self._helper_starred_expected("a, *b = range(3) #@", util.YES) - # Not something inferrable - self._helper_starred_expected("a, *b = balou() #@", util.YES) - # In function, unknown. - self._helper_starred_expected(""" - def test(arg): - head, *tail = arg #@""", util.YES) - # These cases aren't worth supporting. - self._helper_starred_expected( - "a, (*b, c), d = (1, (2, 3, 4), 5) #@", util.YES) - - @require_version(minver='3.0') - def test_assign_stmts_starred_fails(self): - # Too many starred - self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@") - # Too many lhs values - self._helper_starred_inference_error("a, *b, c = (1, 2) #@") - # This could be solved properly, but it complicates needlessly the - # code for assigned_stmts, without oferring real benefit. - self._helper_starred_inference_error( - "(*a, b), (c, *d) = (1, 2, 3), (4, 5, 6) #@") - - def test_assigned_stmts_assignments(self): - assign_stmts = extract_node(""" - c = a #@ - - d, e = b, c #@ - """) - - simple_assnode = next(assign_stmts[0].nodes_of_class(AssignName)) - assigned = list(simple_assnode.assigned_stmts()) - self.assertNameNodesEqual(['a'], assigned) - - assnames = assign_stmts[1].nodes_of_class(AssignName) - simple_mul_assnode_1 = next(assnames) - assigned = list(simple_mul_assnode_1.assigned_stmts()) - self.assertNameNodesEqual(['b'], assigned) - simple_mul_assnode_2 = next(assnames) - assigned = list(simple_mul_assnode_2.assigned_stmts()) - self.assertNameNodesEqual(['c'], assigned) - - def test_sequence_assigned_stmts_not_accepting_empty_node(self): - def transform(node): - node.root().locals['__all__'] = [node.value] - - manager = astroid.MANAGER - with _add_transform(manager, astroid.Assign, transform): - module = astroid.parse(''' - __all__ = ['a'] - ''') - module.wildcard_import_names() - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_python3.py b/pymode/libs/astroid/tests/unittest_python3.py deleted file mode 100644 index 87010571..00000000 --- a/pymode/libs/astroid/tests/unittest_python3.py +++ /dev/null @@ -1,254 +0,0 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -from textwrap import dedent -import unittest - -from astroid import nodes -from astroid.node_classes import Assign, Expr, YieldFrom, Name, Const -from astroid.builder import AstroidBuilder -from astroid.scoped_nodes import ClassDef, FunctionDef -from astroid.test_utils import require_version, extract_node - - -class Python3TC(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.builder = AstroidBuilder() - - @require_version('3.0') - def test_starred_notation(self): - astroid = self.builder.string_build("*a, b = [1, 2, 3]", 'test', 'test') - - # Get the star node - node = next(next(next(astroid.get_children()).get_children()).get_children()) - - self.assertTrue(isinstance(node.assign_type(), Assign)) - - @require_version('3.3') - def test_yield_from(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertIsInstance(func, FunctionDef) - yieldfrom_stmt = func.body[0] - - self.assertIsInstance(yieldfrom_stmt, Expr) - self.assertIsInstance(yieldfrom_stmt.value, YieldFrom) - self.assertEqual(yieldfrom_stmt.as_string(), - 'yield from iter([1, 2])') - - @require_version('3.3') - def test_yield_from_is_generator(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertIsInstance(func, FunctionDef) - self.assertTrue(func.is_generator()) - - @require_version('3.3') - def test_yield_from_as_string(self): - body = dedent(""" - def func(): - yield from iter([1, 2]) - value = yield from other() - """) - astroid = self.builder.string_build(body) - func = astroid.body[0] - self.assertEqual(func.as_string().strip(), body.strip()) - - # metaclass tests - - @require_version('3.0') - def test_simple_metaclass(self): - astroid = self.builder.string_build("class Test(metaclass=type): pass") - klass = astroid.body[0] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'type') - - @require_version('3.0') - def test_metaclass_error(self): - astroid = self.builder.string_build("class Test(metaclass=typ): pass") - klass = astroid.body[0] - self.assertFalse(klass.metaclass()) - - @require_version('3.0') - def test_metaclass_imported(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass""")) - klass = astroid.body[1] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @require_version('3.0') - def test_as_string(self): - body = dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass""") - astroid = self.builder.string_build(body) - klass = astroid.body[1] - - self.assertEqual(klass.as_string(), - '\n\nclass Test(metaclass=ABCMeta):\n pass\n') - - @require_version('3.0') - def test_old_syntax_works(self): - astroid = self.builder.string_build(dedent(""" - class Test: - __metaclass__ = type - class SubTest(Test): pass - """)) - klass = astroid['SubTest'] - metaclass = klass.metaclass() - self.assertIsNone(metaclass) - - @require_version('3.0') - def test_metaclass_yes_leak(self): - astroid = self.builder.string_build(dedent(""" - # notice `ab` instead of `abc` - from ab import ABCMeta - - class Meta(metaclass=ABCMeta): pass - """)) - klass = astroid['Meta'] - self.assertIsNone(klass.metaclass()) - - @require_version('3.0') - def test_parent_metaclass(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - class Test(metaclass=ABCMeta): pass - class SubTest(Test): pass - """)) - klass = astroid['SubTest'] - self.assertTrue(klass.newstyle) - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @require_version('3.0') - def test_metaclass_ancestors(self): - astroid = self.builder.string_build(dedent(""" - from abc import ABCMeta - - class FirstMeta(metaclass=ABCMeta): pass - class SecondMeta(metaclass=type): - pass - - class Simple: - pass - - class FirstImpl(FirstMeta): pass - class SecondImpl(FirstImpl): pass - class ThirdImpl(Simple, SecondMeta): - pass - """)) - classes = { - 'ABCMeta': ('FirstImpl', 'SecondImpl'), - 'type': ('ThirdImpl', ) - } - for metaclass, names in classes.items(): - for name in names: - impl = astroid[name] - meta = impl.metaclass() - self.assertIsInstance(meta, ClassDef) - self.assertEqual(meta.name, metaclass) - - @require_version('3.0') - def test_annotation_support(self): - astroid = self.builder.string_build(dedent(""" - def test(a: int, b: str, c: None, d, e, - *args: float, **kwargs: int)->int: - pass - """)) - func = astroid['test'] - self.assertIsInstance(func.args.varargannotation, Name) - self.assertEqual(func.args.varargannotation.name, 'float') - self.assertIsInstance(func.args.kwargannotation, Name) - self.assertEqual(func.args.kwargannotation.name, 'int') - self.assertIsInstance(func.returns, Name) - self.assertEqual(func.returns.name, 'int') - arguments = func.args - self.assertIsInstance(arguments.annotations[0], Name) - self.assertEqual(arguments.annotations[0].name, 'int') - self.assertIsInstance(arguments.annotations[1], Name) - self.assertEqual(arguments.annotations[1].name, 'str') - self.assertIsInstance(arguments.annotations[2], Const) - self.assertIsNone(arguments.annotations[2].value) - self.assertIsNone(arguments.annotations[3]) - self.assertIsNone(arguments.annotations[4]) - - astroid = self.builder.string_build(dedent(""" - def test(a: int=1, b: str=2): - pass - """)) - func = astroid['test'] - self.assertIsInstance(func.args.annotations[0], Name) - self.assertEqual(func.args.annotations[0].name, 'int') - self.assertIsInstance(func.args.annotations[1], Name) - self.assertEqual(func.args.annotations[1].name, 'str') - self.assertIsNone(func.returns) - - @require_version('3.0') - def test_annotation_as_string(self): - code1 = dedent(''' - def test(a, b:int=4, c=2, f:'lala'=4)->2: - pass''') - code2 = dedent(''' - def test(a:typing.Generic[T], c:typing.Any=24)->typing.Iterable: - pass''') - for code in (code1, code2): - func = extract_node(code) - self.assertEqual(func.as_string(), code) - - @require_version('3.5') - def test_unpacking_in_dicts(self): - code = "{'x': 1, **{'y': 2}}" - node = extract_node(code) - self.assertEqual(node.as_string(), code) - keys = [key for (key, _) in node.items] - self.assertIsInstance(keys[0], nodes.Const) - self.assertIsInstance(keys[1], nodes.DictUnpack) - - @require_version('3.5') - def test_nested_unpacking_in_dicts(self): - code = "{'x': 1, **{'y': 2, **{'z': 3}}}" - node = extract_node(code) - self.assertEqual(node.as_string(), code) - - @require_version('3.5') - def test_unpacking_in_dict_getitem(self): - node = extract_node('{1:2, **{2:3, 3:4}, **{5: 6}}') - for key, expected in ((1, 2), (2, 3), (3, 4), (5, 6)): - value = node.getitem(key) - self.assertIsInstance(value, nodes.Const) - self.assertEqual(value.value, expected) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_raw_building.py b/pymode/libs/astroid/tests/unittest_raw_building.py deleted file mode 100644 index 2bdaac17..00000000 --- a/pymode/libs/astroid/tests/unittest_raw_building.py +++ /dev/null @@ -1,85 +0,0 @@ -import inspect -import os -import unittest - -from six.moves import builtins # pylint: disable=import-error - -from astroid.builder import AstroidBuilder -from astroid.raw_building import ( - attach_dummy_node, build_module, - build_class, build_function, build_from_import -) -from astroid import test_utils -from astroid import nodes -from astroid.bases import BUILTINS - - -class RawBuildingTC(unittest.TestCase): - - def test_attach_dummy_node(self): - node = build_module('MyModule') - attach_dummy_node(node, 'DummyNode') - self.assertEqual(1, len(list(node.get_children()))) - - def test_build_module(self): - node = build_module('MyModule') - self.assertEqual(node.name, 'MyModule') - self.assertEqual(node.pure_python, False) - self.assertEqual(node.package, False) - self.assertEqual(node.parent, None) - - def test_build_class(self): - node = build_class('MyClass') - self.assertEqual(node.name, 'MyClass') - self.assertEqual(node.doc, None) - - def test_build_function(self): - node = build_function('MyFunction') - self.assertEqual(node.name, 'MyFunction') - self.assertEqual(node.doc, None) - - def test_build_function_args(self): - args = ['myArgs1', 'myArgs2'] - node = build_function('MyFunction', args) - self.assertEqual('myArgs1', node.args.args[0].name) - self.assertEqual('myArgs2', node.args.args[1].name) - self.assertEqual(2, len(node.args.args)) - - def test_build_function_defaults(self): - defaults = ['defaults1', 'defaults2'] - node = build_function('MyFunction', None, defaults) - self.assertEqual(2, len(node.args.defaults)) - - def test_build_from_import(self): - names = ['exceptions, inference, inspector'] - node = build_from_import('astroid', names) - self.assertEqual(len(names), len(node.names)) - - @test_utils.require_version(minver='3.0') - def test_io_is__io(self): - # _io module calls itself io. This leads - # to cyclic dependencies when astroid tries to resolve - # what io.BufferedReader is. The code that handles this - # is in astroid.raw_building.imported_member, which verifies - # the true name of the module. - import _io - - builder = AstroidBuilder() - module = builder.inspect_build(_io) - buffered_reader = module.getattr('BufferedReader')[0] - self.assertEqual(buffered_reader.root().name, 'io') - - @unittest.skipUnless(os.name == 'java', 'Requires Jython') - def test_open_is_inferred_correctly(self): - # Lot of Jython builtins don't have a __module__ attribute. - for name, _ in inspect.getmembers(builtins, predicate=inspect.isbuiltin): - if name == 'print': - continue - node = test_utils.extract_node('{0} #@'.format(name)) - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.FunctionDef, name) - self.assertEqual(inferred.root().name, BUILTINS, name) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_regrtest.py b/pymode/libs/astroid/tests/unittest_regrtest.py deleted file mode 100644 index 158c7119..00000000 --- a/pymode/libs/astroid/tests/unittest_regrtest.py +++ /dev/null @@ -1,364 +0,0 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -import sys -import unittest -import textwrap - -import six - -from astroid import MANAGER, Instance, nodes -from astroid.bases import BUILTINS -from astroid.builder import AstroidBuilder -from astroid import exceptions -from astroid.raw_building import build_module -from astroid.manager import AstroidManager -from astroid.test_utils import require_version, extract_node -from astroid.tests import resources -from astroid import transforms - - -class NonRegressionTests(resources.AstroidCacheSetupMixin, - unittest.TestCase): - - def setUp(self): - sys.path.insert(0, resources.find('data')) - MANAGER.always_load_extensions = True - MANAGER.astroid_cache[BUILTINS] = self._builtins - - def tearDown(self): - # Since we may have created a brainless manager, leading - # to a new cache builtin module and proxy classes in the constants, - # clear out the global manager cache. - MANAGER.clear_cache(self._builtins) - MANAGER.always_load_extensions = False - sys.path.pop(0) - sys.path_importer_cache.pop(resources.find('data'), None) - - def brainless_manager(self): - manager = AstroidManager() - # avoid caching into the AstroidManager borg since we get problems - # with other tests : - manager.__dict__ = {} - manager._failed_import_hooks = [] - manager.astroid_cache = {} - manager._mod_file_cache = {} - manager._transform = transforms.TransformVisitor() - manager.clear_cache() # trigger proper bootstraping - return manager - - def test_module_path(self): - man = self.brainless_manager() - mod = man.ast_from_module_name('package.import_package_subpackage_module') - package = next(mod.igetattr('package')) - self.assertEqual(package.name, 'package') - subpackage = next(package.igetattr('subpackage')) - self.assertIsInstance(subpackage, nodes.Module) - self.assertTrue(subpackage.package) - self.assertEqual(subpackage.name, 'package.subpackage') - module = next(subpackage.igetattr('module')) - self.assertEqual(module.name, 'package.subpackage.module') - - - def test_package_sidepackage(self): - manager = self.brainless_manager() - assert 'package.sidepackage' not in MANAGER.astroid_cache - package = manager.ast_from_module_name('absimp') - self.assertIsInstance(package, nodes.Module) - self.assertTrue(package.package) - subpackage = next(package.getattr('sidepackage')[0].infer()) - self.assertIsInstance(subpackage, nodes.Module) - self.assertTrue(subpackage.package) - self.assertEqual(subpackage.name, 'absimp.sidepackage') - - - def test_living_property(self): - builder = AstroidBuilder() - builder._done = {} - builder._module = sys.modules[__name__] - builder.object_build(build_module('module_name', ''), Whatever) - - - def test_new_style_class_detection(self): - try: - import pygtk # pylint: disable=unused-variable - except ImportError: - self.skipTest('test skipped: pygtk is not available') - # XXX may fail on some pygtk version, because objects in - # gobject._gobject have __module__ set to gobject :( - builder = AstroidBuilder() - data = """ -import pygtk -pygtk.require("2.6") -import gobject - -class A(gobject.GObject): - pass -""" - astroid = builder.string_build(data, __name__, __file__) - a = astroid['A'] - self.assertTrue(a.newstyle) - - - def test_pylint_config_attr(self): - try: - from pylint import lint # pylint: disable=unused-variable - except ImportError: - self.skipTest('pylint not available') - mod = MANAGER.ast_from_module_name('pylint.lint') - pylinter = mod['PyLinter'] - expect = ['OptionsManagerMixIn', 'object', 'MessagesHandlerMixIn', - 'ReportsHandlerMixIn', 'BaseTokenChecker', 'BaseChecker', - 'OptionsProviderMixIn'] - self.assertListEqual([c.name for c in pylinter.ancestors()], - expect) - self.assertTrue(list(Instance(pylinter).getattr('config'))) - inferred = list(Instance(pylinter).igetattr('config')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].root().name, 'optparse') - self.assertEqual(inferred[0].name, 'Values') - - def test_numpy_crash(self): - """test don't crash on numpy""" - #a crash occured somewhere in the past, and an - # InferenceError instead of a crash was better, but now we even infer! - try: - import numpy # pylint: disable=unused-variable - except ImportError: - self.skipTest('test skipped: numpy is not available') - builder = AstroidBuilder() - data = """ -from numpy import multiply - -multiply(1, 2, 3) -""" - astroid = builder.string_build(data, __name__, __file__) - callfunc = astroid.body[1].value.func - inferred = callfunc.inferred() - self.assertEqual(len(inferred), 2) - - @require_version('3.0') - def test_nameconstant(self): - # used to fail for Python 3.4 - builder = AstroidBuilder() - astroid = builder.string_build("def test(x=True): pass") - default = astroid.body[0].args.args[0] - self.assertEqual(default.name, 'x') - self.assertEqual(next(default.infer()).value, True) - - @require_version('2.7') - def test_with_infer_assignnames(self): - builder = AstroidBuilder() - data = """ -with open('a.txt') as stream, open('b.txt'): - stream.read() -""" - astroid = builder.string_build(data, __name__, __file__) - # Used to crash due to the fact that the second - # context manager didn't use an assignment name. - list(astroid.nodes_of_class(nodes.Call))[-1].inferred() - - def test_recursion_regression_issue25(self): - builder = AstroidBuilder() - data = """ -import recursion as base - -_real_Base = base.Base - -class Derived(_real_Base): - pass - -def run(): - base.Base = Derived -""" - astroid = builder.string_build(data, __name__, __file__) - # Used to crash in _is_metaclass, due to wrong - # ancestors chain - classes = astroid.nodes_of_class(nodes.ClassDef) - for klass in classes: - # triggers the _is_metaclass call - klass.type # pylint: disable=pointless-statement - - def test_decorator_callchain_issue42(self): - builder = AstroidBuilder() - data = """ - -def test(): - def factory(func): - def newfunc(): - func() - return newfunc - return factory - -@test() -def crash(): - pass -""" - astroid = builder.string_build(data, __name__, __file__) - self.assertEqual(astroid['crash'].type, 'function') - - def test_filter_stmts_scoping(self): - builder = AstroidBuilder() - data = """ -def test(): - compiler = int() - class B(compiler.__class__): - pass - compiler = B() - return compiler -""" - astroid = builder.string_build(data, __name__, __file__) - test = astroid['test'] - result = next(test.infer_call_result(astroid)) - self.assertIsInstance(result, Instance) - base = next(result._proxied.bases[0].infer()) - self.assertEqual(base.name, 'int') - - def test_ancestors_patching_class_recursion(self): - node = AstroidBuilder().string_build(textwrap.dedent(""" - import string - Template = string.Template - - class A(Template): - pass - - class B(A): - pass - - def test(x=False): - if x: - string.Template = A - else: - string.Template = B - """)) - klass = node['A'] - ancestors = list(klass.ancestors()) - self.assertEqual(ancestors[0].qname(), 'string.Template') - - def test_ancestors_yes_in_bases(self): - # Test for issue https://bitbucket.org/logilab/astroid/issue/84 - # This used to crash astroid with a TypeError, because an YES - # node was present in the bases - node = extract_node(""" - def with_metaclass(meta, *bases): - class metaclass(meta): - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - import lala - - class A(with_metaclass(object, lala.lala)): #@ - pass - """) - ancestors = list(node.ancestors()) - if six.PY3: - self.assertEqual(len(ancestors), 1) - self.assertEqual(ancestors[0].qname(), - "{}.object".format(BUILTINS)) - else: - self.assertEqual(len(ancestors), 0) - - def test_ancestors_missing_from_function(self): - # Test for https://www.logilab.org/ticket/122793 - node = extract_node(''' - def gen(): yield - GEN = gen() - next(GEN) - ''') - self.assertRaises(exceptions.InferenceError, next, node.infer()) - - def test_unicode_in_docstring(self): - # Crashed for astroid==1.4.1 - # Test for https://bitbucket.org/logilab/astroid/issues/273/ - - # In a regular file, "coding: utf-8" would have been used. - node = extract_node(u''' - from __future__ import unicode_literals - - class MyClass(object): - def method(self): - "With unicode : %s " - - instance = MyClass() - ''' % u"\u2019") - - next(node.value.infer()).as_string() - - def test_binop_generates_nodes_with_parents(self): - node = extract_node(''' - def no_op(*args): - pass - def foo(*args): - def inner(*more_args): - args + more_args #@ - return inner - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Tuple) - self.assertIsNotNone(inferred.parent) - self.assertIsInstance(inferred.parent, nodes.BinOp) - - def test_decorator_names_inference_error_leaking(self): - node = extract_node(''' - class Parent(object): - @property - def foo(self): - pass - - class Child(Parent): - @Parent.foo.getter - def foo(self): #@ - return super(Child, self).foo + ['oink'] - ''') - inferred = next(node.infer()) - self.assertEqual(inferred.decoratornames(), set()) - - def test_ssl_protocol(self): - node = extract_node(''' - import ssl - ssl.PROTOCOL_TLSv1 - ''') - inferred = next(node.infer()) - self.assertIsInstance(inferred, nodes.Const) - - def test_uninferable_string_argument_of_namedtuple(self): - node = extract_node(''' - import collections - collections.namedtuple('{}'.format("a"), '')() - ''') - next(node.infer()) - - @require_version(maxver='3.0') - def test_reassignment_in_except_handler(self): - node = extract_node(''' - import exceptions - try: - {}["a"] - except KeyError, exceptions.IndexError: - pass - - IndexError #@ - ''') - self.assertEqual(len(node.inferred()), 1) - - -class Whatever(object): - a = property(lambda x: x, lambda x: x) - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_scoped_nodes.py b/pymode/libs/astroid/tests/unittest_scoped_nodes.py deleted file mode 100644 index a15c923a..00000000 --- a/pymode/libs/astroid/tests/unittest_scoped_nodes.py +++ /dev/null @@ -1,1583 +0,0 @@ -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -"""tests for specific behaviour of astroid scoped nodes (i.e. module, class and -function) -""" -import os -import sys -from functools import partial -import unittest -import warnings - -from astroid import builder -from astroid import nodes -from astroid import scoped_nodes -from astroid import util -from astroid.exceptions import ( - InferenceError, NotFoundError, - NoDefault, ResolveError, MroError, - InconsistentMroError, DuplicateBasesError, -) -from astroid.bases import ( - BUILTINS, Instance, - BoundMethod, UnboundMethod, Generator -) -from astroid import __pkginfo__ -from astroid import test_utils -from astroid.tests import resources - - -def _test_dict_interface(self, node, test_attr): - self.assertIs(node[test_attr], node[test_attr]) - self.assertIn(test_attr, node) - node.keys() - node.values() - node.items() - iter(node) - - -class ModuleLoader(resources.SysPathSetup): - def setUp(self): - super(ModuleLoader, self).setUp() - self.module = resources.build_file('data/module.py', 'data.module') - self.module2 = resources.build_file('data/module2.py', 'data.module2') - self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr') - self.pack = resources.build_file('data/__init__.py', 'data') - - -class ModuleNodeTest(ModuleLoader, unittest.TestCase): - - def test_special_attributes(self): - self.assertEqual(len(self.module.getattr('__name__')), 1) - self.assertIsInstance(self.module.getattr('__name__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__name__')[0].value, 'data.module') - self.assertEqual(len(self.module.getattr('__doc__')), 1) - self.assertIsInstance(self.module.getattr('__doc__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__doc__')[0].value, 'test module for astroid\n') - self.assertEqual(len(self.module.getattr('__file__')), 1) - self.assertIsInstance(self.module.getattr('__file__')[0], nodes.Const) - self.assertEqual(self.module.getattr('__file__')[0].value, - os.path.abspath(resources.find('data/module.py'))) - self.assertEqual(len(self.module.getattr('__dict__')), 1) - self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict) - self.assertRaises(NotFoundError, self.module.getattr, '__path__') - self.assertEqual(len(self.pack.getattr('__path__')), 1) - self.assertIsInstance(self.pack.getattr('__path__')[0], nodes.List) - - def test_dict_interface(self): - _test_dict_interface(self, self.module, 'YO') - - def test_getattr(self): - yo = self.module.getattr('YO')[0] - self.assertIsInstance(yo, nodes.ClassDef) - self.assertEqual(yo.name, 'YO') - red = next(self.module.igetattr('redirect')) - self.assertIsInstance(red, nodes.FunctionDef) - self.assertEqual(red.name, 'four_args') - namenode = next(self.module.igetattr('NameNode')) - self.assertIsInstance(namenode, nodes.ClassDef) - self.assertEqual(namenode.name, 'Name') - # resolve packageredirection - mod = resources.build_file('data/appl/myConnection.py', - 'data.appl.myConnection') - ssl = next(mod.igetattr('SSL1')) - cnx = next(ssl.igetattr('Connection')) - self.assertEqual(cnx.__class__, nodes.ClassDef) - self.assertEqual(cnx.name, 'Connection') - self.assertEqual(cnx.root().name, 'data.SSL1.Connection1') - self.assertEqual(len(self.nonregr.getattr('enumerate')), 2) - # raise ResolveError - self.assertRaises(InferenceError, self.nonregr.igetattr, 'YOAA') - - def test_wildcard_import_names(self): - m = resources.build_file('data/all.py', 'all') - self.assertEqual(m.wildcard_import_names(), ['Aaa', '_bla', 'name']) - m = resources.build_file('data/notall.py', 'notall') - res = sorted(m.wildcard_import_names()) - self.assertEqual(res, ['Aaa', 'func', 'name', 'other']) - - def test_public_names(self): - m = builder.parse(''' - name = 'a' - _bla = 2 - other = 'o' - class Aaa: pass - def func(): print('yo') - __all__ = 'Aaa', '_bla', 'name' - ''') - values = sorted(['Aaa', 'name', 'other', 'func']) - self.assertEqual(sorted(m._public_names()), values) - m = builder.parse(''' - name = 'a' - _bla = 2 - other = 'o' - class Aaa: pass - - def func(): return 'yo' - ''') - res = sorted(m._public_names()) - self.assertEqual(res, values) - - m = builder.parse(''' - from missing import tzop - trop = "test" - __all__ = (trop, "test1", tzop, 42) - ''') - res = sorted(m._public_names()) - self.assertEqual(res, ["trop", "tzop"]) - - m = builder.parse(''' - test = tzop = 42 - __all__ = ('test', ) + ('tzop', ) - ''') - res = sorted(m._public_names()) - self.assertEqual(res, ['test', 'tzop']) - - def test_module_getattr(self): - data = ''' - appli = application - appli += 2 - del appli - ''' - astroid = builder.parse(data, __name__) - # test del statement not returned by getattr - self.assertEqual(len(astroid.getattr('appli')), 2, - astroid.getattr('appli')) - - def test_relative_to_absolute_name(self): - # package - mod = nodes.Module('very.multi.package', 'doc') - mod.package = True - modname = mod.relative_to_absolute_name('utils', 1) - self.assertEqual(modname, 'very.multi.package.utils') - modname = mod.relative_to_absolute_name('utils', 2) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 0) - self.assertEqual(modname, 'very.multi.package.utils') - modname = mod.relative_to_absolute_name('', 1) - self.assertEqual(modname, 'very.multi.package') - # non package - mod = nodes.Module('very.multi.module', 'doc') - mod.package = False - modname = mod.relative_to_absolute_name('utils', 0) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 1) - self.assertEqual(modname, 'very.multi.utils') - modname = mod.relative_to_absolute_name('utils', 2) - self.assertEqual(modname, 'very.utils') - modname = mod.relative_to_absolute_name('', 1) - self.assertEqual(modname, 'very.multi') - - def test_import_1(self): - data = '''from . import subpackage''' - sys.path.insert(0, resources.find('data')) - astroid = builder.parse(data, 'package', 'data/package/__init__.py') - try: - m = astroid.import_module('', level=1) - self.assertEqual(m.name, 'package') - inferred = list(astroid.igetattr('subpackage')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].name, 'package.subpackage') - finally: - del sys.path[0] - - - def test_import_2(self): - data = '''from . import subpackage as pouet''' - astroid = builder.parse(data, 'package', 'data/package/__init__.py') - sys.path.insert(0, resources.find('data')) - try: - m = astroid.import_module('', level=1) - self.assertEqual(m.name, 'package') - inferred = list(astroid.igetattr('pouet')) - self.assertEqual(len(inferred), 1) - self.assertEqual(inferred[0].name, 'package.subpackage') - finally: - del sys.path[0] - - - def test_file_stream_in_memory(self): - data = '''irrelevant_variable is irrelevant''' - astroid = builder.parse(data, 'in_memory') - with warnings.catch_warnings(record=True): - self.assertEqual(astroid.file_stream.read().decode(), data) - - def test_file_stream_physical(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - with open(path, 'rb') as file_io: - with warnings.catch_warnings(record=True): - self.assertEqual(astroid.file_stream.read(), file_io.read()) - - def test_file_stream_api(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - if __pkginfo__.numversion >= (1, 6): - # file_stream is slated for removal in astroid 1.6. - with self.assertRaises(AttributeError): - # pylint: disable=pointless-statement - astroid.file_stream - else: - # Until astroid 1.6, Module.file_stream will emit - # PendingDeprecationWarning in 1.4, DeprecationWarning - # in 1.5 and finally it will be removed in 1.6, leaving - # only Module.stream as the recommended way to retrieve - # its file stream. - with warnings.catch_warnings(record=True) as cm: - warnings.simplefilter("always") - self.assertIsNot(astroid.file_stream, astroid.file_stream) - self.assertGreater(len(cm), 1) - self.assertEqual(cm[0].category, PendingDeprecationWarning) - - def test_stream_api(self): - path = resources.find('data/all.py') - astroid = builder.AstroidBuilder().file_build(path, 'all') - stream = astroid.stream() - self.assertTrue(hasattr(stream, 'close')) - with stream: - with open(path, 'rb') as file_io: - self.assertEqual(stream.read(), file_io.read()) - - -class FunctionNodeTest(ModuleLoader, unittest.TestCase): - - def test_special_attributes(self): - func = self.module2['make_class'] - self.assertEqual(len(func.getattr('__name__')), 1) - self.assertIsInstance(func.getattr('__name__')[0], nodes.Const) - self.assertEqual(func.getattr('__name__')[0].value, 'make_class') - self.assertEqual(len(func.getattr('__doc__')), 1) - self.assertIsInstance(func.getattr('__doc__')[0], nodes.Const) - self.assertEqual(func.getattr('__doc__')[0].value, 'check base is correctly resolved to Concrete0') - self.assertEqual(len(self.module.getattr('__dict__')), 1) - self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict) - - def test_dict_interface(self): - _test_dict_interface(self, self.module['global_access'], 'local') - - def test_default_value(self): - func = self.module2['make_class'] - self.assertIsInstance(func.args.default_value('base'), nodes.Attribute) - self.assertRaises(NoDefault, func.args.default_value, 'args') - self.assertRaises(NoDefault, func.args.default_value, 'kwargs') - self.assertRaises(NoDefault, func.args.default_value, 'any') - #self.assertIsInstance(func.mularg_class('args'), nodes.Tuple) - #self.assertIsInstance(func.mularg_class('kwargs'), nodes.Dict) - #self.assertIsNone(func.mularg_class('base')) - - def test_navigation(self): - function = self.module['global_access'] - self.assertEqual(function.statement(), function) - l_sibling = function.previous_sibling() - # check taking parent if child is not a stmt - self.assertIsInstance(l_sibling, nodes.Assign) - child = function.args.args[0] - self.assertIs(l_sibling, child.previous_sibling()) - r_sibling = function.next_sibling() - self.assertIsInstance(r_sibling, nodes.ClassDef) - self.assertEqual(r_sibling.name, 'YO') - self.assertIs(r_sibling, child.next_sibling()) - last = r_sibling.next_sibling().next_sibling().next_sibling() - self.assertIsInstance(last, nodes.Assign) - self.assertIsNone(last.next_sibling()) - first = l_sibling.root().body[0] - self.assertIsNone(first.previous_sibling()) - - def test_nested_args(self): - if sys.version_info >= (3, 0): - self.skipTest("nested args has been removed in py3.x") - code = ''' - def nested_args(a, (b, c, d)): - "nested arguments test" - ''' - tree = builder.parse(code) - func = tree['nested_args'] - self.assertEqual(sorted(func._locals), ['a', 'b', 'c', 'd']) - self.assertEqual(func.args.format_args(), 'a, (b, c, d)') - - def test_four_args(self): - func = self.module['four_args'] - #self.assertEqual(func.args.args, ['a', ('b', 'c', 'd')]) - local = sorted(func.keys()) - self.assertEqual(local, ['a', 'b', 'c', 'd']) - self.assertEqual(func.type, 'function') - - def test_format_args(self): - func = self.module2['make_class'] - self.assertEqual(func.args.format_args(), - 'any, base=data.module.YO, *args, **kwargs') - func = self.module['four_args'] - self.assertEqual(func.args.format_args(), 'a, b, c, d') - - def test_is_generator(self): - self.assertTrue(self.module2['generator'].is_generator()) - self.assertFalse(self.module2['not_a_generator'].is_generator()) - self.assertFalse(self.module2['make_class'].is_generator()) - - def test_is_abstract(self): - method = self.module2['AbstractClass']['to_override'] - self.assertTrue(method.is_abstract(pass_is_abstract=False)) - self.assertEqual(method.qname(), 'data.module2.AbstractClass.to_override') - self.assertEqual(method.pytype(), '%s.instancemethod' % BUILTINS) - method = self.module2['AbstractClass']['return_something'] - self.assertFalse(method.is_abstract(pass_is_abstract=False)) - # non regression : test raise "string" doesn't cause an exception in is_abstract - func = self.module2['raise_string'] - self.assertFalse(func.is_abstract(pass_is_abstract=False)) - - def test_is_abstract_decorated(self): - methods = test_utils.extract_node(""" - import abc - - class Klass(object): - @abc.abstractproperty - def prop(self): #@ - pass - - @abc.abstractmethod - def method1(self): #@ - pass - - some_other_decorator = lambda x: x - @some_other_decorator - def method2(self): #@ - pass - """) - self.assertTrue(methods[0].is_abstract(pass_is_abstract=False)) - self.assertTrue(methods[1].is_abstract(pass_is_abstract=False)) - self.assertFalse(methods[2].is_abstract(pass_is_abstract=False)) - -## def test_raises(self): -## method = self.module2['AbstractClass']['to_override'] -## self.assertEqual([str(term) for term in method.raises()], -## ["Call(Name('NotImplementedError'), [], None, None)"] ) - -## def test_returns(self): -## method = self.module2['AbstractClass']['return_something'] -## # use string comp since Node doesn't handle __cmp__ -## self.assertEqual([str(term) for term in method.returns()], -## ["Const('toto')", "Const(None)"]) - - def test_lambda_pytype(self): - data = ''' - def f(): - g = lambda: None - ''' - astroid = builder.parse(data) - g = list(astroid['f'].ilookup('g'))[0] - self.assertEqual(g.pytype(), '%s.function' % BUILTINS) - - def test_lambda_qname(self): - astroid = builder.parse('lmbd = lambda: None', __name__) - self.assertEqual('%s.' % __name__, astroid['lmbd'].parent.value.qname()) - - def test_is_method(self): - data = ''' - class A: - def meth1(self): - return 1 - @classmethod - def meth2(cls): - return 2 - @staticmethod - def meth3(): - return 3 - - def function(): - return 0 - - @staticmethod - def sfunction(): - return -1 - ''' - astroid = builder.parse(data) - self.assertTrue(astroid['A']['meth1'].is_method()) - self.assertTrue(astroid['A']['meth2'].is_method()) - self.assertTrue(astroid['A']['meth3'].is_method()) - self.assertFalse(astroid['function'].is_method()) - self.assertFalse(astroid['sfunction'].is_method()) - - def test_argnames(self): - if sys.version_info < (3, 0): - code = 'def f(a, (b, c), *args, **kwargs): pass' - else: - code = 'def f(a, b, c, *args, **kwargs): pass' - astroid = builder.parse(code, __name__) - self.assertEqual(astroid['f'].argnames(), ['a', 'b', 'c', 'args', 'kwargs']) - - def test_return_nothing(self): - """test inferred value on a function with empty return""" - data = ''' - def func(): - return - - a = func() - ''' - astroid = builder.parse(data) - call = astroid.body[1].value - func_vals = call.inferred() - self.assertEqual(len(func_vals), 1) - self.assertIsInstance(func_vals[0], nodes.Const) - self.assertIsNone(func_vals[0].value) - - def test_func_instance_attr(self): - """test instance attributes for functions""" - data = """ - def test(): - print(test.bar) - - test.bar = 1 - test() - """ - astroid = builder.parse(data, 'mod') - func = astroid.body[2].value.func.inferred()[0] - self.assertIsInstance(func, nodes.FunctionDef) - self.assertEqual(func.name, 'test') - one = func.getattr('bar')[0].inferred()[0] - self.assertIsInstance(one, nodes.Const) - self.assertEqual(one.value, 1) - - def test_type_builtin_descriptor_subclasses(self): - astroid = builder.parse(""" - class classonlymethod(classmethod): - pass - class staticonlymethod(staticmethod): - pass - - class Node: - @classonlymethod - def clsmethod_subclass(cls): - pass - @classmethod - def clsmethod(cls): - pass - @staticonlymethod - def staticmethod_subclass(cls): - pass - @staticmethod - def stcmethod(cls): - pass - """) - node = astroid._locals['Node'][0] - self.assertEqual(node._locals['clsmethod_subclass'][0].type, - 'classmethod') - self.assertEqual(node._locals['clsmethod'][0].type, - 'classmethod') - self.assertEqual(node._locals['staticmethod_subclass'][0].type, - 'staticmethod') - self.assertEqual(node._locals['stcmethod'][0].type, - 'staticmethod') - - def test_decorator_builtin_descriptors(self): - astroid = builder.parse(""" - def static_decorator(platform=None, order=50): - def wrapper(f): - f.cgm_module = True - f.cgm_module_order = order - f.cgm_module_platform = platform - return staticmethod(f) - return wrapper - - def long_classmethod_decorator(platform=None, order=50): - def wrapper(f): - def wrapper2(f): - def wrapper3(f): - f.cgm_module = True - f.cgm_module_order = order - f.cgm_module_platform = platform - return classmethod(f) - return wrapper3(f) - return wrapper2(f) - return wrapper - - def classmethod_decorator(platform=None): - def wrapper(f): - f.platform = platform - return classmethod(f) - return wrapper - - def classmethod_wrapper(fn): - def wrapper(cls, *args, **kwargs): - result = fn(cls, *args, **kwargs) - return result - - return classmethod(wrapper) - - def staticmethod_wrapper(fn): - def wrapper(*args, **kwargs): - return fn(*args, **kwargs) - return staticmethod(wrapper) - - class SomeClass(object): - @static_decorator() - def static(node, cfg): - pass - @classmethod_decorator() - def classmethod(cls): - pass - @static_decorator - def not_so_static(node): - pass - @classmethod_decorator - def not_so_classmethod(node): - pass - @classmethod_wrapper - def classmethod_wrapped(cls): - pass - @staticmethod_wrapper - def staticmethod_wrapped(): - pass - @long_classmethod_decorator() - def long_classmethod(cls): - pass - """) - node = astroid._locals['SomeClass'][0] - self.assertEqual(node._locals['static'][0].type, - 'staticmethod') - self.assertEqual(node._locals['classmethod'][0].type, - 'classmethod') - self.assertEqual(node._locals['not_so_static'][0].type, - 'method') - self.assertEqual(node._locals['not_so_classmethod'][0].type, - 'method') - self.assertEqual(node._locals['classmethod_wrapped'][0].type, - 'classmethod') - self.assertEqual(node._locals['staticmethod_wrapped'][0].type, - 'staticmethod') - self.assertEqual(node._locals['long_classmethod'][0].type, - 'classmethod') - - def test_igetattr(self): - func = test_utils.extract_node(''' - def test(): - pass - ''') - func._instance_attrs['value'] = [nodes.Const(42)] - value = func.getattr('value') - self.assertEqual(len(value), 1) - self.assertIsInstance(value[0], nodes.Const) - self.assertEqual(value[0].value, 42) - inferred = next(func.igetattr('value')) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - @test_utils.require_version(minver='3.0') - def test_return_annotation_is_not_the_last(self): - func = builder.parse(''' - def test() -> bytes: - pass - pass - return - ''').body[0] - last_child = func.last_child() - self.assertIsInstance(last_child, nodes.Return) - self.assertEqual(func.tolineno, 5) - - -class ClassNodeTest(ModuleLoader, unittest.TestCase): - - def test_dict_interface(self): - _test_dict_interface(self, self.module['YOUPI'], 'method') - - def test_cls_special_attributes_1(self): - cls = self.module['YO'] - self.assertEqual(len(cls.getattr('__bases__')), 1) - self.assertEqual(len(cls.getattr('__name__')), 1) - self.assertIsInstance(cls.getattr('__name__')[0], nodes.Const) - self.assertEqual(cls.getattr('__name__')[0].value, 'YO') - self.assertEqual(len(cls.getattr('__doc__')), 1) - self.assertIsInstance(cls.getattr('__doc__')[0], nodes.Const) - self.assertEqual(cls.getattr('__doc__')[0].value, 'hehe') - self.assertEqual(len(cls.getattr('__module__')), 1) - self.assertIsInstance(cls.getattr('__module__')[0], nodes.Const) - self.assertEqual(cls.getattr('__module__')[0].value, 'data.module') - self.assertEqual(len(cls.getattr('__dict__')), 1) - if not cls.newstyle: - self.assertRaises(NotFoundError, cls.getattr, '__mro__') - for cls in (nodes.List._proxied, nodes.Const(1)._proxied): - self.assertEqual(len(cls.getattr('__bases__')), 1) - self.assertEqual(len(cls.getattr('__name__')), 1) - self.assertEqual(len(cls.getattr('__doc__')), 1, (cls, cls.getattr('__doc__'))) - self.assertEqual(cls.getattr('__doc__')[0].value, cls.doc) - self.assertEqual(len(cls.getattr('__module__')), 1) - self.assertEqual(len(cls.getattr('__dict__')), 1) - self.assertEqual(len(cls.getattr('__mro__')), 1) - - def test__mro__attribute(self): - node = test_utils.extract_node(''' - class A(object): pass - class B(object): pass - class C(A, B): pass - ''') - mro = node.getattr('__mro__')[0] - self.assertIsInstance(mro, nodes.Tuple) - self.assertEqual(mro.elts, node.mro()) - - def test__bases__attribute(self): - node = test_utils.extract_node(''' - class A(object): pass - class B(object): pass - class C(A, B): pass - class D(C): pass - ''') - bases = node.getattr('__bases__')[0] - self.assertIsInstance(bases, nodes.Tuple) - self.assertEqual(len(bases.elts), 1) - self.assertIsInstance(bases.elts[0], nodes.ClassDef) - self.assertEqual(bases.elts[0].name, 'C') - - def test_cls_special_attributes_2(self): - astroid = builder.parse(''' - class A: pass - class B: pass - - A.__bases__ += (B,) - ''', __name__) - self.assertEqual(len(astroid['A'].getattr('__bases__')), 2) - self.assertIsInstance(astroid['A'].getattr('__bases__')[0], nodes.Tuple) - self.assertIsInstance(astroid['A'].getattr('__bases__')[1], nodes.AssignAttr) - - def test_instance_special_attributes(self): - for inst in (Instance(self.module['YO']), nodes.List(), nodes.Const(1)): - self.assertRaises(NotFoundError, inst.getattr, '__mro__') - self.assertRaises(NotFoundError, inst.getattr, '__bases__') - self.assertRaises(NotFoundError, inst.getattr, '__name__') - self.assertEqual(len(inst.getattr('__dict__')), 1) - self.assertEqual(len(inst.getattr('__doc__')), 1) - - def test_navigation(self): - klass = self.module['YO'] - self.assertEqual(klass.statement(), klass) - l_sibling = klass.previous_sibling() - self.assertTrue(isinstance(l_sibling, nodes.FunctionDef), l_sibling) - self.assertEqual(l_sibling.name, 'global_access') - r_sibling = klass.next_sibling() - self.assertIsInstance(r_sibling, nodes.ClassDef) - self.assertEqual(r_sibling.name, 'YOUPI') - - def test_local_attr_ancestors(self): - module = builder.parse(''' - class A(): - def __init__(self): pass - class B(A): pass - class C(B): pass - class D(object): pass - class F(): pass - class E(F, D): pass - ''') - # Test old-style (Python 2) / new-style (Python 3+) ancestors lookups - klass2 = module['C'] - it = klass2.local_attr_ancestors('__init__') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'A') - if sys.version_info[0] == 2: - self.assertRaises(StopIteration, partial(next, it)) - else: - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'object') - self.assertRaises(StopIteration, partial(next, it)) - - it = klass2.local_attr_ancestors('method') - self.assertRaises(StopIteration, partial(next, it)) - - # Test mixed-style ancestor lookups - klass2 = module['E'] - it = klass2.local_attr_ancestors('__init__') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'object') - self.assertRaises(StopIteration, partial(next, it)) - - def test_local_attr_mro(self): - module = builder.parse(''' - class A(object): - def __init__(self): pass - class B(A): - def __init__(self, arg, arg2): pass - class C(A): pass - class D(C, B): pass - ''') - dclass = module['D'] - init = dclass.local_attr('__init__')[0] - self.assertIsInstance(init, nodes.FunctionDef) - self.assertEqual(init.parent.name, 'B') - - cclass = module['C'] - init = cclass.local_attr('__init__')[0] - self.assertIsInstance(init, nodes.FunctionDef) - self.assertEqual(init.parent.name, 'A') - - ancestors = list(dclass.local_attr_ancestors('__init__')) - self.assertEqual([node.name for node in ancestors], ['B', 'A', 'object']) - - def test_instance_attr_ancestors(self): - klass2 = self.module['YOUPI'] - it = klass2.instance_attr_ancestors('yo') - anc_klass = next(it) - self.assertIsInstance(anc_klass, nodes.ClassDef) - self.assertEqual(anc_klass.name, 'YO') - self.assertRaises(StopIteration, partial(next, it)) - klass2 = self.module['YOUPI'] - it = klass2.instance_attr_ancestors('member') - self.assertRaises(StopIteration, partial(next, it)) - - def test_methods(self): - expected_methods = {'__init__', 'class_method', 'method', 'static_method'} - klass2 = self.module['YOUPI'] - methods = {m.name for m in klass2.methods()} - self.assertTrue( - methods.issuperset(expected_methods)) - methods = {m.name for m in klass2.mymethods()} - self.assertSetEqual(expected_methods, methods) - klass2 = self.module2['Specialization'] - methods = {m.name for m in klass2.mymethods()} - self.assertSetEqual(set([]), methods) - method_locals = klass2.local_attr('method') - self.assertEqual(len(method_locals), 1) - self.assertEqual(method_locals[0].name, 'method') - self.assertRaises(NotFoundError, klass2.local_attr, 'nonexistant') - methods = {m.name for m in klass2.methods()} - self.assertTrue(methods.issuperset(expected_methods)) - - #def test_rhs(self): - # my_dict = self.module['MY_DICT'] - # self.assertIsInstance(my_dict.rhs(), nodes.Dict) - # a = self.module['YO']['a'] - # value = a.rhs() - # self.assertIsInstance(value, nodes.Const) - # self.assertEqual(value.value, 1) - - @unittest.skipIf(sys.version_info[0] >= 3, "Python 2 class semantics required.") - def test_ancestors(self): - klass = self.module['YOUPI'] - self.assertEqual(['YO'], [a.name for a in klass.ancestors()]) - klass = self.module2['Specialization'] - self.assertEqual(['YOUPI', 'YO'], [a.name for a in klass.ancestors()]) - - @unittest.skipIf(sys.version_info[0] < 3, "Python 3 class semantics required.") - def test_ancestors_py3(self): - klass = self.module['YOUPI'] - self.assertEqual(['YO', 'object'], [a.name for a in klass.ancestors()]) - klass = self.module2['Specialization'] - self.assertEqual(['YOUPI', 'YO', 'object'], [a.name for a in klass.ancestors()]) - - def test_type(self): - klass = self.module['YOUPI'] - self.assertEqual(klass.type, 'class') - klass = self.module2['Metaclass'] - self.assertEqual(klass.type, 'metaclass') - klass = self.module2['MyException'] - self.assertEqual(klass.type, 'exception') - klass = self.module2['MyError'] - self.assertEqual(klass.type, 'exception') - # the following class used to be detected as a metaclass - # after the fix which used instance._proxied in .ancestors(), - # when in fact it is a normal class - klass = self.module2['NotMetaclass'] - self.assertEqual(klass.type, 'class') - - def test_inner_classes(self): - eee = self.nonregr['Ccc']['Eee'] - self.assertEqual([n.name for n in eee.ancestors()], ['Ddd', 'Aaa', 'object']) - - - def test_classmethod_attributes(self): - data = ''' - class WebAppObject(object): - def registered(cls, application): - cls.appli = application - cls.schema = application.schema - cls.config = application.config - return cls - registered = classmethod(registered) - ''' - astroid = builder.parse(data, __name__) - cls = astroid['WebAppObject'] - self.assertEqual(sorted(cls._locals.keys()), - ['appli', 'config', 'registered', 'schema']) - - def test_class_getattr(self): - data = ''' - class WebAppObject(object): - appli = application - appli += 2 - del self.appli - ''' - astroid = builder.parse(data, __name__) - cls = astroid['WebAppObject'] - # test del statement not returned by getattr - self.assertEqual(len(cls.getattr('appli')), 2) - - - def test_instance_getattr(self): - data = ''' - class WebAppObject(object): - def __init__(self, application): - self.appli = application - self.appli += 2 - del self.appli - ''' - astroid = builder.parse(data) - inst = Instance(astroid['WebAppObject']) - # test del statement not returned by getattr - self.assertEqual(len(inst.getattr('appli')), 2) - - - def test_instance_getattr_with_class_attr(self): - data = ''' - class Parent: - aa = 1 - cc = 1 - - class Klass(Parent): - aa = 0 - bb = 0 - - def incr(self, val): - self.cc = self.aa - if val > self.aa: - val = self.aa - if val < self.bb: - val = self.bb - self.aa += val - ''' - astroid = builder.parse(data) - inst = Instance(astroid['Klass']) - self.assertEqual(len(inst.getattr('aa')), 3, inst.getattr('aa')) - self.assertEqual(len(inst.getattr('bb')), 1, inst.getattr('bb')) - self.assertEqual(len(inst.getattr('cc')), 2, inst.getattr('cc')) - - - def test_getattr_method_transform(self): - data = ''' - class Clazz(object): - - def m1(self, value): - self.value = value - m2 = m1 - - def func(arg1, arg2): - "function that will be used as a method" - return arg1.value + arg2 - - Clazz.m3 = func - inst = Clazz() - inst.m4 = func - ''' - astroid = builder.parse(data) - cls = astroid['Clazz'] - # test del statement not returned by getattr - for method in ('m1', 'm2', 'm3'): - inferred = list(cls.igetattr(method)) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], UnboundMethod) - inferred = list(Instance(cls).igetattr(method)) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], BoundMethod) - inferred = list(Instance(cls).igetattr('m4')) - self.assertEqual(len(inferred), 1) - self.assertIsInstance(inferred[0], nodes.FunctionDef) - - def test_getattr_from_grandpa(self): - data = ''' - class Future: - attr = 1 - - class Present(Future): - pass - - class Past(Present): - pass - ''' - astroid = builder.parse(data) - past = astroid['Past'] - attr = past.getattr('attr') - self.assertEqual(len(attr), 1) - attr1 = attr[0] - self.assertIsInstance(attr1, nodes.AssignName) - self.assertEqual(attr1.name, 'attr') - - def test_function_with_decorator_lineno(self): - data = ''' - @f(a=2, - b=3) - def g1(x): - print(x) - - @f(a=2, - b=3) - def g2(): - pass - ''' - astroid = builder.parse(data) - self.assertEqual(astroid['g1'].fromlineno, 4) - self.assertEqual(astroid['g1'].tolineno, 5) - self.assertEqual(astroid['g2'].fromlineno, 9) - self.assertEqual(astroid['g2'].tolineno, 10) - - @test_utils.require_version(maxver='3.0') - def test_simple_metaclass(self): - astroid = builder.parse(""" - class Test(object): - __metaclass__ = type - """) - klass = astroid['Test'] - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'type') - - def test_metaclass_error(self): - astroid = builder.parse(""" - class Test(object): - __metaclass__ = typ - """) - klass = astroid['Test'] - self.assertFalse(klass.metaclass()) - - @test_utils.require_version(maxver='3.0') - def test_metaclass_imported(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test(object): - __metaclass__ = ABCMeta - """) - klass = astroid['Test'] - - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - def test_metaclass_yes_leak(self): - astroid = builder.parse(""" - # notice `ab` instead of `abc` - from ab import ABCMeta - - class Meta(object): - __metaclass__ = ABCMeta - """) - klass = astroid['Meta'] - self.assertIsNone(klass.metaclass()) - - @test_utils.require_version(maxver='3.0') - def test_newstyle_and_metaclass_good(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test: - __metaclass__ = ABCMeta - """) - klass = astroid['Test'] - self.assertTrue(klass.newstyle) - self.assertEqual(klass.metaclass().name, 'ABCMeta') - astroid = builder.parse(""" - from abc import ABCMeta - __metaclass__ = ABCMeta - class Test: - pass - """) - klass = astroid['Test'] - self.assertTrue(klass.newstyle) - self.assertEqual(klass.metaclass().name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_nested_metaclass(self): - astroid = builder.parse(""" - from abc import ABCMeta - class A(object): - __metaclass__ = ABCMeta - class B: pass - - __metaclass__ = ABCMeta - class C: - __metaclass__ = type - class D: pass - """) - a = astroid['A'] - b = a._locals['B'][0] - c = astroid['C'] - d = c._locals['D'][0] - self.assertEqual(a.metaclass().name, 'ABCMeta') - self.assertFalse(b.newstyle) - self.assertIsNone(b.metaclass()) - self.assertEqual(c.metaclass().name, 'type') - self.assertEqual(d.metaclass().name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_parent_metaclass(self): - astroid = builder.parse(""" - from abc import ABCMeta - class Test: - __metaclass__ = ABCMeta - class SubTest(Test): pass - """) - klass = astroid['SubTest'] - self.assertTrue(klass.newstyle) - metaclass = klass.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.name, 'ABCMeta') - - @test_utils.require_version(maxver='3.0') - def test_metaclass_ancestors(self): - astroid = builder.parse(""" - from abc import ABCMeta - - class FirstMeta(object): - __metaclass__ = ABCMeta - - class SecondMeta(object): - __metaclass__ = type - - class Simple(object): - pass - - class FirstImpl(FirstMeta): pass - class SecondImpl(FirstImpl): pass - class ThirdImpl(Simple, SecondMeta): - pass - """) - classes = { - 'ABCMeta': ('FirstImpl', 'SecondImpl'), - 'type': ('ThirdImpl', ) - } - for metaclass, names in classes.items(): - for name in names: - impl = astroid[name] - meta = impl.metaclass() - self.assertIsInstance(meta, nodes.ClassDef) - self.assertEqual(meta.name, metaclass) - - def test_metaclass_type(self): - klass = test_utils.extract_node(""" - def with_metaclass(meta, base=object): - return meta("NewBase", (base, ), {}) - - class ClassWithMeta(with_metaclass(type)): #@ - pass - """) - self.assertEqual( - ['NewBase', 'object'], - [base.name for base in klass.ancestors()]) - - def test_no_infinite_metaclass_loop(self): - klass = test_utils.extract_node(""" - class SSS(object): - - class JJJ(object): - pass - - @classmethod - def Init(cls): - cls.JJJ = type('JJJ', (cls.JJJ,), {}) - - class AAA(SSS): - pass - - class BBB(AAA.JJJ): - pass - """) - self.assertFalse(scoped_nodes._is_metaclass(klass)) - ancestors = [base.name for base in klass.ancestors()] - self.assertIn('object', ancestors) - self.assertIn('JJJ', ancestors) - - def test_no_infinite_metaclass_loop_with_redefine(self): - nodes = test_utils.extract_node(""" - import datetime - - class A(datetime.date): #@ - @classmethod - def now(cls): - return cls() - - class B(datetime.date): #@ - pass - - datetime.date = A - datetime.date = B - """) - for klass in nodes: - self.assertEqual(None, klass.metaclass()) - - def test_metaclass_generator_hack(self): - klass = test_utils.extract_node(""" - import six - - class WithMeta(six.with_metaclass(type, object)): #@ - pass - """) - self.assertEqual( - ['object'], - [base.name for base in klass.ancestors()]) - self.assertEqual( - 'type', klass.metaclass().name) - - def test_using_six_add_metaclass(self): - klass = test_utils.extract_node(''' - import six - import abc - - @six.add_metaclass(abc.ABCMeta) - class WithMeta(object): - pass - ''') - inferred = next(klass.infer()) - metaclass = inferred.metaclass() - self.assertIsInstance(metaclass, scoped_nodes.ClassDef) - self.assertEqual(metaclass.qname(), 'abc.ABCMeta') - - def test_using_invalid_six_add_metaclass_call(self): - klass = test_utils.extract_node(''' - import six - @six.add_metaclass() - class Invalid(object): - pass - ''') - inferred = next(klass.infer()) - self.assertIsNone(inferred.metaclass()) - - def test_nonregr_infer_callresult(self): - astroid = builder.parse(""" - class Delegate(object): - def __get__(self, obj, cls): - return getattr(obj._subject, self.attribute) - - class CompositeBuilder(object): - __call__ = Delegate() - - builder = CompositeBuilder(result, composite) - tgts = builder() - """) - instance = astroid['tgts'] - # used to raise "'_Yes' object is not iterable", see - # https://bitbucket.org/logilab/astroid/issue/17 - self.assertEqual(list(instance.infer()), [util.YES]) - - def test_slots(self): - astroid = builder.parse(""" - from collections import deque - from textwrap import dedent - - class First(object): #@ - __slots__ = ("a", "b", 1) - class Second(object): #@ - __slots__ = "a" - class Third(object): #@ - __slots__ = deque(["a", "b", "c"]) - class Fourth(object): #@ - __slots__ = {"a": "a", "b": "b"} - class Fifth(object): #@ - __slots__ = list - class Sixth(object): #@ - __slots__ = "" - class Seventh(object): #@ - __slots__ = dedent.__name__ - class Eight(object): #@ - __slots__ = ("parens") - class Ninth(object): #@ - pass - class Ten(object): #@ - __slots__ = dict({"a": "b", "c": "d"}) - """) - expected = [ - ('First', ('a', 'b')), - ('Second', ('a', )), - ('Third', None), - ('Fourth', ('a', 'b')), - ('Fifth', None), - ('Sixth', None), - ('Seventh', ('dedent', )), - ('Eight', ('parens', )), - ('Ninth', None), - ('Ten', ('a', 'c')), - ] - for cls, expected_value in expected: - slots = astroid[cls].slots() - if expected_value is None: - self.assertIsNone(slots) - else: - self.assertEqual(list(expected_value), - [node.value for node in slots]) - - @test_utils.require_version(maxver='3.0') - def test_slots_py2(self): - module = builder.parse(""" - class UnicodeSlots(object): - __slots__ = (u"a", u"b", "c") - """) - slots = module['UnicodeSlots'].slots() - self.assertEqual(len(slots), 3) - self.assertEqual(slots[0].value, "a") - self.assertEqual(slots[1].value, "b") - self.assertEqual(slots[2].value, "c") - - @test_utils.require_version(maxver='3.0') - def test_slots_py2_not_implemented(self): - module = builder.parse(""" - class OldStyle: - __slots__ = ("a", "b") - """) - msg = "The concept of slots is undefined for old-style classes." - with self.assertRaises(NotImplementedError) as cm: - module['OldStyle'].slots() - self.assertEqual(str(cm.exception), msg) - - def test_slots_empty_list_of_slots(self): - module = builder.parse(""" - class Klass(object): - __slots__ = () - """) - cls = module['Klass'] - self.assertEqual(cls.slots(), []) - - def test_slots_taken_from_parents(self): - module = builder.parse(''' - class FirstParent(object): - __slots__ = ('a', 'b', 'c') - class SecondParent(FirstParent): - __slots__ = ('d', 'e') - class Third(SecondParent): - __slots__ = ('d', ) - ''') - cls = module['Third'] - slots = cls.slots() - self.assertEqual(sorted(set(slot.value for slot in slots)), - ['a', 'b', 'c', 'd', 'e']) - - def test_all_ancestors_need_slots(self): - module = builder.parse(''' - class A(object): - __slots__ = ('a', ) - class B(A): pass - class C(B): - __slots__ = ('a', ) - ''') - cls = module['C'] - self.assertIsNone(cls.slots()) - cls = module['B'] - self.assertIsNone(cls.slots()) - - def assertEqualMro(self, klass, expected_mro): - self.assertEqual( - [member.name for member in klass.mro()], - expected_mro) - - @test_utils.require_version(maxver='3.0') - def test_no_mro_for_old_style(self): - node = test_utils.extract_node(""" - class Old: pass""") - with self.assertRaises(NotImplementedError) as cm: - node.mro() - self.assertEqual(str(cm.exception), "Could not obtain mro for " - "old-style classes.") - - @test_utils.require_version(maxver='3.0') - def test_combined_newstyle_oldstyle_in_mro(self): - node = test_utils.extract_node(''' - class Old: - pass - class New(object): - pass - class New1(object): - pass - class New2(New, New1): - pass - class NewOld(New2, Old): #@ - pass - ''') - self.assertEqualMro(node, ['NewOld', 'New2', 'New', 'New1', 'object', 'Old']) - self.assertTrue(node.newstyle) - - def test_with_metaclass_mro(self): - astroid = builder.parse(""" - import six - - class C(object): - pass - class B(C): - pass - class A(six.with_metaclass(type, B)): - pass - """) - self.assertEqualMro(astroid['A'], ['A', 'B', 'C', 'object']) - - def test_mro(self): - astroid = builder.parse(""" - class C(object): pass - class D(dict, C): pass - - class A1(object): pass - class B1(A1): pass - class C1(A1): pass - class D1(B1, C1): pass - class E1(C1, B1): pass - class F1(D1, E1): pass - class G1(E1, D1): pass - - class Boat(object): pass - class DayBoat(Boat): pass - class WheelBoat(Boat): pass - class EngineLess(DayBoat): pass - class SmallMultihull(DayBoat): pass - class PedalWheelBoat(EngineLess, WheelBoat): pass - class SmallCatamaran(SmallMultihull): pass - class Pedalo(PedalWheelBoat, SmallCatamaran): pass - - class OuterA(object): - class Inner(object): - pass - class OuterB(OuterA): - class Inner(OuterA.Inner): - pass - class OuterC(OuterA): - class Inner(OuterA.Inner): - pass - class OuterD(OuterC): - class Inner(OuterC.Inner, OuterB.Inner): - pass - class Duplicates(str, str): pass - - """) - self.assertEqualMro(astroid['D'], ['D', 'dict', 'C', 'object']) - self.assertEqualMro(astroid['D1'], ['D1', 'B1', 'C1', 'A1', 'object']) - self.assertEqualMro(astroid['E1'], ['E1', 'C1', 'B1', 'A1', 'object']) - with self.assertRaises(InconsistentMroError) as cm: - astroid['F1'].mro() - self.assertEqual(str(cm.exception), - "Cannot create a consistent method resolution order " - "for bases (B1, C1, A1, object), " - "(C1, B1, A1, object)") - - with self.assertRaises(InconsistentMroError) as cm: - astroid['G1'].mro() - self.assertEqual(str(cm.exception), - "Cannot create a consistent method resolution order " - "for bases (C1, B1, A1, object), " - "(B1, C1, A1, object)") - - self.assertEqualMro( - astroid['PedalWheelBoat'], - ["PedalWheelBoat", "EngineLess", - "DayBoat", "WheelBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid["SmallCatamaran"], - ["SmallCatamaran", "SmallMultihull", "DayBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid["Pedalo"], - ["Pedalo", "PedalWheelBoat", "EngineLess", "SmallCatamaran", - "SmallMultihull", "DayBoat", "WheelBoat", "Boat", "object"]) - - self.assertEqualMro( - astroid['OuterD']['Inner'], - ['Inner', 'Inner', 'Inner', 'Inner', 'object']) - - with self.assertRaises(DuplicateBasesError) as cm: - astroid['Duplicates'].mro() - self.assertEqual(str(cm.exception), "Duplicates found in the mro.") - self.assertTrue(issubclass(cm.exception.__class__, MroError)) - self.assertTrue(issubclass(cm.exception.__class__, ResolveError)) - - def test_generator_from_infer_call_result_parent(self): - func = test_utils.extract_node(""" - import contextlib - - @contextlib.contextmanager - def test(): #@ - yield - """) - result = next(func.infer_call_result(func)) - self.assertIsInstance(result, Generator) - self.assertEqual(result.parent, func) - - def test_type_three_arguments(self): - classes = test_utils.extract_node(""" - type('A', (object, ), {"a": 1, "b": 2, missing: 3}) #@ - """) - first = next(classes.infer()) - self.assertIsInstance(first, nodes.ClassDef) - self.assertEqual(first.name, "A") - self.assertEqual(first.basenames, ["object"]) - self.assertIsInstance(first["a"], nodes.Const) - self.assertEqual(first["a"].value, 1) - self.assertIsInstance(first["b"], nodes.Const) - self.assertEqual(first["b"].value, 2) - with self.assertRaises(NotFoundError): - first.getattr("missing") - - def test_implicit_metaclass(self): - cls = test_utils.extract_node(""" - class A(object): - pass - """) - type_cls = scoped_nodes.builtin_lookup("type")[1][0] - self.assertEqual(cls.implicit_metaclass(), type_cls) - - @test_utils.require_version(maxver='3.0') - def test_implicit_metaclass_is_none(self): - cls = test_utils.extract_node(""" - class A: pass - """) - self.assertIsNone(cls.implicit_metaclass()) - - def test_local_attr_invalid_mro(self): - cls = test_utils.extract_node(""" - # A has an invalid MRO, local_attr should fallback - # to using .ancestors. - class A(object, object): - test = 42 - class B(A): #@ - pass - """) - local = cls.local_attr('test')[0] - inferred = next(local.infer()) - self.assertIsInstance(inferred, nodes.Const) - self.assertEqual(inferred.value, 42) - - def test_has_dynamic_getattr(self): - module = builder.parse(""" - class Getattr(object): - def __getattr__(self, attrname): - pass - - class Getattribute(object): - def __getattribute__(self, attrname): - pass - - class ParentGetattr(Getattr): - pass - """) - self.assertTrue(module['Getattr'].has_dynamic_getattr()) - self.assertTrue(module['Getattribute'].has_dynamic_getattr()) - self.assertTrue(module['ParentGetattr'].has_dynamic_getattr()) - - # Test that objects analyzed through the live introspection - # aren't considered to have dynamic getattr implemented. - import datetime - astroid_builder = builder.AstroidBuilder() - module = astroid_builder.module_build(datetime) - self.assertFalse(module['timedelta'].has_dynamic_getattr()) - - def test_duplicate_bases_namedtuple(self): - module = builder.parse(""" - import collections - _A = collections.namedtuple('A', 'a') - - class A(_A): pass - - class B(A): pass - """) - self.assertRaises(DuplicateBasesError, module['B'].mro) - - def test_instance_bound_method_lambdas(self): - ast_nodes = test_utils.extract_node(''' - class Test(object): #@ - lam = lambda self: self - not_method = lambda xargs: xargs - Test() #@ - ''') - cls = next(ast_nodes[0].infer()) - self.assertIsInstance(next(cls.igetattr('lam')), scoped_nodes.Lambda) - self.assertIsInstance(next(cls.igetattr('not_method')), scoped_nodes.Lambda) - - instance = next(ast_nodes[1].infer()) - lam = next(instance.igetattr('lam')) - self.assertIsInstance(lam, BoundMethod) - not_method = next(instance.igetattr('not_method')) - self.assertIsInstance(not_method, scoped_nodes.Lambda) - - def test_class_extra_decorators_frame_is_not_class(self): - ast_node = test_utils.extract_node(''' - def ala(): - def bala(): #@ - func = 42 - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_callfunc_are_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - func = 42 - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_assignment_names_are_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - def __init__(self): - self.func = staticmethod(func) - - ''') - self.assertEqual(ast_node.extra_decorators, []) - - def test_class_extra_decorators_only_same_name_considered(self): - ast_node = test_utils.extract_node(''' - class Ala(object): - def func(self): #@ - pass - bala = staticmethod(func) - ''') - self.assertEqual(ast_node.extra_decorators, []) - self.assertEqual(ast_node.type, 'method') - - def test_class_extra_decorators(self): - static_method, clsmethod = test_utils.extract_node(''' - class Ala(object): - def static(self): #@ - pass - def class_method(self): #@ - pass - class_method = classmethod(class_method) - static = staticmethod(static) - ''') - self.assertEqual(len(clsmethod.extra_decorators), 1) - self.assertEqual(clsmethod.type, 'classmethod') - self.assertEqual(len(static_method.extra_decorators), 1) - self.assertEqual(static_method.type, 'staticmethod') - - def test_extra_decorators_only_class_level_assignments(self): - node = test_utils.extract_node(''' - def _bind(arg): - return arg.bind - - class A(object): - @property - def bind(self): - return 42 - def irelevant(self): - # This is important, because it used to trigger - # a maximum recursion error. - bind = _bind(self) - return bind - A() #@ - ''') - inferred = next(node.infer()) - bind = next(inferred.igetattr('bind')) - self.assertIsInstance(bind, nodes.Const) - self.assertEqual(bind.value, 42) - parent = bind.scope() - self.assertEqual(len(parent.extra_decorators), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_transforms.py b/pymode/libs/astroid/tests/unittest_transforms.py deleted file mode 100644 index 1553bfc4..00000000 --- a/pymode/libs/astroid/tests/unittest_transforms.py +++ /dev/null @@ -1,245 +0,0 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . - -from __future__ import print_function - -import contextlib -import time -import unittest - -from astroid import builder -from astroid import nodes -from astroid import parse -from astroid import transforms - - -@contextlib.contextmanager -def add_transform(manager, node, transform, predicate=None): - manager.register_transform(node, transform, predicate) - try: - yield - finally: - manager.unregister_transform(node, transform, predicate) - - -class TestTransforms(unittest.TestCase): - - def setUp(self): - self.transformer = transforms.TransformVisitor() - - def parse_transform(self, code): - module = parse(code, apply_transforms=False) - return self.transformer.visit(module) - - def test_function_inlining_transform(self): - def transform_call(node): - # Let's do some function inlining - inferred = next(node.infer()) - return inferred - - self.transformer.register_transform(nodes.Call, - transform_call) - - module = self.parse_transform(''' - def test(): return 42 - test() #@ - ''') - - self.assertIsInstance(module.body[1], nodes.Expr) - self.assertIsInstance(module.body[1].value, nodes.Const) - self.assertEqual(module.body[1].value.value, 42) - - def test_recursive_transforms_into_astroid_fields(self): - # Test that the transformer walks properly the tree - # by going recursively into the _astroid_fields per each node. - def transform_compare(node): - # Let's check the values of the ops - _, right = node.ops[0] - # Assume they are Consts and they were transformed before - # us. - return nodes.const_factory(node.left.value < right.value) - - def transform_name(node): - # Should be Consts - return next(node.infer()) - - self.transformer.register_transform(nodes.Compare, transform_compare) - self.transformer.register_transform(nodes.Name, transform_name) - - module = self.parse_transform(''' - a = 42 - b = 24 - a < b - ''') - - self.assertIsInstance(module.body[2], nodes.Expr) - self.assertIsInstance(module.body[2].value, nodes.Const) - self.assertFalse(module.body[2].value.value) - - def test_transform_patches_locals(self): - def transform_function(node): - assign = nodes.Assign() - name = nodes.AssignName() - name.name = 'value' - assign.targets = [name] - assign.value = nodes.const_factory(42) - node.body.append(assign) - - self.transformer.register_transform(nodes.FunctionDef, - transform_function) - - module = self.parse_transform(''' - def test(): - pass - ''') - - func = module.body[0] - self.assertEqual(len(func.body), 2) - self.assertIsInstance(func.body[1], nodes.Assign) - self.assertEqual(func.body[1].as_string(), 'value = 42') - - def test_predicates(self): - def transform_call(node): - inferred = next(node.infer()) - return inferred - - def should_inline(node): - return node.func.name.startswith('inlineme') - - self.transformer.register_transform(nodes.Call, - transform_call, - should_inline) - - module = self.parse_transform(''' - def inlineme_1(): - return 24 - def dont_inline_me(): - return 42 - def inlineme_2(): - return 2 - inlineme_1() - dont_inline_me() - inlineme_2() - ''') - values = module.body[-3:] - self.assertIsInstance(values[0], nodes.Expr) - self.assertIsInstance(values[0].value, nodes.Const) - self.assertEqual(values[0].value.value, 24) - self.assertIsInstance(values[1], nodes.Expr) - self.assertIsInstance(values[1].value, nodes.Call) - self.assertIsInstance(values[2], nodes.Expr) - self.assertIsInstance(values[2].value, nodes.Const) - self.assertEqual(values[2].value.value, 2) - - def test_transforms_are_separated(self): - # Test that the transforming is done at a separate - # step, which means that we are not doing inference - # on a partially constructred tree anymore, which was the - # source of crashes in the past when certain inference rules - # were used in a transform. - def transform_function(node): - if node.decorators: - for decorator in node.decorators.nodes: - inferred = next(decorator.infer()) - if inferred.qname() == 'abc.abstractmethod': - return next(node.infer_call_result(node)) - - manager = builder.MANAGER - with add_transform(manager, nodes.FunctionDef, transform_function): - module = builder.parse(''' - import abc - from abc import abstractmethod - - class A(object): - @abc.abstractmethod - def ala(self): - return 24 - - @abstractmethod - def bala(self): - return 42 - ''') - - cls = module['A'] - ala = cls.body[0] - bala = cls.body[1] - self.assertIsInstance(ala, nodes.Const) - self.assertEqual(ala.value, 24) - self.assertIsInstance(bala, nodes.Const) - self.assertEqual(bala.value, 42) - - def test_transforms_are_called_for_builtin_modules(self): - # Test that transforms are called for builtin modules. - def transform_function(node): - name = nodes.AssignName() - name.name = 'value' - node.args.args = [name] - return node - - manager = builder.MANAGER - predicate = lambda node: node.root().name == 'time' - with add_transform(manager, nodes.FunctionDef, - transform_function, predicate): - builder_instance = builder.AstroidBuilder() - module = builder_instance.module_build(time) - - asctime = module['asctime'] - self.assertEqual(len(asctime.args.args), 1) - self.assertIsInstance(asctime.args.args[0], nodes.AssignName) - self.assertEqual(asctime.args.args[0].name, 'value') - - def test_builder_apply_transforms(self): - def transform_function(node): - return nodes.const_factory(42) - - manager = builder.MANAGER - with add_transform(manager, nodes.FunctionDef, transform_function): - astroid_builder = builder.AstroidBuilder(apply_transforms=False) - module = astroid_builder.string_build('''def test(): pass''') - - # The transform wasn't applied. - self.assertIsInstance(module.body[0], nodes.FunctionDef) - - def test_transform_crashes_on_is_subtype_of(self): - # Test that we don't crash when having is_subtype_of - # in a transform, as per issue #188. This happened - # before, when the transforms weren't in their own step. - def transform_class(cls): - if cls.is_subtype_of('django.db.models.base.Model'): - return cls - return cls - - self.transformer.register_transform(nodes.ClassDef, - transform_class) - - self.parse_transform(''' - # Change environ to automatically call putenv() if it exists - import os - putenv = os.putenv - try: - # This will fail if there's no putenv - putenv - except NameError: - pass - else: - import UserDict - ''') - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/tests/unittest_utils.py b/pymode/libs/astroid/tests/unittest_utils.py deleted file mode 100644 index ef832252..00000000 --- a/pymode/libs/astroid/tests/unittest_utils.py +++ /dev/null @@ -1,124 +0,0 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -import unittest - -from astroid import builder -from astroid import InferenceError -from astroid import nodes -from astroid import node_classes -from astroid import test_utils -from astroid import util as astroid_util - - -class InferenceUtil(unittest.TestCase): - - def test_not_exclusive(self): - module = builder.parse(""" - x = 10 - for x in range(5): - print (x) - - if x > 0: - print ('#' * x) - """, __name__, __file__) - xass1 = module.locals['x'][0] - assert xass1.lineno == 2 - xnames = [n for n in module.nodes_of_class(nodes.Name) if n.name == 'x'] - assert len(xnames) == 3 - assert xnames[1].lineno == 6 - self.assertEqual(node_classes.are_exclusive(xass1, xnames[1]), False) - self.assertEqual(node_classes.are_exclusive(xass1, xnames[2]), False) - - def test_if(self): - module = builder.parse(''' - if 1: - a = 1 - a = 2 - elif 2: - a = 12 - a = 13 - else: - a = 3 - a = 4 - ''') - a1 = module.locals['a'][0] - a2 = module.locals['a'][1] - a3 = module.locals['a'][2] - a4 = module.locals['a'][3] - a5 = module.locals['a'][4] - a6 = module.locals['a'][5] - self.assertEqual(node_classes.are_exclusive(a1, a2), False) - self.assertEqual(node_classes.are_exclusive(a1, a3), True) - self.assertEqual(node_classes.are_exclusive(a1, a5), True) - self.assertEqual(node_classes.are_exclusive(a3, a5), True) - self.assertEqual(node_classes.are_exclusive(a3, a4), False) - self.assertEqual(node_classes.are_exclusive(a5, a6), False) - - def test_try_except(self): - module = builder.parse(''' - try: - def exclusive_func2(): - "docstring" - except TypeError: - def exclusive_func2(): - "docstring" - except: - def exclusive_func2(): - "docstring" - else: - def exclusive_func2(): - "this one redefine the one defined line 42" - ''') - f1 = module.locals['exclusive_func2'][0] - f2 = module.locals['exclusive_func2'][1] - f3 = module.locals['exclusive_func2'][2] - f4 = module.locals['exclusive_func2'][3] - self.assertEqual(node_classes.are_exclusive(f1, f2), True) - self.assertEqual(node_classes.are_exclusive(f1, f3), True) - self.assertEqual(node_classes.are_exclusive(f1, f4), False) - self.assertEqual(node_classes.are_exclusive(f2, f4), True) - self.assertEqual(node_classes.are_exclusive(f3, f4), True) - self.assertEqual(node_classes.are_exclusive(f3, f2), True) - - self.assertEqual(node_classes.are_exclusive(f2, f1), True) - self.assertEqual(node_classes.are_exclusive(f4, f1), False) - self.assertEqual(node_classes.are_exclusive(f4, f2), True) - - def test_unpack_infer_uninferable_nodes(self): - node = test_utils.extract_node(''' - x = [A] * 1 - f = [x, [A] * 2] - f - ''') - inferred = next(node.infer()) - unpacked = list(node_classes.unpack_infer(inferred)) - self.assertEqual(len(unpacked), 3) - self.assertTrue(all(elt is astroid_util.YES - for elt in unpacked)) - - def test_unpack_infer_empty_tuple(self): - node = test_utils.extract_node(''' - () - ''') - inferred = next(node.infer()) - with self.assertRaises(InferenceError): - list(node_classes.unpack_infer(inferred)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/astroid/transforms.py b/pymode/libs/astroid/transforms.py index 5d8fc91b..852b9854 100644 --- a/pymode/libs/astroid/transforms.py +++ b/pymode/libs/astroid/transforms.py @@ -1,20 +1,8 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + import collections import warnings @@ -69,8 +57,8 @@ def _visit_generic(self, node): return [self._visit_generic(child) for child in node] elif isinstance(node, tuple): return tuple(self._visit_generic(child) for child in node) - else: - return self._visit(node) + + return self._visit(node) def register_transform(self, node_class, transform, predicate=None): """Register `transform(node)` function to be applied on the given diff --git a/pymode/libs/astroid/util.py b/pymode/libs/astroid/util.py index 44e2039d..6d2d0177 100644 --- a/pymode/libs/astroid/util.py +++ b/pymode/libs/astroid/util.py @@ -1,89 +1,116 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid 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 Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see . -# -# The code in this file was originally part of logilab-common, licensed under -# the same license. +# Copyright (c) 2015-2016 Cara Vinson +# Copyright (c) 2015-2016 Claudiu Popa + +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER + +import sys import warnings -from astroid import exceptions +import importlib +import lazy_object_proxy +import six -def generate_warning(message, warning): - return lambda *args: warnings.warn(message % args, warning, stacklevel=3) +def lazy_descriptor(obj): + class DescriptorProxy(lazy_object_proxy.Proxy): + def __get__(self, instance, owner=None): + return self.__class__.__get__(self, instance) + return DescriptorProxy(obj) -rename_warning = generate_warning( - "%r is deprecated and will be removed in astroid %.1f, use %r instead", - PendingDeprecationWarning) -attribute_to_method_warning = generate_warning( - "%s is deprecated and will be removed in astroid %.1f, use the " - "method '%s()' instead.", PendingDeprecationWarning) +def lazy_import(module_name): + return lazy_object_proxy.Proxy( + lambda: importlib.import_module('.' + module_name, 'astroid')) -attribute_to_function_warning = generate_warning( - "%s is deprecated and will be removed in astroid %.1f, use the " - "function '%s()' instead.", PendingDeprecationWarning) -method_to_function_warning = generate_warning( - "%s() is deprecated and will be removed in astroid %.1f, use the " - "function '%s()' instead.", PendingDeprecationWarning) +def reraise(exception): + '''Reraises an exception with the traceback from the current exception + block.''' + six.reraise(type(exception), exception, sys.exc_info()[2]) -class _Yes(object): +@object.__new__ +class Uninferable(object): """Special inference object, which is returned when inference fails.""" def __repr__(self): - return 'YES' - + return 'Uninferable' __str__ = __repr__ def __getattribute__(self, name): if name == 'next': raise AttributeError('next method should not be called') if name.startswith('__') and name.endswith('__'): - return super(_Yes, self).__getattribute__(name) + return object.__getattribute__(self, name) if name == 'accept': - return super(_Yes, self).__getattribute__(name) + return object.__getattribute__(self, name) return self def __call__(self, *args, **kwargs): return self + def __bool__(self): + return False + + __nonzero__ = __bool__ + def accept(self, visitor): - func = getattr(visitor, "visit_yes") + func = getattr(visitor, "visit_uninferable") return func(self) +class BadOperationMessage(object): + """Object which describes a TypeError occurred somewhere in the inference chain -YES = _Yes() + This is not an exception, but a container object which holds the types and + the error which occurred. + """ -def safe_infer(node, context=None): - """Return the inferred value for the given node. - Return None if inference failed or if there is some ambiguity (more than - one node has been inferred). - """ - try: - inferit = node.infer(context=context) - value = next(inferit) - except exceptions.InferenceError: - return - try: - next(inferit) - return # None if there is ambiguity on the inferred node - except exceptions.InferenceError: - return # there is some kind of ambiguity - except StopIteration: - return value +class BadUnaryOperationMessage(BadOperationMessage): + """Object which describes operational failures on UnaryOps.""" + + def __init__(self, operand, op, error): + self.operand = operand + self.op = op + self.error = error + + def __str__(self): + operand_type = self.operand.name + msg = "bad operand type for unary {}: {}" + return msg.format(self.op, operand_type) + + +class BadBinaryOperationMessage(BadOperationMessage): + """Object which describes type errors for BinOps.""" + + def __init__(self, left_type, op, right_type): + self.left_type = left_type + self.right_type = right_type + self.op = op + + def __str__(self): + msg = "unsupported operand type(s) for {}: {!r} and {!r}" + return msg.format(self.op, self.left_type.name, self.right_type.name) + + +def _instancecheck(cls, other): + wrapped = cls.__wrapped__ + other_cls = other.__class__ + is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped) + warnings.warn("%r is deprecated and slated for removal in astroid " + "2.0, use %r instead" % (cls.__class__.__name__, + wrapped.__name__), + PendingDeprecationWarning, stacklevel=2) + return is_instance_of + + +def proxy_alias(alias_name, node_type): + """Get a Proxy from the given name to the given node type.""" + proxy = type(alias_name, (lazy_object_proxy.Proxy,), + {'__class__': object.__dict__['__class__'], + '__instancecheck__': _instancecheck}) + return proxy(lambda: node_type) + + +# Backwards-compatibility aliases +YES = Uninferable diff --git a/pymode/libs/isort/__init__.py b/pymode/libs/isort/__init__.py index 082128cd..3063d1ed 100644 --- a/pymode/libs/isort/__init__.py +++ b/pymode/libs/isort/__init__.py @@ -25,4 +25,4 @@ from . import settings from .isort import SortImports -__version__ = "4.2.5" +__version__ = "4.2.15" diff --git a/pymode/libs/isort/__main__.py b/pymode/libs/isort/__main__.py new file mode 100644 index 00000000..94b1d057 --- /dev/null +++ b/pymode/libs/isort/__main__.py @@ -0,0 +1,3 @@ +from isort.main import main + +main() diff --git a/pymode/libs/isort/isort.py b/pymode/libs/isort/isort.py index 70954b0f..cecd5af9 100644 --- a/pymode/libs/isort/isort.py +++ b/pymode/libs/isort/isort.py @@ -37,12 +37,10 @@ from difflib import unified_diff from fnmatch import fnmatch from glob import glob -from sys import path as PYTHONPATH -from sys import stdout from . import settings from .natural import nsorted -from .pie_slice import * +from .pie_slice import OrderedDict, OrderedSet, input, itemsview KNOWN_SECTION_MAPPING = { 'STDLIB': 'STANDARD_LIBRARY', @@ -57,7 +55,7 @@ class SortImports(object): skipped = False def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, check=False, - show_diff=False, settings_path=None, ask_to_apply=False, **setting_overrides): + show_diff=False, settings_path=None, ask_to_apply=False, **setting_overrides): if not settings_path and file_path: settings_path = os.path.dirname(os.path.abspath(file_path)) settings_path = settings_path or os.getcwd() @@ -74,7 +72,7 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch else: self.config[key] = value - if self.config.get('force_alphabetical_sort', False): + if self.config['force_alphabetical_sort']: self.config.update({'force_alphabetical_sort_within_sections': True, 'no_sections': True, 'lines_between_types': 1, @@ -91,8 +89,8 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch self.place_imports = {} self.import_placements = {} - self.remove_imports = [self._format_simplified(removal) for removal in self.config.get('remove_imports', [])] - self.add_imports = [self._format_natural(addition) for addition in self.config.get('add_imports', [])] + self.remove_imports = [self._format_simplified(removal) for removal in self.config['remove_imports']] + self.add_imports = [self._format_natural(addition) for addition in self.config['add_imports']] self._section_comments = ["# " + value for key, value in itemsview(self.config) if key.startswith('import_heading') and value] @@ -118,20 +116,29 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch self.in_lines = file_contents.split("\n") self.original_length = len(self.in_lines) - if (self.original_length > 1 or self.in_lines[:1] not in ([], [""])) or self.config.get('force_adds', False): + if (self.original_length > 1 or self.in_lines[:1] not in ([], [""])) or self.config['force_adds']: for add_import in self.add_imports: self.in_lines.append(add_import) self.number_of_lines = len(self.in_lines) self.out_lines = [] self.comments = {'from': {}, 'straight': {}, 'nested': {}, 'above': {'straight': {}, 'from': {}}} - self.imports = {} + self.imports = OrderedDict() self.as_map = {} - section_names = self.config.get('sections') + section_names = self.config['sections'] self.sections = namedtuple('Sections', section_names)(*[name for name in section_names]) for section in itertools.chain(self.sections, self.config['forced_separate']): - self.imports[section] = {'straight': set(), 'from': {}} + self.imports[section] = {'straight': OrderedSet(), 'from': OrderedDict()} + + self.known_patterns = [] + for placement in reversed(self.sections): + known_placement = KNOWN_SECTION_MAPPING.get(placement, placement) + config_key = 'known_{0}'.format(known_placement.lower()) + known_patterns = self.config.get(config_key, []) + for known_pattern in known_patterns: + self.known_patterns.append((re.compile('^' + known_pattern.replace('*', '.*').replace('?', '.?') + '$'), + placement)) self.index = 0 self.import_index = -1 @@ -147,7 +154,7 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch self.out_lines.append("") self.output = "\n".join(self.out_lines) - if self.config.get('atomic', False): + if self.config['atomic']: try: compile(self._strip_top_comments(self.out_lines), self.file_path, 'exec', 0, 1) except SyntaxError: @@ -162,21 +169,24 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch return if check: - if self.output.replace("\n", "").replace(" ", "") == file_contents.replace("\n", "").replace(" ", ""): + check_output = self.output + check_against = file_contents + if self.config['ignore_whitespace']: + check_output = check_output.replace("\n", "").replace(" ", "") + check_against = check_against.replace("\n", "").replace(" ", "") + + if check_output == check_against: if self.config['verbose']: print("SUCCESS: {0} Everything Looks Good!".format(self.file_path)) - else: - print("ERROR: {0} Imports are incorrectly sorted.".format(self.file_path)) - self.incorrectly_sorted = True - if show_diff or self.config.get('show_diff', False) is True: - self._show_diff(file_contents) - return + return - if show_diff or self.config.get('show_diff', False) is True: + print("ERROR: {0} Imports are incorrectly sorted.".format(self.file_path)) + self.incorrectly_sorted = True + if show_diff or self.config['show_diff']: self._show_diff(file_contents) elif write_to_stdout: - stdout.write(self.output) - elif file_name: + sys.stdout.write(self.output) + elif file_name and not check: if ask_to_apply: if self.output == file_contents: return @@ -201,7 +211,7 @@ def _show_diff(self, file_contents): if self.file_path else datetime.now()), tofiledate=str(datetime.now()) ): - stdout.write(line) + sys.stdout.write(line) @staticmethod def _strip_top_comments(lines): @@ -233,13 +243,15 @@ def place_module(self, module_name): parts = module_name.split('.') module_names_to_check = ['.'.join(parts[:first_k]) for first_k in range(len(parts), 0, -1)] for module_name_to_check in module_names_to_check: - for placement in reversed(self.sections): - known_placement = KNOWN_SECTION_MAPPING.get(placement, placement) - config_key = 'known_{0}'.format(known_placement.lower()) - if module_name_to_check in self.config.get(config_key, []): + for pattern, placement in self.known_patterns: + if pattern.match(module_name_to_check): return placement - paths = PYTHONPATH + # Use a copy of sys.path to avoid any unintended modifications + # to it - e.g. `+=` used below will change paths in place and + # if not copied, consequently sys.path, which will grow unbounded + # with duplicates on every call to this method. + paths = list(sys.path) virtual_env = self.config.get('virtual_env') or os.environ.get('VIRTUAL_ENV') virtual_env_src = False if virtual_env: @@ -248,15 +260,20 @@ def place_module(self, module_name): paths += [path for path in glob('{0}/src/*'.format(virtual_env)) if os.path.isdir(path)] virtual_env_src = '{0}/src/'.format(virtual_env) + # handle case-insensitive paths on windows + stdlib_lib_prefix = os.path.normcase(get_stdlib_path()) + for prefix in paths: module_path = "/".join((prefix, module_name.replace(".", "/"))) package_path = "/".join((prefix, module_name.split(".")[0])) - if (os.path.exists(module_path + ".py") or os.path.exists(module_path + ".so") or - (os.path.exists(package_path) and os.path.isdir(package_path))): + is_module = (exists_case_sensitive(module_path + ".py") or + exists_case_sensitive(module_path + ".so")) + is_package = exists_case_sensitive(package_path) and os.path.isdir(package_path) + if is_module or is_package: if ('site-packages' in prefix or 'dist-packages' in prefix or - (virtual_env and virtual_env_src in prefix)): + (virtual_env and virtual_env_src in prefix)): return self.sections.THIRDPARTY - elif 'python2' in prefix.lower() or 'python3' in prefix.lower(): + elif os.path.normcase(prefix).startswith(stdlib_lib_prefix): return self.sections.STDLIB else: return self.config['default_section'] @@ -313,9 +330,9 @@ def _wrap(self, line): """ Returns an import wrapped to the specified line-length, if possible. """ - wrap_mode = self.config.get('multi_line_output', 0) + wrap_mode = self.config['multi_line_output'] if len(line) > self.config['line_length'] and wrap_mode != settings.WrapModes.NOQA: - for splitter in ("import", "."): + for splitter in ("import", ".", "as"): exp = r"\b" + re.escape(splitter) + r"\b" if re.search(exp, line) and not line.strip().startswith(splitter): line_parts = re.split(exp, line) @@ -328,7 +345,18 @@ def _wrap(self, line): cont_line = self._wrap(self.config['indent'] + splitter.join(next_line).lstrip()) if self.config['use_parentheses']: - return "{0}{1} (\n{2})".format(line, splitter, cont_line) + output = "{0}{1} (\n{2}{3}{4})".format( + line, splitter, cont_line, + "," if self.config['include_trailing_comma'] else "", + "\n" if wrap_mode in ( + settings.WrapModes.VERTICAL_HANGING_INDENT, + settings.WrapModes.VERTICAL_GRID_GROUPED, + ) else "") + lines = output.split('\n') + if ' #' in lines[-1] and lines[-1].endswith(')'): + line, comment = lines[-1].split(' #', 1) + lines[-1] = line + ') #' + comment[:-1] + return '\n'.join(lines) return "{0}{1} \\\n{2}".format(line, splitter, cont_line) elif len(line) > self.config['line_length'] and wrap_mode == settings.WrapModes.NOQA: if "# NOQA" not in line: @@ -357,7 +385,7 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case): continue import_start = "from {0} import ".format(module) - from_imports = list(self.imports[section]['from'][module]) + from_imports = self.imports[section]['from'][module] from_imports = nsorted(from_imports, key=lambda key: self._module_key(key, self.config, True, ignore_case)) if self.remove_imports: from_imports = [line for line in from_imports if not "{0}.{1}".format(module, line) in @@ -372,11 +400,13 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case): self.config['combine_star']): from_imports[from_imports.index(from_import)] = import_definition else: - import_statement = self._wrap(import_start + import_definition) + import_statement = import_start + import_definition + force_grid_wrap = self.config['force_grid_wrap'] comments = self.comments['straight'].get(submodule) - import_statement = self._add_comments(comments, import_statement) - section_output.append(import_statement) + import_statement = self._add_comments(comments, self._wrap(import_statement)) from_imports.remove(from_import) + section_output.append(import_statement) + if from_imports: comments = self.comments['from'].pop(module, ()) @@ -418,34 +448,24 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case): import_statement = self._add_comments(comments, import_start + (", ").join(from_imports)) if not from_imports: import_statement = "" - if len(from_imports) > 1 and ( - len(import_statement) > self.config['line_length'] - or self.config.get('force_grid_wrap') - ): - output_mode = settings.WrapModes._fields[self.config.get('multi_line_output', - 0)].lower() - formatter = getattr(self, "_output_" + output_mode, self._output_grid) - dynamic_indent = " " * (len(import_start) + 1) - indent = self.config['indent'] - line_length = self.config['wrap_length'] or self.config['line_length'] - import_statement = formatter(import_start, copy.copy(from_imports), - dynamic_indent, indent, line_length, comments) - if self.config['balanced_wrapping']: - lines = import_statement.split("\n") - line_count = len(lines) - if len(lines) > 1: - minimum_length = min([len(line) for line in lines[:-1]]) - else: - minimum_length = 0 - new_import_statement = import_statement - while (len(lines[-1]) < minimum_length and - len(lines) == line_count and line_length > 10): - import_statement = new_import_statement - line_length -= 1 - new_import_statement = formatter(import_start, copy.copy(from_imports), - dynamic_indent, indent, line_length, comments) - lines = new_import_statement.split("\n") - elif len(import_statement) > self.config['line_length']: + + do_multiline_reformat = False + + force_grid_wrap = self.config['force_grid_wrap'] + if force_grid_wrap and len(from_imports) >= force_grid_wrap: + do_multiline_reformat = True + + if len(import_statement) > self.config['line_length'] and len(from_imports) > 1: + do_multiline_reformat = True + + # If line too long AND have imports AND we are NOT using GRID or VERTICAL wrap modes + if (len(import_statement) > self.config['line_length'] and len(from_imports) > 0 and + self.config['multi_line_output'] not in (1, 0)): + do_multiline_reformat = True + + if do_multiline_reformat: + import_statement = self._multi_line_reformat(import_start, from_imports, comments) + if not do_multiline_reformat and len(import_statement) > self.config['line_length']: import_statement = self._wrap(import_statement) if import_statement: @@ -454,16 +474,43 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case): section_output.extend(above_comments) section_output.append(import_statement) + def _multi_line_reformat(self, import_start, from_imports, comments): + output_mode = settings.WrapModes._fields[self.config['multi_line_output']].lower() + formatter = getattr(self, "_output_" + output_mode, self._output_grid) + dynamic_indent = " " * (len(import_start) + 1) + indent = self.config['indent'] + line_length = self.config['wrap_length'] or self.config['line_length'] + import_statement = formatter(import_start, copy.copy(from_imports), + dynamic_indent, indent, line_length, comments) + if self.config['balanced_wrapping']: + lines = import_statement.split("\n") + line_count = len(lines) + if len(lines) > 1: + minimum_length = min([len(line) for line in lines[:-1]]) + else: + minimum_length = 0 + new_import_statement = import_statement + while (len(lines[-1]) < minimum_length and + len(lines) == line_count and line_length > 10): + import_statement = new_import_statement + line_length -= 1 + new_import_statement = formatter(import_start, copy.copy(from_imports), + dynamic_indent, indent, line_length, comments) + lines = new_import_statement.split("\n") + if import_statement.count('\n') == 0: + return self._wrap(import_statement) + return import_statement + def _add_formatted_imports(self): """Adds the imports back to the file. (at the index of the first import) sorted alphabetically and split between groups """ - sort_ignore_case = self.config.get('force_alphabetical_sort_within_sections', False) + sort_ignore_case = self.config['force_alphabetical_sort_within_sections'] sections = itertools.chain(self.sections, self.config['forced_separate']) - if self.config.get('no_sections', False): + if self.config['no_sections']: self.imports['no_sections'] = {'straight': [], 'from': {}} for section in sections: self.imports['no_sections']['straight'].extend(self.imports[section].get('straight', [])) @@ -472,30 +519,36 @@ def _add_formatted_imports(self): output = [] for section in sections: - straight_modules = list(self.imports[section]['straight']) + straight_modules = self.imports[section]['straight'] straight_modules = nsorted(straight_modules, key=lambda key: self._module_key(key, self.config)) - from_modules = sorted(list(self.imports[section]['from'].keys())) - from_modules = nsorted(from_modules, key=lambda key: self._module_key(key, self.config, )) + from_modules = self.imports[section]['from'] + from_modules = nsorted(from_modules, key=lambda key: self._module_key(key, self.config)) section_output = [] - if self.config.get('from_first', False): + if self.config['from_first']: self._add_from_imports(from_modules, section, section_output, sort_ignore_case) - if self.config.get('lines_between_types', 0) and from_modules and straight_modules: + if self.config['lines_between_types'] and from_modules and straight_modules: section_output.extend([''] * self.config['lines_between_types']) self._add_straight_imports(straight_modules, section, section_output) else: self._add_straight_imports(straight_modules, section, section_output) - if self.config.get('lines_between_types', 0) and from_modules and straight_modules: + if self.config['lines_between_types'] and from_modules and straight_modules: section_output.extend([''] * self.config['lines_between_types']) self._add_from_imports(from_modules, section, section_output, sort_ignore_case) - if self.config.get('force_sort_within_sections', False): + if self.config['force_sort_within_sections']: def by_module(line): + section = 'B' + if line.startswith('#'): + return 'AA' + line = re.sub('^from ', '', line) line = re.sub('^import ', '', line) + if line.split(' ')[0] in self.config['force_to_top']: + section = 'A' if not self.config['order_by_type']: line = line.lower() - return line + return '{0}{1}'.format(section, line) section_output = nsorted(section_output, key=by_module) if section_output: @@ -507,7 +560,7 @@ def by_module(line): section_title = self.config.get('import_heading_' + str(section_name).lower(), '') if section_title: section_comment = "# {0}".format(section_title) - if not section_comment in self.out_lines[0:1]: + if not section_comment in self.out_lines[0:1] and not section_comment in self.in_lines[0:1]: section_output.insert(0, section_comment) output += section_output + ([''] * self.config['lines_between_sections']) @@ -528,15 +581,18 @@ def by_module(line): if len(self.out_lines) > imports_tail: next_construct = "" self._in_quote = False - for line in self.out_lines[imports_tail:]: - if not self._skip_line(line) and not line.strip().startswith("#") and line.strip(): + tail = self.out_lines[imports_tail:] + for index, line in enumerate(tail): + if not self._skip_line(line) and line.strip(): + if line.strip().startswith("#") and len(tail) > (index + 1) and tail[index + 1].strip(): + continue next_construct = line break if self.config['lines_after_imports'] != -1: self.out_lines[imports_tail:0] = ["" for line in range(self.config['lines_after_imports'])] elif next_construct.startswith("def") or next_construct.startswith("class") or \ - next_construct.startswith("@"): + next_construct.startswith("@") or next_construct.startswith("async def"): self.out_lines[imports_tail:0] = ["", ""] else: self.out_lines[imports_tail:0] = [""] @@ -557,8 +613,16 @@ def _output_grid(self, statement, imports, white_space, indent, line_length, com next_import = imports.pop(0) next_statement = self._add_comments(comments, statement + ", " + next_import) if len(next_statement.split("\n")[-1]) + 1 > line_length: + lines = ['{0}{1}'.format(white_space, next_import.split(" ")[0])] + for part in next_import.split(" ")[1:]: + new_line = '{0} {1}'.format(lines[-1], part) + if len(new_line) + 1 > line_length: + lines.append('{0}{1}'.format(white_space, part)) + else: + lines[-1] = new_line + next_import = '\n'.join(lines) statement = (self._add_comments(comments, "{0},".format(statement)) + - "\n{0}{1}".format(white_space, next_import)) + "\n{0}".format(next_import)) comments = None else: statement += ", " + next_import @@ -675,7 +739,7 @@ def _skip_line(self, line): elif self._in_top_comment: if not line.startswith("#"): self._in_top_comment = False - self._first_comment_index_end = self.index + self._first_comment_index_end = self.index - 1 if '"' in line or "'" in line: index = 0 @@ -749,7 +813,7 @@ def _parse(self): self.out_lines.append(line) continue - line = line.replace("\t", " ") + line = line.replace("\t", " ").replace('import*', 'import *') if self.import_index == -1: self.import_index = self.index - 1 @@ -760,7 +824,7 @@ def _parse(self): if import_type == "from" and len(stripped_line) == 2 and stripped_line[1] != "*" and new_comments: nested_comments[stripped_line[-1]] = comments[0] - if "(" in line and not self._at_end(): + if "(" in line.split("#")[0] and not self._at_end(): while not line.strip().endswith(")") and not self._at_end(): line, comments, new_comments = self._strip_comments(self._get_line(), comments) stripped_line = self._strip_syntax(line).strip() @@ -776,7 +840,7 @@ def _parse(self): if import_string.strip().endswith(" import") or line.strip().startswith("import "): import_string += "\n" + line else: - import_string = import_string.rstrip().rstrip("\\") + line.lstrip() + import_string = import_string.rstrip().rstrip("\\") + " " + line.lstrip() if import_type == "from": import_string = import_string.replace("import(", "import (") @@ -816,12 +880,12 @@ def _parse(self): if comments: self.comments['from'].setdefault(import_from, []).extend(comments) - if len(self.out_lines) > max(self.import_index, self._first_comment_index_end, 1) - 1: + if len(self.out_lines) > max(self.import_index, self._first_comment_index_end + 1, 1) - 1: last = self.out_lines and self.out_lines[-1].rstrip() or "" while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and not 'isort:imports-' in last): self.comments['above']['from'].setdefault(import_from, []).insert(0, self.out_lines.pop(-1)) - if len(self.out_lines) > max(self.import_index - 1, self._first_comment_index_end, 1) - 1: + if len(self.out_lines) > max(self.import_index - 1, self._first_comment_index_end + 1, 1) - 1: last = self.out_lines[-1].rstrip() else: last = "" @@ -831,21 +895,21 @@ def _parse(self): if root.get(import_from, False): root[import_from].update(imports) else: - root[import_from] = set(imports) + root[import_from] = OrderedSet(imports) else: for module in imports: if comments: self.comments['straight'][module] = comments comments = None - if len(self.out_lines) > max(self.import_index, self._first_comment_index_end, 1) - 1: + if len(self.out_lines) > max(self.import_index, self._first_comment_index_end + 1, 1) - 1: + last = self.out_lines and self.out_lines[-1].rstrip() or "" - while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") - and not 'isort:imports-' in last): + while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and + not 'isort:imports-' in last): self.comments['above']['straight'].setdefault(module, []).insert(0, self.out_lines.pop(-1)) - if len(self.out_lines) > max(self.import_index - 1, self._first_comment_index_end, - 1) - 1: + if len(self.out_lines) > 0: last = self.out_lines[-1].rstrip() else: last = "" @@ -876,3 +940,30 @@ def coding_check(fname, default='utf-8'): break return coding + + +def get_stdlib_path(): + """Returns the path to the standard lib for the current path installation. + + This function can be dropped and "sysconfig.get_paths()" used directly once Python 2.6 support is dropped. + """ + if sys.version_info >= (2, 7): + import sysconfig + return sysconfig.get_paths()['stdlib'] + else: + return os.path.join(sys.prefix, 'lib') + + +def exists_case_sensitive(path): + """ + Returns if the given path exists and also matches the case on Windows. + + When finding files that can be imported, it is important for the cases to match because while + file os.path.exists("module.py") and os.path.exists("MODULE.py") both return True on Windows, Python + can only import using the case of the real file. + """ + result = os.path.exists(path) + if sys.platform.startswith('win') and result: + directory, basename = os.path.split(path) + result = basename in os.listdir(directory) + return result diff --git a/pymode/libs/isort/main.py b/pymode/libs/isort/main.py index 600fbad5..eae7afa5 100644 --- a/pymode/libs/isort/main.py +++ b/pymode/libs/isort/main.py @@ -30,11 +30,11 @@ from isort import SortImports, __version__ from isort.settings import DEFAULT_SECTIONS, default, from_path, should_skip -from .pie_slice import * +from .pie_slice import itemsview -INTRO = """ -/#######################################################################\\ +INTRO = r""" +/#######################################################################\ `sMMy` .yyyy- ` @@ -130,7 +130,7 @@ def run(self): if incorrectly_sorted: wrong_sorted_files = True except IOError as e: - print("WARNING: Unable to parse file {0} due to {1}".format(file_name, e)) + print("WARNING: Unable to parse file {0} due to {1}".format(python_file, e)) if wrong_sorted_files: exit(1) @@ -162,35 +162,37 @@ def create_parser(): help='Force sortImports to recognize a module as being part of a third party library.') parser.add_argument('-p', '--project', dest='known_first_party', action='append', help='Force sortImports to recognize a module as being part of the current python project.') - parser.add_argument('-m', '--multi_line', dest='multi_line_output', type=int, choices=[0, 1, 2, 3, 4, 5], + parser.add_argument('--virtual-env', dest='virtual_env', + help='Virtual environment to use for determining whether a package is third-party') + parser.add_argument('-m', '--multi-line', dest='multi_line_output', type=int, choices=[0, 1, 2, 3, 4, 5], help='Multi line output (0-grid, 1-vertical, 2-hanging, 3-vert-hanging, 4-vert-grid, ' '5-vert-grid-grouped).') parser.add_argument('-i', '--indent', help='String to place for indents defaults to " " (4 spaces).', dest='indent', type=str) - parser.add_argument('-a', '--add_import', dest='add_imports', action='append', + parser.add_argument('-a', '--add-import', dest='add_imports', action='append', help='Adds the specified import line to all files, ' 'automatically determining correct placement.') - parser.add_argument('-af', '--force_adds', dest='force_adds', action='store_true', + parser.add_argument('-af', '--force-adds', dest='force_adds', action='store_true', help='Forces import adds even if the original file is empty.') - parser.add_argument('-r', '--remove_import', dest='remove_imports', action='append', + parser.add_argument('-r', '--remove-import', dest='remove_imports', action='append', help='Removes the specified import from all files.') - parser.add_argument('-ls', '--length_sort', help='Sort imports by their string length.', - dest='length_sort', action='store_true', default=False) + parser.add_argument('-ls', '--length-sort', help='Sort imports by their string length.', + dest='length_sort', action='store_true') parser.add_argument('-d', '--stdout', help='Force resulting output to stdout, instead of in-place.', dest='write_to_stdout', action='store_true') - parser.add_argument('-c', '--check-only', action='store_true', default=False, dest="check", + parser.add_argument('-c', '--check-only', action='store_true', dest="check", help='Checks the file for unsorted / unformatted imports and prints them to the ' 'command line without modifying the file.') + parser.add_argument('-ws', '--ignore-whitespace', action='store_true', dest="ignore_whitespace", + help='Tells isort to ignore whitespace differences when --check-only is being used.') parser.add_argument('-sl', '--force-single-line-imports', dest='force_single_line', action='store_true', help='Forces all from imports to appear on their own line') - parser.add_argument('--force_single_line_imports', dest='force_single_line', action='store_true', - help=argparse.SUPPRESS) parser.add_argument('-ds', '--no-sections', help='Put all imports into the same section bucket', dest='no_sections', action='store_true') parser.add_argument('-sd', '--section-default', dest='default_section', help='Sets the default section for imports (by default FIRSTPARTY) options: ' + str(DEFAULT_SECTIONS)) - parser.add_argument('-df', '--diff', dest='show_diff', default=False, action='store_true', + parser.add_argument('-df', '--diff', dest='show_diff', action='store_true', help="Prints a diff of all the changes isort would make to a file, instead of " "changing it in place") parser.add_argument('-e', '--balanced', dest='balanced_wrapping', action='store_true', @@ -214,22 +216,25 @@ def create_parser(): help='Shows verbose output, such as when files are skipped or when a check is successful.') parser.add_argument('-q', '--quiet', action='store_true', dest="quiet", help='Shows extra quiet output, only errors are outputted.') - parser.add_argument('-sp', '--settings-path', dest="settings_path", + parser.add_argument('-sp', '--settings-path', dest="settings_path", help='Explicitly set the settings path instead of auto determining based on file location.') parser.add_argument('-ff', '--from-first', dest='from_first', help="Switches the typical ordering preference, showing from imports first then straight ones.") parser.add_argument('-wl', '--wrap-length', dest='wrap_length', help="Specifies how long lines that are wrapped should be, if not set line_length is used.") - parser.add_argument('-fgw', '--force-grid-wrap', action='store_true', dest="force_grid_wrap", - help='Force from imports to be grid wrapped regardless of line length') - parser.add_argument('-fass', '--force-alphabetical-sort-within-sections', action='store_true', + parser.add_argument('-fgw', '--force-grid-wrap', nargs='?', const=2, type=int, dest="force_grid_wrap", + help='Force number of from imports (defaults to 2) to be grid wrapped regardless of line ' + 'length') + parser.add_argument('-fass', '--force-alphabetical-sort-within-sections', action='store_true', dest="force_alphabetical_sort", help='Force all imports to be sorted alphabetically within a ' 'section') - parser.add_argument('-fas', '--force-alphabetical-sort', action='store_true', dest="force_alphabetical_sort", + parser.add_argument('-fas', '--force-alphabetical-sort', action='store_true', dest="force_alphabetical_sort", help='Force all imports to be sorted as a single section') - parser.add_argument('-fss', '--force-sort-within-sections', action='store_true', dest="force_sort_within_sections", + parser.add_argument('-fss', '--force-sort-within-sections', action='store_true', dest="force_sort_within_sections", help='Force imports to be sorted by module, independent of import_type') parser.add_argument('-lbt', '--lines-between-types', dest='lines_between_types', type=int) + parser.add_argument('-up', '--use-parentheses', dest='use_parentheses', action='store_true', + help='Use parenthesis for line continuation on lenght limit instead of slashes.') arguments = dict((key, value) for (key, value) in itemsview(vars(parser.parse_args())) if value) if 'dont_order_by_type' in arguments: @@ -243,6 +248,10 @@ def main(): print(INTRO) return + if 'settings_path' in arguments: + sp = arguments['settings_path'] + arguments['settings_path'] = os.path.abspath(sp) if os.path.isdir(sp) else os.path.dirname(os.path.abspath(sp)) + file_names = arguments.pop('files', []) if file_names == ['-']: SortImports(file_contents=sys.stdin.read(), write_to_stdout=True, **arguments) @@ -259,7 +268,7 @@ def main(): if arguments.get('recursive', False): file_names = iter_source_code(file_names, config, skipped) num_skipped = 0 - if config.get('verbose', False) or config.get('show_logo', False): + if config['verbose'] or config.get('show_logo', False): print(INTRO) for file_name in file_names: try: diff --git a/pymode/libs/isort/natural.py b/pymode/libs/isort/natural.py index 0529fa60..aac8c4a3 100644 --- a/pymode/libs/isort/natural.py +++ b/pymode/libs/isort/natural.py @@ -33,7 +33,7 @@ def _atoi(text): def _natural_keys(text): - return [_atoi(c) for c in re.split('(\d+)', text)] + return [_atoi(c) for c in re.split(r'(\d+)', text)] def nsorted(to_sort, key=None): diff --git a/pymode/libs/isort/pie_slice.py b/pymode/libs/isort/pie_slice.py index d8a35769..bfb341a7 100644 --- a/pymode/libs/isort/pie_slice.py +++ b/pymode/libs/isort/pie_slice.py @@ -22,6 +22,7 @@ from __future__ import absolute_import import abc +import collections import functools import sys from numbers import Integral @@ -67,6 +68,7 @@ class Form(with_metaclass(FormType, BaseForm)): class metaclass(meta): __call__ = type.__call__ __init__ = type.__init__ + def __new__(cls, name, this_bases, d): if this_bases is None: return type.__new__(cls, name, (), d) @@ -118,6 +120,7 @@ def __instancecheck__(cls, instance): import builtins from urllib import parse + input = input integer_types = (int, ) def u(string): @@ -428,7 +431,7 @@ def __eq__(self, other): if isinstance(other, OrderedDict): if len(self) != len(other): return False - for p, q in zip(self.items(), other.items()): + for p, q in zip(self.items(), other.items()): if p != q: return False return True @@ -526,3 +529,66 @@ def cache_clear(): else: from functools import lru_cache + + +class OrderedSet(collections.MutableSet): + + def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] + self.map = {} + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.map) + + def __contains__(self, key): + return key in self.map + + def add(self, key): + if key not in self.map: + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + def discard(self, key): + if key in self.map: + key, prev, next = self.map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + def pop(self, last=True): + if not self: + raise KeyError('set is empty') + key = self.end[1][0] if last else self.end[2][0] + self.discard(key) + return key + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return set(self) == set(other) + + def update(self, other): + for item in other: + self.add(item) diff --git a/pymode/libs/isort/settings.py b/pymode/libs/isort/settings.py index 26cec5bd..15cdb210 100644 --- a/pymode/libs/isort/settings.py +++ b/pymode/libs/isort/settings.py @@ -26,9 +26,10 @@ import fnmatch import os +import posixpath from collections import namedtuple -from .pie_slice import * +from .pie_slice import itemsview, lru_cache, native_str try: import configparser @@ -36,7 +37,7 @@ import ConfigParser as configparser MAX_CONFIG_SEARCH_DEPTH = 25 # The number of parent directories isort will look for a config file within -DEFAULT_SECTIONS = ("FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER") +DEFAULT_SECTIONS = ('FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER') WrapModes = ('GRID', 'VERTICAL', 'HANGING_INDENT', 'VERTICAL_HANGING_INDENT', 'VERTICAL_GRID', 'VERTICAL_GRID_GROUPED', 'NOQA') WrapModes = namedtuple('WrapModes', WrapModes)(*range(len(WrapModes))) @@ -50,26 +51,51 @@ 'sections': DEFAULT_SECTIONS, 'no_sections': False, 'known_future_library': ['__future__'], - 'known_standard_library': ["abc", "anydbm", "argparse", "array", "asynchat", "asyncore", "atexit", "base64", - "BaseHTTPServer", "bisect", "bz2", "calendar", "cgitb", "cmd", "codecs", - "collections", "commands", "compileall", "ConfigParser", "contextlib", "Cookie", - "copy", "cPickle", "cProfile", "cStringIO", "csv", "datetime", "dbhash", "dbm", - "decimal", "difflib", "dircache", "dis", "doctest", "dumbdbm", "EasyDialogs", - "errno", "exceptions", "filecmp", "fileinput", "fnmatch", "fractions", - "functools", "gc", "gdbm", "getopt", "getpass", "gettext", "glob", "grp", "gzip", - "hashlib", "heapq", "hmac", "imaplib", "imp", "inspect", "io", "itertools", "json", - "linecache", "locale", "logging", "mailbox", "math", "mhlib", "mmap", - "multiprocessing", "operator", "optparse", "os", "pdb", "pickle", "pipes", - "pkgutil", "platform", "plistlib", "pprint", "profile", "pstats", "pwd", "pyclbr", - "pydoc", "Queue", "random", "re", "readline", "resource", "rlcompleter", - "robotparser", "sched", "select", "shelve", "shlex", "shutil", "signal", - "SimpleXMLRPCServer", "site", "sitecustomize", "smtpd", "smtplib", "socket", - "SocketServer", "sqlite3", "string", "StringIO", "struct", "subprocess", "sys", - "sysconfig", "tabnanny", "tarfile", "tempfile", "textwrap", "threading", "time", - "timeit", "trace", "traceback", "unittest", "urllib", "urllib2", "urlparse", - "usercustomize", "uuid", "warnings", "weakref", "webbrowser", "whichdb", "xml", - "xmlrpclib", "zipfile", "zipimport", "zlib", 'builtins', '__builtin__', 'thread', - "binascii", "statistics", "unicodedata", "fcntl", 'pathlib'], + 'known_standard_library': ['AL', 'BaseHTTPServer', 'Bastion', 'CGIHTTPServer', 'Carbon', 'ColorPicker', + 'ConfigParser', 'Cookie', 'DEVICE', 'DocXMLRPCServer', 'EasyDialogs', 'FL', + 'FrameWork', 'GL', 'HTMLParser', 'MacOS', 'MimeWriter', 'MiniAEFrame', 'Nav', + 'PixMapWrapper', 'Queue', 'SUNAUDIODEV', 'ScrolledText', 'SimpleHTTPServer', + 'SimpleXMLRPCServer', 'SocketServer', 'StringIO', 'Tix', 'Tkinter', 'UserDict', + 'UserList', 'UserString', 'W', '__builtin__', 'abc', 'aepack', 'aetools', + 'aetypes', 'aifc', 'al', 'anydbm', 'applesingle', 'argparse', 'array', 'ast', + 'asynchat', 'asyncio', 'asyncore', 'atexit', 'audioop', 'autoGIL', 'base64', + 'bdb', 'binascii', 'binhex', 'bisect', 'bsddb', 'buildtools', 'builtins', + 'bz2', 'cPickle', 'cProfile', 'cStringIO', 'calendar', 'cd', 'cfmfile', 'cgi', + 'cgitb', 'chunk', 'cmath', 'cmd', 'code', 'codecs', 'codeop', 'collections', + 'colorsys', 'commands', 'compileall', 'compiler', 'concurrent', 'configparser', + 'contextlib', 'cookielib', 'copy', 'copy_reg', 'copyreg', 'crypt', 'csv', + 'ctypes', 'curses', 'datetime', 'dbhash', 'dbm', 'decimal', 'difflib', + 'dircache', 'dis', 'distutils', 'dl', 'doctest', 'dumbdbm', 'dummy_thread', + 'dummy_threading', 'email', 'encodings', 'ensurepip', 'enum', 'errno', + 'exceptions', 'faulthandler', 'fcntl', 'filecmp', 'fileinput', 'findertools', + 'fl', 'flp', 'fm', 'fnmatch', 'formatter', 'fpectl', 'fpformat', 'fractions', + 'ftplib', 'functools', 'future_builtins', 'gc', 'gdbm', 'gensuitemodule', + 'getopt', 'getpass', 'gettext', 'gl', 'glob', 'grp', 'gzip', 'hashlib', + 'heapq', 'hmac', 'hotshot', 'html', 'htmlentitydefs', 'htmllib', 'http', + 'httplib', 'ic', 'icopen', 'imageop', 'imaplib', 'imgfile', 'imghdr', 'imp', + 'importlib', 'imputil', 'inspect', 'io', 'ipaddress', 'itertools', 'jpeg', + 'json', 'keyword', 'lib2to3', 'linecache', 'locale', 'logging', 'lzma', + 'macerrors', 'macostools', 'macpath', 'macresource', 'mailbox', 'mailcap', + 'marshal', 'math', 'md5', 'mhlib', 'mimetools', 'mimetypes', 'mimify', 'mmap', + 'modulefinder', 'msilib', 'msvcrt', 'multifile', 'multiprocessing', 'mutex', + 'netrc', 'new', 'nis', 'nntplib', 'numbers', 'operator', 'optparse', 'os', + 'ossaudiodev', 'parser', 'pathlib', 'pdb', 'pickle', 'pickletools', 'pipes', + 'pkgutil', 'platform', 'plistlib', 'popen2', 'poplib', 'posix', 'posixfile', + 'pprint', 'profile', 'pstats', 'pty', 'pwd', 'py_compile', 'pyclbr', 'pydoc', + 'queue', 'quopri', 'random', 're', 'readline', 'reprlib', 'resource', 'rexec', + 'rfc822', 'rlcompleter', 'robotparser', 'runpy', 'sched', 'secrets', 'select', + 'selectors', 'sets', 'sgmllib', 'sha', 'shelve', 'shlex', 'shutil', 'signal', + 'site', 'sitecustomize', 'smtpd', 'smtplib', 'sndhdr', 'socket', 'socketserver', + 'spwd', 'sqlite3', 'ssl', 'stat', 'statistics', 'statvfs', 'string', 'stringprep', + 'struct', 'subprocess', 'sunau', 'sunaudiodev', 'symbol', 'symtable', 'sys', + 'sysconfig', 'syslog', 'tabnanny', 'tarfile', 'telnetlib', 'tempfile', 'termios', + 'test', 'textwrap', 'this', 'thread', 'threading', 'time', 'timeit', 'tkinter', + 'token', 'tokenize', 'trace', 'traceback', 'tracemalloc', 'ttk', 'tty', 'turtle', + 'turtledemo', 'types', 'typing', 'unicodedata', 'unittest', 'urllib', 'urllib2', + 'urlparse', 'user', 'usercustomize', 'uu', 'uuid', 'venv', 'videoreader', + 'warnings', 'wave', 'weakref', 'webbrowser', 'whichdb', 'winreg', 'winsound', + 'wsgiref', 'xdrlib', 'xml', 'xmlrpc', 'xmlrpclib', 'zipapp', 'zipfile', + 'zipimport', 'zlib'], 'known_third_party': ['google.appengine.api'], 'known_first_party': [], 'multi_line_output': WrapModes.GRID, @@ -101,9 +127,10 @@ 'force_adds': False, 'force_alphabetical_sort_within_sections': False, 'force_alphabetical_sort': False, - 'force_grid_wrap': False, + 'force_grid_wrap': 0, 'force_sort_within_sections': False, - 'show_diff': False} + 'show_diff': False, + 'ignore_whitespace': False} @lru_cache() @@ -112,6 +139,7 @@ def from_path(path): _update_settings_with_config(path, '.editorconfig', '~/.editorconfig', ('*', '*.py', '**.py'), computed_settings) _update_settings_with_config(path, '.isort.cfg', '~/.isort.cfg', ('settings', 'isort'), computed_settings) _update_settings_with_config(path, 'setup.cfg', None, ('isort', ), computed_settings) + _update_settings_with_config(path, 'tox.ini', None, ('isort', ), computed_settings) return computed_settings @@ -140,17 +168,17 @@ def _update_with_config_file(file_path, sections, computed_settings): if not settings: return - if file_path.endswith(".editorconfig"): - indent_style = settings.pop('indent_style', "").strip() - indent_size = settings.pop('indent_size', "").strip() - if indent_style == "space": - computed_settings['indent'] = " " * (indent_size and int(indent_size) or 4) - elif indent_style == "tab": - computed_settings['indent'] = "\t" * (indent_size and int(indent_size) or 1) + if file_path.endswith('.editorconfig'): + indent_style = settings.pop('indent_style', '').strip() + indent_size = settings.pop('indent_size', '').strip() + if indent_style == 'space': + computed_settings['indent'] = ' ' * (indent_size and int(indent_size) or 4) + elif indent_style == 'tab': + computed_settings['indent'] = '\t' * (indent_size and int(indent_size) or 1) - max_line_length = settings.pop('max_line_length', "").strip() + max_line_length = settings.pop('max_line_length', '').strip() if max_line_length: - computed_settings['line_length'] = int(max_line_length) + computed_settings['line_length'] = float('inf') if max_line_length == 'off' else int(max_line_length) for key, value in itemsview(settings): access_key = key.replace('not_', '').lower() @@ -165,27 +193,34 @@ def _update_with_config_file(file_path, sections, computed_settings): computed_settings[access_key] = list(existing_data.difference(_as_list(value))) else: computed_settings[access_key] = list(existing_data.union(_as_list(value))) - elif existing_value_type == bool and value.lower().strip() == "false": + elif existing_value_type == bool and value.lower().strip() == 'false': computed_settings[access_key] = False elif key.startswith('known_'): computed_settings[access_key] = list(_as_list(value)) + elif key == 'force_grid_wrap': + try: + result = existing_value_type(value) + except ValueError: + # backwards compat + result = default.get(access_key) if value.lower().strip() == 'false' else 2 + computed_settings[access_key] = result else: computed_settings[access_key] = existing_value_type(value) def _as_list(value): - return filter(bool, [item.strip() for item in value.replace('\n', ',').split(",")]) + return filter(bool, [item.strip() for item in value.replace('\n', ',').split(',')]) @lru_cache() def _get_config_data(file_path, sections): with open(file_path, 'rU') as config_file: - if file_path.endswith(".editorconfig"): - line = "\n" + if file_path.endswith('.editorconfig'): + line = '\n' last_position = config_file.tell() while line: line = config_file.readline() - if "[" in line: + if '[' in line: config_file.seek(last_position) break last_position = config_file.tell() @@ -205,7 +240,7 @@ def _get_config_data(file_path, sections): def should_skip(filename, config, path='/'): """Returns True if the file should be skipped based on the passed in settings.""" for skip_path in config['skip']: - if os.path.join(path, filename).endswith('/' + skip_path.lstrip('/')): + if posixpath.abspath(posixpath.join(path, filename)) == posixpath.abspath(skip_path.replace('\\', '/')): return True position = os.path.split(filename) diff --git a/pymode/libs/lazy_object_proxy/__init__.py b/pymode/libs/lazy_object_proxy/__init__.py index 2d2cce8c..1fd4f87c 100644 --- a/pymode/libs/lazy_object_proxy/__init__.py +++ b/pymode/libs/lazy_object_proxy/__init__.py @@ -15,6 +15,6 @@ else: copyreg.constructor(identity) -__version__ = "1.2.2" +__version__ = "1.3.1" __all__ = "Proxy", diff --git a/pymode/libs/lazy_object_proxy/cext.c b/pymode/libs/lazy_object_proxy/cext.c index 684bcf7f..98086571 100644 --- a/pymode/libs/lazy_object_proxy/cext.c +++ b/pymode/libs/lazy_object_proxy/cext.c @@ -9,7 +9,7 @@ #endif #define Proxy__WRAPPED_REPLACE_OR_RETURN_NULL(object) \ - if (PyObject_IsInstance(object, (PyObject *)&Proxy_Type)) { \ + if (PyObject_TypeCheck(object, &Proxy_Type)) { \ object = Proxy__ensure_wrapped((ProxyObject *)object); \ if (!object) return NULL; \ } diff --git a/pymode/libs/lazy_object_proxy/cext.so b/pymode/libs/lazy_object_proxy/cext.so deleted file mode 100755 index c891dc4300430f181e6be99f5384c779cce8c506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36084 zcmeHw3wTu3wf{*Vn(K?;tJtaxNDviBf`S%76P_~~AQGS!i<3z*A<-~1&I5vaHC0f@ zh)r7`+-hrXOOdM8=%tqS@6{;2Ta{8TTI(ae@T9&{Ybk0k`Ty45Yn|6jh7rGh-~a!8 z9N3TF-h1t});@c$bIv|%PG0!@!#xKYM!^unFp3clLGTqB##*Fw9E0$3fnfxLi)Np{ zNENxGN;fnZqfZ0fs6Z`(!DP5CNjZIZ`)eo0IL43HDdC|ytK*?YyAuY3iDariVHJ7% zyXOpD)eYI{Ak0~Xi@Co86e9VkzhHB?H5QJe%-i30rs{^hg*qk7SzVAJUqd1pZ;33| zwHf_Qo31OivrvM$xw~%^27{@{s+LG&uqDzIRoHz#O3v1lA8-eRUGj0cB=&ioRkf%} zN|9D_zJyZ`rt?a3h0ZMX;@O z{gqVe#v_=9u(!W+xQ>!wur-uRzHy+Zqml=Uu(LnXcOEt1BN%K9B}0O!f49D|8M>~5 zCl+DXJhn+yE*Pv&*t0mZzfC+i*7$+SDW7vrQ-^e3i6j`T4$MDy_N;)c*&3?FQK@3X zVEpMcjY&^uU!x79y_~Ahj{5T>T~C;gUf^aB`Oi0uaVRT9pmWj>{3$wGbE#p(4mXU0 zQHG}K*nn~h)OI7%`COhYDQ`23o3m7W17*bL^{p=yTrmCAJwKcC+~2O9aq8wVC@Z1% zha9BB$%3g22bq^M5Qvue8^#WtmI9+Jm57(Mw$xLoU7bjVS4^BSv2it!YGjN>LjA_h z$ABO`i81N9|JXkQ`$u5^2<#t${Ufk{1omwN7W>oh*4FsbUzlf2z}-a0WhMT#1IZ)( zPt8K@- zYGn}rswK4$0Nwk{FYx#gNIyAm?XKhu;a6$Ci&B63QUBU!lH>gyGmEP`W{&W8#76k9 zesoOW>LcVAxZ-Sw{(y6b4iaUztOrqor|GLTdf{FPt?t=VJ^$g(9 z?Y4F*eZK{bYXa#Vf%HGL;xw){r;`<@+fN~-6{j-dRGr>ao&H4iQ*~iga9Ll98gvwG zuMnP7iRWeDiGd)oRI{y3bWF@wzp*w~r+(LJUQHIS=O=>KFq_x1txdy5&f@dQ`t1s& z2h0y?4ANWuYyX^DYQBuyH-E?E`@V@}?XJ|(IB|!N&{GxHC;jQkH=(K;WDkNYkbbJ- z&+{E+Y~O@yCgS(!U=i@wF027F#J#><`$Y7rg;b*lzmTHBKv zCriODI!dOcT~z2g?ZZa4%leY}{I6Kr%yZdR2R}XDRePD=4`EC^^Lv(Se*c{sbQFDp znWl$wDHfS|+lgOke$TPFI_Gy-^SZ|3^$}*IS!VNc&2QMNt3N2ArTf%ulSa9E-JwU2 z`CNBs^%O$0O|nH;+&ik%&zjHTAtwE(I{&a>XIFQm%)r0_uu53=J;@UPKym6|b%w>x z&V<2nRQT8cSEmy`HQpu4tl9HtN$qTyj9mk_mcz2@#g;tQ41%pcJ+lP1+($wpRc1So ze!V)~uexYb_6YN1-SiMyuyvDfpN!$%Uhz!TmcQdM*ZePx0C#vH8tpt4Wj{pO+Mc%g zSUTo0!~?Qcfpm&Cjpm!BL{qdKJyF$I{{T8Z>TZzw2Z}aOvTkyfT1R|E=zESRlp)>f zw2!-Jgx5{JgqZFCBXo9BHP$6eLh1yW{}(G`8AUbB1sRK2HH_u^Ljt(oteZR;wAJZ< zn71-{pkpNleOKy)K*tpr9&4|AEw`qiBpJ{|#71=5wR>F8?Kv!Q27z z9P&p|oo)Olv;4O*`5^L_lW@7`Pah2_x!3sK$C02}m z+bbtz)#QRYT;ki%Y_jp}Uctq8QV-j*}@Aoju_@p7-Xn;|RC zz-g8Sw`2O7uN`M;pzngSTra;%w_ZCzo7f||2@>_uy^ewTyFWlf2@*!Gg)@E0*)p5 zm!UMPy`$$*o<9X7e-jHZ$n|~z{bZB>30xjX{u6V{-$TOXCI6?GHCq1fV9A+3#`}l8 z$zMe`HXFeq$NV{a5c!K({^d+Q$ow((F8`g7l;*!B|Ls^a=4)TiB7ZLXa0_*lX&*{; z?>p4>fb7Fr)ccio?@s%WtN$t4`~L%ag7hn`{$Iy@Hb;K>{&!GEnerFu{*Si$zk>RI z1aHr>*thKR2h>$_rQJUsNU$G+XDEM1WgR_v9O>_9-(-M4^2Pe9HP8#K)+^&pqc$B} z-ye>mbym^eF>}o+E$Bx(am| zrBh_SqXYeXw3vwxQ+lZo=Rh`W+0jnTuH;$RlEFDB_76PcPvfzcTJY2B zJlxX+1`e!FfAKzwioRiKcr_N2`S{mJPWLv>u#uH|f6%d?ltaIZA&6H$dg>wlZbe;A z{U#Ezwn!fRehSIGaybvgCBk%+VEx9iA#((g8P1tB9ig!G$*UUKPYJr4!a{|sDx z`4||P69XNWkMUs>W!ReAY%B9FI#OERp{&fTF=S@$g`KBIpb|?>{Rkv>D!Gi!%$-E7 z)vUK3f`|{czdtdHoT|Bi){w3~*a@*4{(1-VYKH<~n^F&CR^L#!`#97bhVW`=M_4qq7&}zP(iluHQ56^u* z)%{*>{l1Y!zjtA^X}-=yT~7U82mkE)RikDf^n0HSw9>B@OWnL__*d5NOcK#^JuG7V zmZL7GetW<_yMEJ9vk&?mZ0VQ4A~83Yd}aMEAQ3(KmEx*I=kHq7<<#%^LG}9yB-;o5 zPN55sI)6XJ+Av=nmWO_{|9kaiFg0U&w|Cf@b+9V4D+bgJ&83h;DfoR9VyBxd%`9A& zNWqP$gM#DbhGwkX&@2$@X+*78;3DgehPL6&^^gr3sttO}yf}C0u@OJQKR{c|?;nF( znHswGDAl%LS(u+4rbMhx@3yy(u@$feLVDhh>HTebQZsjfC*&P$fBSn%q|E*8#h@j1 zf6e5gu4jL{2Gy+VVEfyvAvJVaL)RIl%LiBj<^+`P?Ro1Dbbm7?xBM@lpKQ;IH-nbs z{|D+x{XyjKB;oYA8chBRs7XiB<8%R0@{cF^R~(v4{=L{g>d~`)-o<5vDMk5YE+rzEU?W*)2G{O_W-b$!K}$(v-Fl@bAB zay^)+cZ=$cp4v~_OaC(l>3^vnr0-h&_hFWsC!>FMq~QHbdER_!5G~G9TD(fiYb|E7 z7W8`V@apvEwq5KSO*}1Ug}z@BQAg1pvdv1xCKBP!e{=4u>WxFk{aUX1u*8_Or zdi;CF+AN&&DVzuD_C#$UfJhkAr-R4)W_$^WV9z#uXvOkR`9h1LFw=3(W z??$&4(T8VS$)sE~b{hLH6}_qT;s`Bz%g-^9r~{miV&1PpGz|Xr#sFT4M8b zku8aKS90qIZ>d2n%{av~Zu6YLJjtx67iTb=ztK$ZQr45601qdowP0$SO}xyq@6U4S zcYw`H^m~MCiFN}!T(dgcVnvqAG>3jQ{eA#Zc}zt=vR|U#pQyT{=vf+OWiKWX(*&6A zgMMReUZURzWE`}9lQgTK#p)@n3lqQPv1ZbjJAakx{5=4A)^9eSzc%osC;tCM)z!NP zk`rKROK|Gybh)}5t{tNE-cG}>^qxw>T!vCx?;Pu0&(|q7Z_)QaTi+Q}+ffv?SiFRF zVvYa{SvmWn?_(smzA}owKZNL{@1Y)jFVp2p-X&9z>3kkDFJ;rAP|HF`e1rBxbc@modwwiM*%w>NuG zZ}XJ(G8;T)z5GHm{Sm3H#<7r?&ID6?99{N6{8N>`mTh2lGMip;T@m(suN5%K5xLd^!sCcuAA5`%c75`Sn52^TJ75Aw4F%>_qV!B!n zls>KEXI1=r6+f@yZ7SZb;ulrCL&Yzv_!Skus^ZsG+^gcZRQ!&LcdFP_@n2N@fr>v; zaleW`QSqlL-lgK*D*jx>|5WiF71Iw$2TBW7JQQ&=O_07PG2NT7xn%S`M7c95_W>cq%`+(X z7s@T8TrcG=qudV4{g`sUryMEW_Za0~qa4|mX8HwR-@TMOmU8r)xaLzS_an;rDc4E4 zI?7!`xs{Z=oN_l(E>5{klxwCO8T7sjDYt`iizwGmxpOFYAZ&Uc`MfuerrZ?DO{Ls; z$}OVYXv)PXH-d6&DM!QEd>iG4Qm%(`G}z65qFg`aKBC-C${hsz()TLmPNv*;%AG^G zrzzJ!xrZrt73DTl?l#KZMY+wC>!RFql)Hs;Z&U6D$_-HND$0EgX0or1auX;Qq1-u? zYouHQ<(5+JD$3PR?l#KJq1^qHn?|`ODL097Z&7X><@QhxJCjDU4->f$TR2AZWXj>X zYc!urIb`5hd))uv99Gp1lsPtp_Xk;{p+xFfNjqt6!~nT!X6$Tzm= z6rG1T*Vd9$RrRZr;e^V?!{C(&H!^5UHH4kna2rtVRA0=XuZGr8LURj6B2fs~5{+oAMxB{kgJf{2v0&wk4p56&Qv6NNWm>!d^708EO=6!!jx_Lid=4 zod+0&B?lWrdU1=}bEr|+j?IvsBaA}d2xCaeF-Bpx4}FX>3d%P>X&0w=ak`n)hdF(k)9swT z%IQu{`#Jrb)1lL~K8JBSg45BQ>ROyPY_rm_jnhstwm53A?@vbwHV5d~#%U*B+t5)* zcMv#wIQ8LmBOUFW_HtVJbzN?JL#I8QwjZl;<#Aju37LHyb)5Ea>cfjTI=VTn^eJfg zM(NbR+M}bF)1DJF?!r2xqq9_}v9UU>!Fr^l9P5#e60Ao$`Z>kgR7dO-oz{%kY54@5 zc5$|v~?40u`6M8nD-umHO-^=wdg|6ca zu8&pdVlV$0T)%CQ`US$DF7Y_L^h-VU#kyJE@xL>DH}~&5H9P4w+^$pVPs`r!hukj4 z^}U0%`w6$Jo2>iU#;Ld0johwginqp%ySZHtw<|y0T`#DI+jU7jU*n`+(%*BtO0KUP zq@A?iTk4$`(q6uk!plgC4Z05Jbztj{4*D(!9h+wAbT_A+T;DJ4usKS{Hcsn?X)N&< zvkN7w(-NK3ak`CDX;g#jx$`KQni159ZuPGI2pu4!KzIZs9iboQ@WOLX@x3#Td>yDPKQtm$Y*X|#I{Ufk{ z1on@>{t?(e0$*+fhL0Lo=dY?8UR8JWoLI@?84I2N=G4y6{}#?v={d2InD5&&YpY_# z_%{y0A1hv1bskurRT->VJ-e+TxM+1OJUbqb#*OnXDe08bC85?77ppS8DHEJKGdL^U zYP4?|rb-veMiO;mwDCs9Guv&J9Px@s@_F*4Ai)(cU$zb9g1b*43!L-dB$g z*j}7QER_lQtNG9qv|j$!I`b$P@I~dZxx}n-EW;Lo~Jj!su~;h zKoLQ+vj*~zTvQ%YajytRiB8qrjkm-HdjSsBQa1};W;dQRUSuHEEA4ZKk zz2(@Kqw@8x@;R;1kP@WJTO5tseQk181|l`Bp@uN@qyDKg)kX1C*dC$lvNbs$%M;|Cp1MZt|Dt%kr&ym|Pa$nD zQ{zpp^6DtQc!|<(cd4b(7FW4*lzUt?^TW%r#k*2X!>3&}df>OY%4(ts?3C-)FMDeE zT=cq%T_?eGS6Q<5yULxzzS~vf9`E)c&QrnzeVs03t2Z;$+Ny>>qjU~G6QLn2mNG)? zU5#KZ$qo^9m%E}xozYFMLYUXZkwus+7prsPuG5AThNKFc{ZzjtTRn`E)c1Jmt%|3! zRoEtNo3~mtcsWajlBCyF;SVK51k+p5OoI2jN&|^NB#{h78r0<3?Wv=aMKtY0)oJ20 zvM?M|jIVQ-wlp-)jIM}<;@TX#Djfr}K3j#Yf0wsf^xx#JXt`9e>2{a$xzUBS;Y(6s zXcn9qjU-`4)C}q2I(2Od&WT4?%!$TVXq)`Bt1duqaU#^hmTsGFp)Rfq!=XlP@^oQv zMyjQ?QC+)f%zC*rfcH}R3Uyj=%4w*fqabJ$8HM!9O1)A!PQ7qZcLT=gAx3*CcH-8r zE5LqjdqHPGU3)=YXF*p%T})*vI}3Uo|F#v>(P0+>bb_ka`qyvedKDej5D9wjLbpg_ z`e-iz2W0CieU(bgFYr3CQRQ?L!8;cxP60O!DKJ)defxZBLHke>5y}42aJ&p0_LYFYi@1 zGriz^>D&2z>?2GsIA3~skNd3X&+m2fr8kb(1N5Tk&sgZ|bhWzv&qtvXtNF|A-(Y%q zf1EG9yk~x&=>_LYFYl*!GreG;ciKym--$_nd9OX>-}L+uoG*Q)PY=*xOfOjIdv&!n zeojpM&^ympw(}?cA=8*%aK7~7SMn{U z7cBI39{rt|^cVk;My3~>FMa<6%^=S7g7c*pzm=;*e|}S(FTMD?e4ptB3%%1`()c?u z=`a2tArb^x_wEJktx#m)>AMp-D_HIA414H=4urg7c*pKc(}TUa-)&d(NK|)AJI~!{YaCs>>qy0SoQ;{oZ8F&-XV--zwT>{W&iC&#TDsD#2Lxm#$L^WO%>@;rAR<4T`CUyn)qQ5wI(Se~CgVJy!> z#qf6|edPIO6k~Z_q3^Cxy*z(ZGnVIxddBj6kYX(N``0m+`}ZF)miuw~js^8E_t%dy zmiy(`7|Z?dZpP&kw0=dHmr6dyM=+NA%@Y{Q{p2LZaz9wbxUx+5SIt=N*S;sx=EZ6hT7|ZqfVEBvD zc*ynk>x||4c@kr}9!_N}*SGT+%k`?6v0Q&HV{EW}zL9YyIr@BK zxfsJRp0a;E0vK?Qt~HF4J$SAMFZ19Q55CfaZ}8wBd+@y;+~dJ7dhkvU{>+09gfdQj zj`HBK9(=k7&-LJC9!$Sv#D8nN=qH&@e1``=%qG` zxESx7o%;Dan7(M?tgrIm1s+`I!6^^E-h+Sc!N2uj`u2&F|4SbH7md+GAM|%S??l*y z@C$^y5bj2}2jM=1ZiM?09zggngv|)QLU<72*9i3c=ieaw7UBOO(0cxFgohF6r`J6Q zk0Q`7rne$Ij_?G+lL${CJdN-S!m|j!L!jSSKZo!>sn-W9Bo04sQ|sg=6+1fk&ywZ!@FB>9L8*EWVmjN?w|h zcl&3e)b`9|VEbfJfy=Fx3mhJ;D9Lcxw9CX*6D3|JO-B(tAsq<5k2YdoK34&GV%i1T z1=EEs2S~fr;dGf<=;FvNGZ=HZ)4wvKCw8pND7Sq5GHT$_mr|8cS1Tt-2lPsoWhg9vN1MzwES86(UGE*DY-6*~ z%R0+wWE}?9-|4Uj&JO7HRJ3cwMbS|L-$Wa+&$p{Uyc8XUZui8D3UR-4R%nOBj1u;B zbCoL>Ja36pN^v^0+n}V`p@zfF&~6h*DE~scKsgpVpu?lkF3r@1OEM%!xkvI^@)~q> zMSp_5X0_Xq9tD|>gH)K|F=!WNxC){w(*a)!wc{X=(_@gJ$5k-HRlh72Z&`^?T$HU0 z#mkzat#IE@lr>H&tB;@7wt8~wMWzm7QERU2eDvPzmCe)L6 z;)E5a&W+9db{T!zVM0`W+F^qFv_n}U-k?fdAABe?$USjlgYmEAtOP5ApKfg8icmu| z(Kex?d}76<32kRgfy3m4NfS>WL^vf|6lajWO%ZGi!%-MNbI7g;>%nc~yfBL!*e{lgTHshJZRz?g`3PNg z9T#-PJftpmDw_~zcJ60|_}w#Z)IUZL#+L8AU9GQ#siMvopT{l%lo4RDEtetC#SVPfDuJO#QN&RMm0ezl@v+4sZ z`oy(FV)PSh9k?9_TmsPYG#U6fr-3A&IT5R6XIJq zQlmbHV*z{-NAkR`1gdZ32$0X@*qFYQBM6l0YdC_z+=Z!LK9b{X<1M3hSQGeujrKgBm@z;8s{aHoUCwaJwP$C#n zKXH=QC`hn3yrXD^{sNPftOzHYqxdnGeSRT|AoU|Nt|1dO@#0mjEeTZX!3xR`)Il!N zI7bZ{&}WjO6FGyQpkaPkE#u)PVI+2(dHug^sS*)aYuK4P8` diff --git a/pymode/libs/pyflakes/test/__init__.py b/pymode/libs/pyflakes/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pyflakes/test/harness.py b/pymode/libs/pyflakes/test/harness.py deleted file mode 100644 index 009923f9..00000000 --- a/pymode/libs/pyflakes/test/harness.py +++ /dev/null @@ -1,72 +0,0 @@ - -import sys -import textwrap -import unittest - -from pyflakes import checker - -__all__ = ['TestCase', 'skip', 'skipIf'] - -if sys.version_info < (2, 7): - skip = lambda why: (lambda func: 'skip') # not callable - skipIf = lambda cond, why: (skip(why) if cond else lambda func: func) -else: - skip = unittest.skip - skipIf = unittest.skipIf -PyCF_ONLY_AST = 1024 - - -class TestCase(unittest.TestCase): - - withDoctest = False - - def flakes(self, input, *expectedOutputs, **kw): - tree = compile(textwrap.dedent(input), "", "exec", PyCF_ONLY_AST) - w = checker.Checker(tree, withDoctest=self.withDoctest, **kw) - outputs = [type(o) for o in w.messages] - expectedOutputs = list(expectedOutputs) - outputs.sort(key=lambda t: t.__name__) - expectedOutputs.sort(key=lambda t: t.__name__) - self.assertEqual(outputs, expectedOutputs, '''\ -for input: -%s -expected outputs: -%r -but got: -%s''' % (input, expectedOutputs, '\n'.join([str(o) for o in w.messages]))) - return w - - if not hasattr(unittest.TestCase, 'assertIs'): - - def assertIs(self, expr1, expr2, msg=None): - if expr1 is not expr2: - self.fail(msg or '%r is not %r' % (expr1, expr2)) - - if not hasattr(unittest.TestCase, 'assertIsInstance'): - - def assertIsInstance(self, obj, cls, msg=None): - """Same as self.assertTrue(isinstance(obj, cls)).""" - if not isinstance(obj, cls): - self.fail(msg or '%r is not an instance of %r' % (obj, cls)) - - if not hasattr(unittest.TestCase, 'assertNotIsInstance'): - - def assertNotIsInstance(self, obj, cls, msg=None): - """Same as self.assertFalse(isinstance(obj, cls)).""" - if isinstance(obj, cls): - self.fail(msg or '%r is an instance of %r' % (obj, cls)) - - if not hasattr(unittest.TestCase, 'assertIn'): - - def assertIn(self, member, container, msg=None): - """Just like self.assertTrue(a in b).""" - if member not in container: - self.fail(msg or '%r not found in %r' % (member, container)) - - if not hasattr(unittest.TestCase, 'assertNotIn'): - - def assertNotIn(self, member, container, msg=None): - """Just like self.assertTrue(a not in b).""" - if member in container: - self.fail(msg or - '%r unexpectedly found in %r' % (member, container)) diff --git a/pymode/libs/pyflakes/test/test_api.py b/pymode/libs/pyflakes/test/test_api.py deleted file mode 100644 index 77ee33cc..00000000 --- a/pymode/libs/pyflakes/test/test_api.py +++ /dev/null @@ -1,744 +0,0 @@ -""" -Tests for L{pyflakes.scripts.pyflakes}. -""" - -import os -import sys -import shutil -import subprocess -import tempfile - -from pyflakes.checker import PY2 -from pyflakes.messages import UnusedImport -from pyflakes.reporter import Reporter -from pyflakes.api import ( - main, - checkPath, - checkRecursive, - iterSourceCode, -) -from pyflakes.test.harness import TestCase, skipIf - -if sys.version_info < (3,): - from cStringIO import StringIO -else: - from io import StringIO - unichr = chr - -try: - sys.pypy_version_info - PYPY = True -except AttributeError: - PYPY = False - -try: - WindowsError - WIN = True -except NameError: - WIN = False - -ERROR_HAS_COL_NUM = ERROR_HAS_LAST_LINE = sys.version_info >= (3, 2) or PYPY - - -def withStderrTo(stderr, f, *args, **kwargs): - """ - Call C{f} with C{sys.stderr} redirected to C{stderr}. - """ - (outer, sys.stderr) = (sys.stderr, stderr) - try: - return f(*args, **kwargs) - finally: - sys.stderr = outer - - -class Node(object): - """ - Mock an AST node. - """ - def __init__(self, lineno, col_offset=0): - self.lineno = lineno - self.col_offset = col_offset - - -class SysStreamCapturing(object): - - """ - Context manager capturing sys.stdin, sys.stdout and sys.stderr. - - The file handles are replaced with a StringIO object. - On environments that support it, the StringIO object uses newlines - set to os.linesep. Otherwise newlines are converted from \\n to - os.linesep during __exit__. - """ - - def _create_StringIO(self, buffer=None): - # Python 3 has a newline argument - try: - return StringIO(buffer, newline=os.linesep) - except TypeError: - self._newline = True - # Python 2 creates an input only stream when buffer is not None - if buffer is None: - return StringIO() - else: - return StringIO(buffer) - - def __init__(self, stdin): - self._newline = False - self._stdin = self._create_StringIO(stdin or '') - - def __enter__(self): - self._orig_stdin = sys.stdin - self._orig_stdout = sys.stdout - self._orig_stderr = sys.stderr - - sys.stdin = self._stdin - sys.stdout = self._stdout_stringio = self._create_StringIO() - sys.stderr = self._stderr_stringio = self._create_StringIO() - - return self - - def __exit__(self, *args): - self.output = self._stdout_stringio.getvalue() - self.error = self._stderr_stringio.getvalue() - - if self._newline and os.linesep != '\n': - self.output = self.output.replace('\n', os.linesep) - self.error = self.error.replace('\n', os.linesep) - - sys.stdin = self._orig_stdin - sys.stdout = self._orig_stdout - sys.stderr = self._orig_stderr - - -class LoggingReporter(object): - """ - Implementation of Reporter that just appends any error to a list. - """ - - def __init__(self, log): - """ - Construct a C{LoggingReporter}. - - @param log: A list to append log messages to. - """ - self.log = log - - def flake(self, message): - self.log.append(('flake', str(message))) - - def unexpectedError(self, filename, message): - self.log.append(('unexpectedError', filename, message)) - - def syntaxError(self, filename, msg, lineno, offset, line): - self.log.append(('syntaxError', filename, msg, lineno, offset, line)) - - -class TestIterSourceCode(TestCase): - """ - Tests for L{iterSourceCode}. - """ - - def setUp(self): - self.tempdir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tempdir) - - def makeEmptyFile(self, *parts): - assert parts - fpath = os.path.join(self.tempdir, *parts) - fd = open(fpath, 'a') - fd.close() - return fpath - - def test_emptyDirectory(self): - """ - There are no Python files in an empty directory. - """ - self.assertEqual(list(iterSourceCode([self.tempdir])), []) - - def test_singleFile(self): - """ - If the directory contains one Python file, C{iterSourceCode} will find - it. - """ - childpath = self.makeEmptyFile('foo.py') - self.assertEqual(list(iterSourceCode([self.tempdir])), [childpath]) - - def test_onlyPythonSource(self): - """ - Files that are not Python source files are not included. - """ - self.makeEmptyFile('foo.pyc') - self.assertEqual(list(iterSourceCode([self.tempdir])), []) - - def test_recurses(self): - """ - If the Python files are hidden deep down in child directories, we will - find them. - """ - os.mkdir(os.path.join(self.tempdir, 'foo')) - apath = self.makeEmptyFile('foo', 'a.py') - os.mkdir(os.path.join(self.tempdir, 'bar')) - bpath = self.makeEmptyFile('bar', 'b.py') - cpath = self.makeEmptyFile('c.py') - self.assertEqual( - sorted(iterSourceCode([self.tempdir])), - sorted([apath, bpath, cpath])) - - def test_multipleDirectories(self): - """ - L{iterSourceCode} can be given multiple directories. It will recurse - into each of them. - """ - foopath = os.path.join(self.tempdir, 'foo') - barpath = os.path.join(self.tempdir, 'bar') - os.mkdir(foopath) - apath = self.makeEmptyFile('foo', 'a.py') - os.mkdir(barpath) - bpath = self.makeEmptyFile('bar', 'b.py') - self.assertEqual( - sorted(iterSourceCode([foopath, barpath])), - sorted([apath, bpath])) - - def test_explicitFiles(self): - """ - If one of the paths given to L{iterSourceCode} is not a directory but - a file, it will include that in its output. - """ - epath = self.makeEmptyFile('e.py') - self.assertEqual(list(iterSourceCode([epath])), - [epath]) - - -class TestReporter(TestCase): - """ - Tests for L{Reporter}. - """ - - def test_syntaxError(self): - """ - C{syntaxError} reports that there was a syntax error in the source - file. It reports to the error stream and includes the filename, line - number, error message, actual line of source and a caret pointing to - where the error is. - """ - err = StringIO() - reporter = Reporter(None, err) - reporter.syntaxError('foo.py', 'a problem', 3, 7, 'bad line of source') - self.assertEqual( - ("foo.py:3:8: a problem\n" - "bad line of source\n" - " ^\n"), - err.getvalue()) - - def test_syntaxErrorNoOffset(self): - """ - C{syntaxError} doesn't include a caret pointing to the error if - C{offset} is passed as C{None}. - """ - err = StringIO() - reporter = Reporter(None, err) - reporter.syntaxError('foo.py', 'a problem', 3, None, - 'bad line of source') - self.assertEqual( - ("foo.py:3: a problem\n" - "bad line of source\n"), - err.getvalue()) - - def test_multiLineSyntaxError(self): - """ - If there's a multi-line syntax error, then we only report the last - line. The offset is adjusted so that it is relative to the start of - the last line. - """ - err = StringIO() - lines = [ - 'bad line of source', - 'more bad lines of source', - ] - reporter = Reporter(None, err) - reporter.syntaxError('foo.py', 'a problem', 3, len(lines[0]) + 7, - '\n'.join(lines)) - self.assertEqual( - ("foo.py:3:7: a problem\n" + - lines[-1] + "\n" + - " ^\n"), - err.getvalue()) - - def test_unexpectedError(self): - """ - C{unexpectedError} reports an error processing a source file. - """ - err = StringIO() - reporter = Reporter(None, err) - reporter.unexpectedError('source.py', 'error message') - self.assertEqual('source.py: error message\n', err.getvalue()) - - def test_flake(self): - """ - C{flake} reports a code warning from Pyflakes. It is exactly the - str() of a L{pyflakes.messages.Message}. - """ - out = StringIO() - reporter = Reporter(out, None) - message = UnusedImport('foo.py', Node(42), 'bar') - reporter.flake(message) - self.assertEqual(out.getvalue(), "%s\n" % (message,)) - - -class CheckTests(TestCase): - """ - Tests for L{check} and L{checkPath} which check a file for flakes. - """ - - def makeTempFile(self, content): - """ - Make a temporary file containing C{content} and return a path to it. - """ - _, fpath = tempfile.mkstemp() - if not hasattr(content, 'decode'): - content = content.encode('ascii') - fd = open(fpath, 'wb') - fd.write(content) - fd.close() - return fpath - - def assertHasErrors(self, path, errorList): - """ - Assert that C{path} causes errors. - - @param path: A path to a file to check. - @param errorList: A list of errors expected to be printed to stderr. - """ - err = StringIO() - count = withStderrTo(err, checkPath, path) - self.assertEqual( - (count, err.getvalue()), (len(errorList), ''.join(errorList))) - - def getErrors(self, path): - """ - Get any warnings or errors reported by pyflakes for the file at C{path}. - - @param path: The path to a Python file on disk that pyflakes will check. - @return: C{(count, log)}, where C{count} is the number of warnings or - errors generated, and log is a list of those warnings, presented - as structured data. See L{LoggingReporter} for more details. - """ - log = [] - reporter = LoggingReporter(log) - count = checkPath(path, reporter) - return count, log - - def test_legacyScript(self): - from pyflakes.scripts import pyflakes as script_pyflakes - self.assertIs(script_pyflakes.checkPath, checkPath) - - def test_missingTrailingNewline(self): - """ - Source which doesn't end with a newline shouldn't cause any - exception to be raised nor an error indicator to be returned by - L{check}. - """ - fName = self.makeTempFile("def foo():\n\tpass\n\t") - self.assertHasErrors(fName, []) - - def test_checkPathNonExisting(self): - """ - L{checkPath} handles non-existing files. - """ - count, errors = self.getErrors('extremo') - self.assertEqual(count, 1) - self.assertEqual( - errors, - [('unexpectedError', 'extremo', 'No such file or directory')]) - - def test_multilineSyntaxError(self): - """ - Source which includes a syntax error which results in the raised - L{SyntaxError.text} containing multiple lines of source are reported - with only the last line of that source. - """ - source = """\ -def foo(): - ''' - -def bar(): - pass - -def baz(): - '''quux''' -""" - - # Sanity check - SyntaxError.text should be multiple lines, if it - # isn't, something this test was unprepared for has happened. - def evaluate(source): - exec(source) - try: - evaluate(source) - except SyntaxError: - e = sys.exc_info()[1] - if not PYPY: - self.assertTrue(e.text.count('\n') > 1) - else: - self.fail() - - sourcePath = self.makeTempFile(source) - - if PYPY: - message = 'EOF while scanning triple-quoted string literal' - else: - message = 'invalid syntax' - - self.assertHasErrors( - sourcePath, - ["""\ -%s:8:11: %s - '''quux''' - ^ -""" % (sourcePath, message)]) - - def test_eofSyntaxError(self): - """ - The error reported for source files which end prematurely causing a - syntax error reflects the cause for the syntax error. - """ - sourcePath = self.makeTempFile("def foo(") - if PYPY: - result = """\ -%s:1:7: parenthesis is never closed -def foo( - ^ -""" % (sourcePath,) - else: - result = """\ -%s:1:9: unexpected EOF while parsing -def foo( - ^ -""" % (sourcePath,) - - self.assertHasErrors( - sourcePath, - [result]) - - def test_eofSyntaxErrorWithTab(self): - """ - The error reported for source files which end prematurely causing a - syntax error reflects the cause for the syntax error. - """ - sourcePath = self.makeTempFile("if True:\n\tfoo =") - column = 5 if PYPY else 7 - last_line = '\t ^' if PYPY else '\t ^' - - self.assertHasErrors( - sourcePath, - ["""\ -%s:2:%s: invalid syntax -\tfoo = -%s -""" % (sourcePath, column, last_line)]) - - def test_nonDefaultFollowsDefaultSyntaxError(self): - """ - Source which has a non-default argument following a default argument - should include the line number of the syntax error. However these - exceptions do not include an offset. - """ - source = """\ -def foo(bar=baz, bax): - pass -""" - sourcePath = self.makeTempFile(source) - last_line = ' ^\n' if ERROR_HAS_LAST_LINE else '' - column = '8:' if ERROR_HAS_COL_NUM else '' - self.assertHasErrors( - sourcePath, - ["""\ -%s:1:%s non-default argument follows default argument -def foo(bar=baz, bax): -%s""" % (sourcePath, column, last_line)]) - - def test_nonKeywordAfterKeywordSyntaxError(self): - """ - Source which has a non-keyword argument after a keyword argument should - include the line number of the syntax error. However these exceptions - do not include an offset. - """ - source = """\ -foo(bar=baz, bax) -""" - sourcePath = self.makeTempFile(source) - last_line = ' ^\n' if ERROR_HAS_LAST_LINE else '' - column = '13:' if ERROR_HAS_COL_NUM or PYPY else '' - - if sys.version_info >= (3, 5): - message = 'positional argument follows keyword argument' - else: - message = 'non-keyword arg after keyword arg' - - self.assertHasErrors( - sourcePath, - ["""\ -%s:1:%s %s -foo(bar=baz, bax) -%s""" % (sourcePath, column, message, last_line)]) - - def test_invalidEscape(self): - """ - The invalid escape syntax raises ValueError in Python 2 - """ - ver = sys.version_info - # ValueError: invalid \x escape - sourcePath = self.makeTempFile(r"foo = '\xyz'") - if ver < (3,): - decoding_error = "%s: problem decoding source\n" % (sourcePath,) - elif PYPY: - # pypy3 only - decoding_error = """\ -%s:1:6: %s: ('unicodeescape', b'\\\\xyz', 0, 2, 'truncated \\\\xXX escape') -foo = '\\xyz' - ^ -""" % (sourcePath, 'UnicodeDecodeError') - else: - last_line = ' ^\n' if ERROR_HAS_LAST_LINE else '' - # Column has been "fixed" since 3.2.4 and 3.3.1 - col = 1 if ver >= (3, 3, 1) or ((3, 2, 4) <= ver < (3, 3)) else 2 - decoding_error = """\ -%s:1:7: (unicode error) 'unicodeescape' codec can't decode bytes \ -in position 0-%d: truncated \\xXX escape -foo = '\\xyz' -%s""" % (sourcePath, col, last_line) - self.assertHasErrors( - sourcePath, [decoding_error]) - - @skipIf(sys.platform == 'win32', 'unsupported on Windows') - def test_permissionDenied(self): - """ - If the source file is not readable, this is reported on standard - error. - """ - sourcePath = self.makeTempFile('') - os.chmod(sourcePath, 0) - count, errors = self.getErrors(sourcePath) - self.assertEqual(count, 1) - self.assertEqual( - errors, - [('unexpectedError', sourcePath, "Permission denied")]) - - def test_pyflakesWarning(self): - """ - If the source file has a pyflakes warning, this is reported as a - 'flake'. - """ - sourcePath = self.makeTempFile("import foo") - count, errors = self.getErrors(sourcePath) - self.assertEqual(count, 1) - self.assertEqual( - errors, [('flake', str(UnusedImport(sourcePath, Node(1), 'foo')))]) - - def test_encodedFileUTF8(self): - """ - If source file declares the correct encoding, no error is reported. - """ - SNOWMAN = unichr(0x2603) - source = ("""\ -# coding: utf-8 -x = "%s" -""" % SNOWMAN).encode('utf-8') - sourcePath = self.makeTempFile(source) - self.assertHasErrors(sourcePath, []) - - def test_CRLFLineEndings(self): - """ - Source files with Windows CR LF line endings are parsed successfully. - """ - sourcePath = self.makeTempFile("x = 42\r\n") - self.assertHasErrors(sourcePath, []) - - def test_misencodedFileUTF8(self): - """ - If a source file contains bytes which cannot be decoded, this is - reported on stderr. - """ - SNOWMAN = unichr(0x2603) - source = ("""\ -# coding: ascii -x = "%s" -""" % SNOWMAN).encode('utf-8') - sourcePath = self.makeTempFile(source) - - if PYPY and sys.version_info < (3, ): - message = ('\'ascii\' codec can\'t decode byte 0xe2 ' - 'in position 21: ordinal not in range(128)') - result = """\ -%s:0:0: %s -x = "\xe2\x98\x83" - ^\n""" % (sourcePath, message) - - else: - message = 'problem decoding source' - result = "%s: problem decoding source\n" % (sourcePath,) - - self.assertHasErrors( - sourcePath, [result]) - - def test_misencodedFileUTF16(self): - """ - If a source file contains bytes which cannot be decoded, this is - reported on stderr. - """ - SNOWMAN = unichr(0x2603) - source = ("""\ -# coding: ascii -x = "%s" -""" % SNOWMAN).encode('utf-16') - sourcePath = self.makeTempFile(source) - self.assertHasErrors( - sourcePath, ["%s: problem decoding source\n" % (sourcePath,)]) - - def test_checkRecursive(self): - """ - L{checkRecursive} descends into each directory, finding Python files - and reporting problems. - """ - tempdir = tempfile.mkdtemp() - os.mkdir(os.path.join(tempdir, 'foo')) - file1 = os.path.join(tempdir, 'foo', 'bar.py') - fd = open(file1, 'wb') - fd.write("import baz\n".encode('ascii')) - fd.close() - file2 = os.path.join(tempdir, 'baz.py') - fd = open(file2, 'wb') - fd.write("import contraband".encode('ascii')) - fd.close() - log = [] - reporter = LoggingReporter(log) - warnings = checkRecursive([tempdir], reporter) - self.assertEqual(warnings, 2) - self.assertEqual( - sorted(log), - sorted([('flake', str(UnusedImport(file1, Node(1), 'baz'))), - ('flake', - str(UnusedImport(file2, Node(1), 'contraband')))])) - - -class IntegrationTests(TestCase): - """ - Tests of the pyflakes script that actually spawn the script. - """ - - def setUp(self): - self.tempdir = tempfile.mkdtemp() - self.tempfilepath = os.path.join(self.tempdir, 'temp') - - def tearDown(self): - shutil.rmtree(self.tempdir) - - def getPyflakesBinary(self): - """ - Return the path to the pyflakes binary. - """ - import pyflakes - package_dir = os.path.dirname(pyflakes.__file__) - return os.path.join(package_dir, '..', 'bin', 'pyflakes') - - def runPyflakes(self, paths, stdin=None): - """ - Launch a subprocess running C{pyflakes}. - - @param paths: Command-line arguments to pass to pyflakes. - @param stdin: Text to use as stdin. - @return: C{(returncode, stdout, stderr)} of the completed pyflakes - process. - """ - env = dict(os.environ) - env['PYTHONPATH'] = os.pathsep.join(sys.path) - command = [sys.executable, self.getPyflakesBinary()] - command.extend(paths) - if stdin: - p = subprocess.Popen(command, env=env, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (stdout, stderr) = p.communicate(stdin.encode('ascii')) - else: - p = subprocess.Popen(command, env=env, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (stdout, stderr) = p.communicate() - rv = p.wait() - if sys.version_info >= (3,): - stdout = stdout.decode('utf-8') - stderr = stderr.decode('utf-8') - # Workaround https://bitbucket.org/pypy/pypy/issues/2350 - if PYPY and PY2 and WIN: - stderr = stderr.replace('\r\r\n', '\r\n') - return (stdout, stderr, rv) - - def test_goodFile(self): - """ - When a Python source file is all good, the return code is zero and no - messages are printed to either stdout or stderr. - """ - fd = open(self.tempfilepath, 'a') - fd.close() - d = self.runPyflakes([self.tempfilepath]) - self.assertEqual(d, ('', '', 0)) - - def test_fileWithFlakes(self): - """ - When a Python source file has warnings, the return code is non-zero - and the warnings are printed to stdout. - """ - fd = open(self.tempfilepath, 'wb') - fd.write("import contraband\n".encode('ascii')) - fd.close() - d = self.runPyflakes([self.tempfilepath]) - expected = UnusedImport(self.tempfilepath, Node(1), 'contraband') - self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1)) - - def test_errors_io(self): - """ - When pyflakes finds errors with the files it's given, (if they don't - exist, say), then the return code is non-zero and the errors are - printed to stderr. - """ - d = self.runPyflakes([self.tempfilepath]) - error_msg = '%s: No such file or directory%s' % (self.tempfilepath, - os.linesep) - self.assertEqual(d, ('', error_msg, 1)) - - def test_errors_syntax(self): - """ - When pyflakes finds errors with the files it's given, (if they don't - exist, say), then the return code is non-zero and the errors are - printed to stderr. - """ - fd = open(self.tempfilepath, 'wb') - fd.write("import".encode('ascii')) - fd.close() - d = self.runPyflakes([self.tempfilepath]) - error_msg = '{0}:1:{2}: invalid syntax{1}import{1} {3}^{1}'.format( - self.tempfilepath, os.linesep, 5 if PYPY else 7, '' if PYPY else ' ') - self.assertEqual(d, ('', error_msg, True)) - - def test_readFromStdin(self): - """ - If no arguments are passed to C{pyflakes} then it reads from stdin. - """ - d = self.runPyflakes([], stdin='import contraband') - expected = UnusedImport('', Node(1), 'contraband') - self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1)) - - -class TestMain(IntegrationTests): - """ - Tests of the pyflakes main function. - """ - - def runPyflakes(self, paths, stdin=None): - try: - with SysStreamCapturing(stdin) as capture: - main(args=paths) - except SystemExit as e: - return (capture.output, capture.error, e.code) - else: - raise RuntimeError('SystemExit not raised') diff --git a/pymode/libs/pyflakes/test/test_dict.py b/pymode/libs/pyflakes/test/test_dict.py deleted file mode 100644 index 628ec0ca..00000000 --- a/pymode/libs/pyflakes/test/test_dict.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -Tests for dict duplicate keys Pyflakes behavior. -""" - -from sys import version_info - -from pyflakes import messages as m -from pyflakes.test.harness import TestCase, skipIf - - -class Test(TestCase): - - def test_duplicate_keys(self): - self.flakes( - "{'yes': 1, 'yes': 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - @skipIf(version_info < (3,), - "bytes and strings with same 'value' are not equal in python3") - @skipIf(version_info[0:2] == (3, 2), - "python3.2 does not allow u"" literal string definition") - def test_duplicate_keys_bytes_vs_unicode_py3(self): - self.flakes("{b'a': 1, u'a': 2}") - - @skipIf(version_info < (3,), - "bytes and strings with same 'value' are not equal in python3") - @skipIf(version_info[0:2] == (3, 2), - "python3.2 does not allow u"" literal string definition") - def test_duplicate_values_bytes_vs_unicode_py3(self): - self.flakes( - "{1: b'a', 1: u'a'}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - @skipIf(version_info >= (3,), - "bytes and strings with same 'value' are equal in python2") - def test_duplicate_keys_bytes_vs_unicode_py2(self): - self.flakes( - "{b'a': 1, u'a': 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - @skipIf(version_info >= (3,), - "bytes and strings with same 'value' are equal in python2") - def test_duplicate_values_bytes_vs_unicode_py2(self): - self.flakes("{1: b'a', 1: u'a'}") - - def test_multiple_duplicate_keys(self): - self.flakes( - "{'yes': 1, 'yes': 2, 'no': 2, 'no': 3}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_in_function(self): - self.flakes( - ''' - def f(thing): - pass - f({'yes': 1, 'yes': 2}) - ''', - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_in_lambda(self): - self.flakes( - "lambda x: {(0,1): 1, (0,1): 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_tuples(self): - self.flakes( - "{(0,1): 1, (0,1): 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_tuples_int_and_float(self): - self.flakes( - "{(0,1): 1, (0,1.0): 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_ints(self): - self.flakes( - "{1: 1, 1: 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_bools(self): - self.flakes( - "{True: 1, True: 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_bools_false(self): - # Needed to ensure 2.x correctly coerces these from variables - self.flakes( - "{False: 1, False: 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_keys_none(self): - self.flakes( - "{None: 1, None: 2}", - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_variable_keys(self): - self.flakes( - ''' - a = 1 - {a: 1, a: 2} - ''', - m.MultiValueRepeatedKeyVariable, - m.MultiValueRepeatedKeyVariable, - ) - - def test_duplicate_variable_values(self): - self.flakes( - ''' - a = 1 - b = 2 - {1: a, 1: b} - ''', - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_variable_values_same_value(self): - # Current behaviour is not to look up variable values. This is to - # confirm that. - self.flakes( - ''' - a = 1 - b = 1 - {1: a, 1: b} - ''', - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_duplicate_key_float_and_int(self): - """ - These do look like different values, but when it comes to their use as - keys, they compare as equal and so are actually duplicates. - The literal dict {1: 1, 1.0: 1} actually becomes {1.0: 1}. - """ - self.flakes( - ''' - {1: 1, 1.0: 2} - ''', - m.MultiValueRepeatedKeyLiteral, - m.MultiValueRepeatedKeyLiteral, - ) - - def test_no_duplicate_key_error_same_value(self): - self.flakes(''' - {'yes': 1, 'yes': 1} - ''') - - def test_no_duplicate_key_errors(self): - self.flakes(''' - {'yes': 1, 'no': 2} - ''') - - def test_no_duplicate_keys_tuples_same_first_element(self): - self.flakes("{(0,1): 1, (0,2): 1}") - - def test_no_duplicate_key_errors_func_call(self): - self.flakes(''' - def test(thing): - pass - test({True: 1, None: 2, False: 1}) - ''') - - def test_no_duplicate_key_errors_bool_or_none(self): - self.flakes("{True: 1, None: 2, False: 1}") - - def test_no_duplicate_key_errors_ints(self): - self.flakes(''' - {1: 1, 2: 1} - ''') - - def test_no_duplicate_key_errors_vars(self): - self.flakes(''' - test = 'yes' - rest = 'yes' - {test: 1, rest: 2} - ''') - - def test_no_duplicate_key_errors_tuples(self): - self.flakes(''' - {(0,1): 1, (0,2): 1} - ''') - - def test_no_duplicate_key_errors_instance_attributes(self): - self.flakes(''' - class Test(): - pass - f = Test() - f.a = 1 - {f.a: 1, f.a: 1} - ''') diff --git a/pymode/libs/pyflakes/test/test_doctests.py b/pymode/libs/pyflakes/test/test_doctests.py deleted file mode 100644 index aed7957b..00000000 --- a/pymode/libs/pyflakes/test/test_doctests.py +++ /dev/null @@ -1,442 +0,0 @@ -import sys -import textwrap - -from pyflakes import messages as m -from pyflakes.checker import ( - DoctestScope, - FunctionScope, - ModuleScope, -) -from pyflakes.test.test_other import Test as TestOther -from pyflakes.test.test_imports import Test as TestImports -from pyflakes.test.test_undefined_names import Test as TestUndefinedNames -from pyflakes.test.harness import TestCase, skip - -try: - sys.pypy_version_info - PYPY = True -except AttributeError: - PYPY = False - - -class _DoctestMixin(object): - - withDoctest = True - - def doctestify(self, input): - lines = [] - for line in textwrap.dedent(input).splitlines(): - if line.strip() == '': - pass - elif (line.startswith(' ') or - line.startswith('except:') or - line.startswith('except ') or - line.startswith('finally:') or - line.startswith('else:') or - line.startswith('elif ')): - line = "... %s" % line - else: - line = ">>> %s" % line - lines.append(line) - doctestificator = textwrap.dedent('''\ - def doctest_something(): - """ - %s - """ - ''') - return doctestificator % "\n ".join(lines) - - def flakes(self, input, *args, **kw): - return super(_DoctestMixin, self).flakes(self.doctestify(input), *args, **kw) - - -class Test(TestCase): - - withDoctest = True - - def test_scope_class(self): - """Check that a doctest is given a DoctestScope.""" - checker = self.flakes(""" - m = None - - def doctest_stuff(): - ''' - >>> d = doctest_stuff() - ''' - f = m - return f - """) - - scopes = checker.deadScopes - module_scopes = [ - scope for scope in scopes if scope.__class__ is ModuleScope] - doctest_scopes = [ - scope for scope in scopes if scope.__class__ is DoctestScope] - function_scopes = [ - scope for scope in scopes if scope.__class__ is FunctionScope] - - self.assertEqual(len(module_scopes), 1) - self.assertEqual(len(doctest_scopes), 1) - - module_scope = module_scopes[0] - doctest_scope = doctest_scopes[0] - - self.assertIsInstance(doctest_scope, DoctestScope) - self.assertIsInstance(doctest_scope, ModuleScope) - self.assertNotIsInstance(doctest_scope, FunctionScope) - self.assertNotIsInstance(module_scope, DoctestScope) - - self.assertIn('m', module_scope) - self.assertIn('doctest_stuff', module_scope) - - self.assertIn('d', doctest_scope) - - self.assertEqual(len(function_scopes), 1) - self.assertIn('f', function_scopes[0]) - - def test_nested_doctest_ignored(self): - """Check that nested doctests are ignored.""" - checker = self.flakes(""" - m = None - - def doctest_stuff(): - ''' - >>> def function_in_doctest(): - ... \"\"\" - ... >>> ignored_undefined_name - ... \"\"\" - ... df = m - ... return df - ... - >>> function_in_doctest() - ''' - f = m - return f - """) - - scopes = checker.deadScopes - module_scopes = [ - scope for scope in scopes if scope.__class__ is ModuleScope] - doctest_scopes = [ - scope for scope in scopes if scope.__class__ is DoctestScope] - function_scopes = [ - scope for scope in scopes if scope.__class__ is FunctionScope] - - self.assertEqual(len(module_scopes), 1) - self.assertEqual(len(doctest_scopes), 1) - - module_scope = module_scopes[0] - doctest_scope = doctest_scopes[0] - - self.assertIn('m', module_scope) - self.assertIn('doctest_stuff', module_scope) - self.assertIn('function_in_doctest', doctest_scope) - - self.assertEqual(len(function_scopes), 2) - - self.assertIn('f', function_scopes[0]) - self.assertIn('df', function_scopes[1]) - - def test_global_module_scope_pollution(self): - """Check that global in doctest does not pollute module scope.""" - checker = self.flakes(""" - def doctest_stuff(): - ''' - >>> def function_in_doctest(): - ... global m - ... m = 50 - ... df = 10 - ... m = df - ... - >>> function_in_doctest() - ''' - f = 10 - return f - - """) - - scopes = checker.deadScopes - module_scopes = [ - scope for scope in scopes if scope.__class__ is ModuleScope] - doctest_scopes = [ - scope for scope in scopes if scope.__class__ is DoctestScope] - function_scopes = [ - scope for scope in scopes if scope.__class__ is FunctionScope] - - self.assertEqual(len(module_scopes), 1) - self.assertEqual(len(doctest_scopes), 1) - - module_scope = module_scopes[0] - doctest_scope = doctest_scopes[0] - - self.assertIn('doctest_stuff', module_scope) - self.assertIn('function_in_doctest', doctest_scope) - - self.assertEqual(len(function_scopes), 2) - - self.assertIn('f', function_scopes[0]) - self.assertIn('df', function_scopes[1]) - self.assertIn('m', function_scopes[1]) - - self.assertNotIn('m', module_scope) - - def test_global_undefined(self): - self.flakes(""" - global m - - def doctest_stuff(): - ''' - >>> m - ''' - """, m.UndefinedName) - - def test_nested_class(self): - """Doctest within nested class are processed.""" - self.flakes(""" - class C: - class D: - ''' - >>> m - ''' - def doctest_stuff(self): - ''' - >>> m - ''' - return 1 - """, m.UndefinedName, m.UndefinedName) - - def test_ignore_nested_function(self): - """Doctest module does not process doctest in nested functions.""" - # 'syntax error' would cause a SyntaxError if the doctest was processed. - # However doctest does not find doctest in nested functions - # (https://bugs.python.org/issue1650090). If nested functions were - # processed, this use of m should cause UndefinedName, and the - # name inner_function should probably exist in the doctest scope. - self.flakes(""" - def doctest_stuff(): - def inner_function(): - ''' - >>> syntax error - >>> inner_function() - 1 - >>> m - ''' - return 1 - m = inner_function() - return m - """) - - def test_inaccessible_scope_class(self): - """Doctest may not access class scope.""" - self.flakes(""" - class C: - def doctest_stuff(self): - ''' - >>> m - ''' - return 1 - m = 1 - """, m.UndefinedName) - - def test_importBeforeDoctest(self): - self.flakes(""" - import foo - - def doctest_stuff(): - ''' - >>> foo - ''' - """) - - @skip("todo") - def test_importBeforeAndInDoctest(self): - self.flakes(''' - import foo - - def doctest_stuff(): - """ - >>> import foo - >>> foo - """ - - foo - ''', m.RedefinedWhileUnused) - - def test_importInDoctestAndAfter(self): - self.flakes(''' - def doctest_stuff(): - """ - >>> import foo - >>> foo - """ - - import foo - foo() - ''') - - def test_offsetInDoctests(self): - exc = self.flakes(''' - - def doctest_stuff(): - """ - >>> x # line 5 - """ - - ''', m.UndefinedName).messages[0] - self.assertEqual(exc.lineno, 5) - self.assertEqual(exc.col, 12) - - def test_offsetInLambdasInDoctests(self): - exc = self.flakes(''' - - def doctest_stuff(): - """ - >>> lambda: x # line 5 - """ - - ''', m.UndefinedName).messages[0] - self.assertEqual(exc.lineno, 5) - self.assertEqual(exc.col, 20) - - def test_offsetAfterDoctests(self): - exc = self.flakes(''' - - def doctest_stuff(): - """ - >>> x = 5 - """ - - x - - ''', m.UndefinedName).messages[0] - self.assertEqual(exc.lineno, 8) - self.assertEqual(exc.col, 0) - - def test_syntaxErrorInDoctest(self): - exceptions = self.flakes( - ''' - def doctest_stuff(): - """ - >>> from # line 4 - >>> fortytwo = 42 - >>> except Exception: - """ - ''', - m.DoctestSyntaxError, - m.DoctestSyntaxError, - m.DoctestSyntaxError).messages - exc = exceptions[0] - self.assertEqual(exc.lineno, 4) - self.assertEqual(exc.col, 26) - - # PyPy error column offset is 0, - # for the second and third line of the doctest - # i.e. at the beginning of the line - exc = exceptions[1] - self.assertEqual(exc.lineno, 5) - if PYPY: - self.assertEqual(exc.col, 13) - else: - self.assertEqual(exc.col, 16) - exc = exceptions[2] - self.assertEqual(exc.lineno, 6) - if PYPY: - self.assertEqual(exc.col, 13) - else: - self.assertEqual(exc.col, 18) - - def test_indentationErrorInDoctest(self): - exc = self.flakes(''' - def doctest_stuff(): - """ - >>> if True: - ... pass - """ - ''', m.DoctestSyntaxError).messages[0] - self.assertEqual(exc.lineno, 5) - if PYPY: - self.assertEqual(exc.col, 13) - else: - self.assertEqual(exc.col, 16) - - def test_offsetWithMultiLineArgs(self): - (exc1, exc2) = self.flakes( - ''' - def doctest_stuff(arg1, - arg2, - arg3): - """ - >>> assert - >>> this - """ - ''', - m.DoctestSyntaxError, - m.UndefinedName).messages - self.assertEqual(exc1.lineno, 6) - self.assertEqual(exc1.col, 19) - self.assertEqual(exc2.lineno, 7) - self.assertEqual(exc2.col, 12) - - def test_doctestCanReferToFunction(self): - self.flakes(""" - def foo(): - ''' - >>> foo - ''' - """) - - def test_doctestCanReferToClass(self): - self.flakes(""" - class Foo(): - ''' - >>> Foo - ''' - def bar(self): - ''' - >>> Foo - ''' - """) - - def test_noOffsetSyntaxErrorInDoctest(self): - exceptions = self.flakes( - ''' - def buildurl(base, *args, **kwargs): - """ - >>> buildurl('/blah.php', ('a', '&'), ('b', '=') - '/blah.php?a=%26&b=%3D' - >>> buildurl('/blah.php', a='&', 'b'='=') - '/blah.php?b=%3D&a=%26' - """ - pass - ''', - m.DoctestSyntaxError, - m.DoctestSyntaxError).messages - exc = exceptions[0] - self.assertEqual(exc.lineno, 4) - exc = exceptions[1] - self.assertEqual(exc.lineno, 6) - - def test_singleUnderscoreInDoctest(self): - self.flakes(''' - def func(): - """A docstring - - >>> func() - 1 - >>> _ - 1 - """ - return 1 - ''') - - -class TestOther(_DoctestMixin, TestOther): - """Run TestOther with each test wrapped in a doctest.""" - - -class TestImports(_DoctestMixin, TestImports): - """Run TestImports with each test wrapped in a doctest.""" - - -class TestUndefinedNames(_DoctestMixin, TestUndefinedNames): - """Run TestUndefinedNames with each test wrapped in a doctest.""" diff --git a/pymode/libs/pyflakes/test/test_imports.py b/pymode/libs/pyflakes/test/test_imports.py deleted file mode 100644 index 3e3be88a..00000000 --- a/pymode/libs/pyflakes/test/test_imports.py +++ /dev/null @@ -1,1180 +0,0 @@ - -from sys import version_info - -from pyflakes import messages as m -from pyflakes.checker import ( - FutureImportation, - Importation, - ImportationFrom, - StarImportation, - SubmoduleImportation, -) -from pyflakes.test.harness import TestCase, skip, skipIf - - -class TestImportationObject(TestCase): - - def test_import_basic(self): - binding = Importation('a', None, 'a') - assert binding.source_statement == 'import a' - assert str(binding) == 'a' - - def test_import_as(self): - binding = Importation('c', None, 'a') - assert binding.source_statement == 'import a as c' - assert str(binding) == 'a as c' - - def test_import_submodule(self): - binding = SubmoduleImportation('a.b', None) - assert binding.source_statement == 'import a.b' - assert str(binding) == 'a.b' - - def test_import_submodule_as(self): - # A submodule import with an as clause is not a SubmoduleImportation - binding = Importation('c', None, 'a.b') - assert binding.source_statement == 'import a.b as c' - assert str(binding) == 'a.b as c' - - def test_import_submodule_as_source_name(self): - binding = Importation('a', None, 'a.b') - assert binding.source_statement == 'import a.b as a' - assert str(binding) == 'a.b as a' - - def test_importfrom_relative(self): - binding = ImportationFrom('a', None, '.', 'a') - assert binding.source_statement == 'from . import a' - assert str(binding) == '.a' - - def test_importfrom_relative_parent(self): - binding = ImportationFrom('a', None, '..', 'a') - assert binding.source_statement == 'from .. import a' - assert str(binding) == '..a' - - def test_importfrom_relative_with_module(self): - binding = ImportationFrom('b', None, '..a', 'b') - assert binding.source_statement == 'from ..a import b' - assert str(binding) == '..a.b' - - def test_importfrom_relative_with_module_as(self): - binding = ImportationFrom('c', None, '..a', 'b') - assert binding.source_statement == 'from ..a import b as c' - assert str(binding) == '..a.b as c' - - def test_importfrom_member(self): - binding = ImportationFrom('b', None, 'a', 'b') - assert binding.source_statement == 'from a import b' - assert str(binding) == 'a.b' - - def test_importfrom_submodule_member(self): - binding = ImportationFrom('c', None, 'a.b', 'c') - assert binding.source_statement == 'from a.b import c' - assert str(binding) == 'a.b.c' - - def test_importfrom_member_as(self): - binding = ImportationFrom('c', None, 'a', 'b') - assert binding.source_statement == 'from a import b as c' - assert str(binding) == 'a.b as c' - - def test_importfrom_submodule_member_as(self): - binding = ImportationFrom('d', None, 'a.b', 'c') - assert binding.source_statement == 'from a.b import c as d' - assert str(binding) == 'a.b.c as d' - - def test_importfrom_star(self): - binding = StarImportation('a.b', None) - assert binding.source_statement == 'from a.b import *' - assert str(binding) == 'a.b.*' - - def test_importfrom_star_relative(self): - binding = StarImportation('.b', None) - assert binding.source_statement == 'from .b import *' - assert str(binding) == '.b.*' - - def test_importfrom_future(self): - binding = FutureImportation('print_function', None, None) - assert binding.source_statement == 'from __future__ import print_function' - assert str(binding) == '__future__.print_function' - - -class Test(TestCase): - - def test_unusedImport(self): - self.flakes('import fu, bar', m.UnusedImport, m.UnusedImport) - self.flakes('from baz import fu, bar', m.UnusedImport, m.UnusedImport) - - def test_unusedImport_relative(self): - self.flakes('from . import fu', m.UnusedImport) - self.flakes('from . import fu as baz', m.UnusedImport) - self.flakes('from .. import fu', m.UnusedImport) - self.flakes('from ... import fu', m.UnusedImport) - self.flakes('from .. import fu as baz', m.UnusedImport) - self.flakes('from .bar import fu', m.UnusedImport) - self.flakes('from ..bar import fu', m.UnusedImport) - self.flakes('from ...bar import fu', m.UnusedImport) - self.flakes('from ...bar import fu as baz', m.UnusedImport) - - checker = self.flakes('from . import fu', m.UnusedImport) - - error = checker.messages[0] - assert error.message == '%r imported but unused' - assert error.message_args == ('.fu', ) - - checker = self.flakes('from . import fu as baz', m.UnusedImport) - - error = checker.messages[0] - assert error.message == '%r imported but unused' - assert error.message_args == ('.fu as baz', ) - - def test_aliasedImport(self): - self.flakes('import fu as FU, bar as FU', - m.RedefinedWhileUnused, m.UnusedImport) - self.flakes('from moo import fu as FU, bar as FU', - m.RedefinedWhileUnused, m.UnusedImport) - - def test_aliasedImportShadowModule(self): - """Imported aliases can shadow the source of the import.""" - self.flakes('from moo import fu as moo; moo') - self.flakes('import fu as fu; fu') - self.flakes('import fu.bar as fu; fu') - - def test_usedImport(self): - self.flakes('import fu; print(fu)') - self.flakes('from baz import fu; print(fu)') - self.flakes('import fu; del fu') - - def test_usedImport_relative(self): - self.flakes('from . import fu; assert fu') - self.flakes('from .bar import fu; assert fu') - self.flakes('from .. import fu; assert fu') - self.flakes('from ..bar import fu as baz; assert baz') - - def test_redefinedWhileUnused(self): - self.flakes('import fu; fu = 3', m.RedefinedWhileUnused) - self.flakes('import fu; fu, bar = 3', m.RedefinedWhileUnused) - self.flakes('import fu; [fu, bar] = 3', m.RedefinedWhileUnused) - - def test_redefinedIf(self): - """ - Test that importing a module twice within an if - block does raise a warning. - """ - self.flakes(''' - i = 2 - if i==1: - import os - import os - os.path''', m.RedefinedWhileUnused) - - def test_redefinedIfElse(self): - """ - Test that importing a module twice in if - and else blocks does not raise a warning. - """ - self.flakes(''' - i = 2 - if i==1: - import os - else: - import os - os.path''') - - def test_redefinedTry(self): - """ - Test that importing a module twice in a try block - does raise a warning. - """ - self.flakes(''' - try: - import os - import os - except: - pass - os.path''', m.RedefinedWhileUnused) - - def test_redefinedTryExcept(self): - """ - Test that importing a module twice in a try - and except block does not raise a warning. - """ - self.flakes(''' - try: - import os - except: - import os - os.path''') - - def test_redefinedTryNested(self): - """ - Test that importing a module twice using a nested - try/except and if blocks does not issue a warning. - """ - self.flakes(''' - try: - if True: - if True: - import os - except: - import os - os.path''') - - def test_redefinedTryExceptMulti(self): - self.flakes(""" - try: - from aa import mixer - except AttributeError: - from bb import mixer - except RuntimeError: - from cc import mixer - except: - from dd import mixer - mixer(123) - """) - - def test_redefinedTryElse(self): - self.flakes(""" - try: - from aa import mixer - except ImportError: - pass - else: - from bb import mixer - mixer(123) - """, m.RedefinedWhileUnused) - - def test_redefinedTryExceptElse(self): - self.flakes(""" - try: - import funca - except ImportError: - from bb import funca - from bb import funcb - else: - from bbb import funcb - print(funca, funcb) - """) - - def test_redefinedTryExceptFinally(self): - self.flakes(""" - try: - from aa import a - except ImportError: - from bb import a - finally: - a = 42 - print(a) - """) - - def test_redefinedTryExceptElseFinally(self): - self.flakes(""" - try: - import b - except ImportError: - b = Ellipsis - from bb import a - else: - from aa import a - finally: - a = 42 - print(a, b) - """) - - def test_redefinedByFunction(self): - self.flakes(''' - import fu - def fu(): - pass - ''', m.RedefinedWhileUnused) - - def test_redefinedInNestedFunction(self): - """ - Test that shadowing a global name with a nested function definition - generates a warning. - """ - self.flakes(''' - import fu - def bar(): - def baz(): - def fu(): - pass - ''', m.RedefinedWhileUnused, m.UnusedImport) - - def test_redefinedInNestedFunctionTwice(self): - """ - Test that shadowing a global name with a nested function definition - generates a warning. - """ - self.flakes(''' - import fu - def bar(): - import fu - def baz(): - def fu(): - pass - ''', - m.RedefinedWhileUnused, m.RedefinedWhileUnused, - m.UnusedImport, m.UnusedImport) - - def test_redefinedButUsedLater(self): - """ - Test that a global import which is redefined locally, - but used later in another scope does not generate a warning. - """ - self.flakes(''' - import unittest, transport - - class GetTransportTestCase(unittest.TestCase): - def test_get_transport(self): - transport = 'transport' - self.assertIsNotNone(transport) - - class TestTransportMethodArgs(unittest.TestCase): - def test_send_defaults(self): - transport.Transport() - ''') - - def test_redefinedByClass(self): - self.flakes(''' - import fu - class fu: - pass - ''', m.RedefinedWhileUnused) - - def test_redefinedBySubclass(self): - """ - If an imported name is redefined by a class statement which also uses - that name in the bases list, no warning is emitted. - """ - self.flakes(''' - from fu import bar - class bar(bar): - pass - ''') - - def test_redefinedInClass(self): - """ - Test that shadowing a global with a class attribute does not produce a - warning. - """ - self.flakes(''' - import fu - class bar: - fu = 1 - print(fu) - ''') - - def test_importInClass(self): - """ - Test that import within class is a locally scoped attribute. - """ - self.flakes(''' - class bar: - import fu - ''') - - self.flakes(''' - class bar: - import fu - - fu - ''', m.UndefinedName) - - def test_usedInFunction(self): - self.flakes(''' - import fu - def fun(): - print(fu) - ''') - - def test_shadowedByParameter(self): - self.flakes(''' - import fu - def fun(fu): - print(fu) - ''', m.UnusedImport, m.RedefinedWhileUnused) - - self.flakes(''' - import fu - def fun(fu): - print(fu) - print(fu) - ''') - - def test_newAssignment(self): - self.flakes('fu = None') - - def test_usedInGetattr(self): - self.flakes('import fu; fu.bar.baz') - self.flakes('import fu; "bar".fu.baz', m.UnusedImport) - - def test_usedInSlice(self): - self.flakes('import fu; print(fu.bar[1:])') - - def test_usedInIfBody(self): - self.flakes(''' - import fu - if True: print(fu) - ''') - - def test_usedInIfConditional(self): - self.flakes(''' - import fu - if fu: pass - ''') - - def test_usedInElifConditional(self): - self.flakes(''' - import fu - if False: pass - elif fu: pass - ''') - - def test_usedInElse(self): - self.flakes(''' - import fu - if False: pass - else: print(fu) - ''') - - def test_usedInCall(self): - self.flakes('import fu; fu.bar()') - - def test_usedInClass(self): - self.flakes(''' - import fu - class bar: - bar = fu - ''') - - def test_usedInClassBase(self): - self.flakes(''' - import fu - class bar(object, fu.baz): - pass - ''') - - def test_notUsedInNestedScope(self): - self.flakes(''' - import fu - def bleh(): - pass - print(fu) - ''') - - def test_usedInFor(self): - self.flakes(''' - import fu - for bar in range(9): - print(fu) - ''') - - def test_usedInForElse(self): - self.flakes(''' - import fu - for bar in range(10): - pass - else: - print(fu) - ''') - - def test_redefinedByFor(self): - self.flakes(''' - import fu - for fu in range(2): - pass - ''', m.ImportShadowedByLoopVar) - - def test_shadowedByFor(self): - """ - Test that shadowing a global name with a for loop variable generates a - warning. - """ - self.flakes(''' - import fu - fu.bar() - for fu in (): - pass - ''', m.ImportShadowedByLoopVar) - - def test_shadowedByForDeep(self): - """ - Test that shadowing a global name with a for loop variable nested in a - tuple unpack generates a warning. - """ - self.flakes(''' - import fu - fu.bar() - for (x, y, z, (a, b, c, (fu,))) in (): - pass - ''', m.ImportShadowedByLoopVar) - # Same with a list instead of a tuple - self.flakes(''' - import fu - fu.bar() - for [x, y, z, (a, b, c, (fu,))] in (): - pass - ''', m.ImportShadowedByLoopVar) - - def test_usedInReturn(self): - self.flakes(''' - import fu - def fun(): - return fu - ''') - - def test_usedInOperators(self): - self.flakes('import fu; 3 + fu.bar') - self.flakes('import fu; 3 % fu.bar') - self.flakes('import fu; 3 - fu.bar') - self.flakes('import fu; 3 * fu.bar') - self.flakes('import fu; 3 ** fu.bar') - self.flakes('import fu; 3 / fu.bar') - self.flakes('import fu; 3 // fu.bar') - self.flakes('import fu; -fu.bar') - self.flakes('import fu; ~fu.bar') - self.flakes('import fu; 1 == fu.bar') - self.flakes('import fu; 1 | fu.bar') - self.flakes('import fu; 1 & fu.bar') - self.flakes('import fu; 1 ^ fu.bar') - self.flakes('import fu; 1 >> fu.bar') - self.flakes('import fu; 1 << fu.bar') - - def test_usedInAssert(self): - self.flakes('import fu; assert fu.bar') - - def test_usedInSubscript(self): - self.flakes('import fu; fu.bar[1]') - - def test_usedInLogic(self): - self.flakes('import fu; fu and False') - self.flakes('import fu; fu or False') - self.flakes('import fu; not fu.bar') - - def test_usedInList(self): - self.flakes('import fu; [fu]') - - def test_usedInTuple(self): - self.flakes('import fu; (fu,)') - - def test_usedInTry(self): - self.flakes(''' - import fu - try: fu - except: pass - ''') - - def test_usedInExcept(self): - self.flakes(''' - import fu - try: fu - except: pass - ''') - - def test_redefinedByExcept(self): - as_exc = ', ' if version_info < (2, 6) else ' as ' - self.flakes(''' - import fu - try: pass - except Exception%sfu: pass - ''' % as_exc, m.RedefinedWhileUnused) - - def test_usedInRaise(self): - self.flakes(''' - import fu - raise fu.bar - ''') - - def test_usedInYield(self): - self.flakes(''' - import fu - def gen(): - yield fu - ''') - - def test_usedInDict(self): - self.flakes('import fu; {fu:None}') - self.flakes('import fu; {1:fu}') - - def test_usedInParameterDefault(self): - self.flakes(''' - import fu - def f(bar=fu): - pass - ''') - - def test_usedInAttributeAssign(self): - self.flakes('import fu; fu.bar = 1') - - def test_usedInKeywordArg(self): - self.flakes('import fu; fu.bar(stuff=fu)') - - def test_usedInAssignment(self): - self.flakes('import fu; bar=fu') - self.flakes('import fu; n=0; n+=fu') - - def test_usedInListComp(self): - self.flakes('import fu; [fu for _ in range(1)]') - self.flakes('import fu; [1 for _ in range(1) if fu]') - - @skipIf(version_info >= (3,), - 'in Python 3 list comprehensions execute in a separate scope') - def test_redefinedByListComp(self): - self.flakes('import fu; [1 for fu in range(1)]', - m.RedefinedInListComp) - - def test_usedInTryFinally(self): - self.flakes(''' - import fu - try: pass - finally: fu - ''') - - self.flakes(''' - import fu - try: fu - finally: pass - ''') - - def test_usedInWhile(self): - self.flakes(''' - import fu - while 0: - fu - ''') - - self.flakes(''' - import fu - while fu: pass - ''') - - def test_usedInGlobal(self): - """ - A 'global' statement shadowing an unused import should not prevent it - from being reported. - """ - self.flakes(''' - import fu - def f(): global fu - ''', m.UnusedImport) - - def test_usedAndGlobal(self): - """ - A 'global' statement shadowing a used import should not cause it to be - reported as unused. - """ - self.flakes(''' - import foo - def f(): global foo - def g(): foo.is_used() - ''') - - def test_assignedToGlobal(self): - """ - Binding an import to a declared global should not cause it to be - reported as unused. - """ - self.flakes(''' - def f(): global foo; import foo - def g(): foo.is_used() - ''') - - @skipIf(version_info >= (3,), 'deprecated syntax') - def test_usedInBackquote(self): - self.flakes('import fu; `fu`') - - def test_usedInExec(self): - if version_info < (3,): - exec_stmt = 'exec "print 1" in fu.bar' - else: - exec_stmt = 'exec("print(1)", fu.bar)' - self.flakes('import fu; %s' % exec_stmt) - - def test_usedInLambda(self): - self.flakes('import fu; lambda: fu') - - def test_shadowedByLambda(self): - self.flakes('import fu; lambda fu: fu', - m.UnusedImport, m.RedefinedWhileUnused) - self.flakes('import fu; lambda fu: fu\nfu()') - - def test_usedInSliceObj(self): - self.flakes('import fu; "meow"[::fu]') - - def test_unusedInNestedScope(self): - self.flakes(''' - def bar(): - import fu - fu - ''', m.UnusedImport, m.UndefinedName) - - def test_methodsDontUseClassScope(self): - self.flakes(''' - class bar: - import fu - def fun(self): - fu - ''', m.UndefinedName) - - def test_nestedFunctionsNestScope(self): - self.flakes(''' - def a(): - def b(): - fu - import fu - ''') - - def test_nestedClassAndFunctionScope(self): - self.flakes(''' - def a(): - import fu - class b: - def c(self): - print(fu) - ''') - - def test_importStar(self): - """Use of import * at module level is reported.""" - self.flakes('from fu import *', m.ImportStarUsed, m.UnusedImport) - self.flakes(''' - try: - from fu import * - except: - pass - ''', m.ImportStarUsed, m.UnusedImport) - - checker = self.flakes('from fu import *', - m.ImportStarUsed, m.UnusedImport) - - error = checker.messages[0] - assert error.message.startswith("'from %s import *' used; unable ") - assert error.message_args == ('fu', ) - - error = checker.messages[1] - assert error.message == '%r imported but unused' - assert error.message_args == ('fu.*', ) - - def test_importStar_relative(self): - """Use of import * from a relative import is reported.""" - self.flakes('from .fu import *', m.ImportStarUsed, m.UnusedImport) - self.flakes(''' - try: - from .fu import * - except: - pass - ''', m.ImportStarUsed, m.UnusedImport) - - checker = self.flakes('from .fu import *', - m.ImportStarUsed, m.UnusedImport) - - error = checker.messages[0] - assert error.message.startswith("'from %s import *' used; unable ") - assert error.message_args == ('.fu', ) - - error = checker.messages[1] - assert error.message == '%r imported but unused' - assert error.message_args == ('.fu.*', ) - - checker = self.flakes('from .. import *', - m.ImportStarUsed, m.UnusedImport) - - error = checker.messages[0] - assert error.message.startswith("'from %s import *' used; unable ") - assert error.message_args == ('..', ) - - error = checker.messages[1] - assert error.message == '%r imported but unused' - assert error.message_args == ('from .. import *', ) - - @skipIf(version_info < (3,), - 'import * below module level is a warning on Python 2') - def test_localImportStar(self): - """import * is only allowed at module level.""" - self.flakes(''' - def a(): - from fu import * - ''', m.ImportStarNotPermitted) - self.flakes(''' - class a: - from fu import * - ''', m.ImportStarNotPermitted) - - checker = self.flakes(''' - class a: - from .. import * - ''', m.ImportStarNotPermitted) - error = checker.messages[0] - assert error.message == "'from %s import *' only allowed at module level" - assert error.message_args == ('..', ) - - @skipIf(version_info > (3,), - 'import * below module level is an error on Python 3') - def test_importStarNested(self): - """All star imports are marked as used by an undefined variable.""" - self.flakes(''' - from fu import * - def f(): - from bar import * - x - ''', m.ImportStarUsed, m.ImportStarUsed, m.ImportStarUsage) - - def test_packageImport(self): - """ - If a dotted name is imported and used, no warning is reported. - """ - self.flakes(''' - import fu.bar - fu.bar - ''') - - def test_unusedPackageImport(self): - """ - If a dotted name is imported and not used, an unused import warning is - reported. - """ - self.flakes('import fu.bar', m.UnusedImport) - - def test_duplicateSubmoduleImport(self): - """ - If a submodule of a package is imported twice, an unused import warning - and a redefined while unused warning are reported. - """ - self.flakes(''' - import fu.bar, fu.bar - fu.bar - ''', m.RedefinedWhileUnused) - self.flakes(''' - import fu.bar - import fu.bar - fu.bar - ''', m.RedefinedWhileUnused) - - def test_differentSubmoduleImport(self): - """ - If two different submodules of a package are imported, no duplicate - import warning is reported for the package. - """ - self.flakes(''' - import fu.bar, fu.baz - fu.bar, fu.baz - ''') - self.flakes(''' - import fu.bar - import fu.baz - fu.bar, fu.baz - ''') - - def test_used_package_with_submodule_import(self): - """ - Usage of package marks submodule imports as used. - """ - self.flakes(''' - import fu - import fu.bar - fu.x - ''') - - self.flakes(''' - import fu.bar - import fu - fu.x - ''') - - def test_unused_package_with_submodule_import(self): - """ - When a package and its submodule are imported, only report once. - """ - checker = self.flakes(''' - import fu - import fu.bar - ''', m.UnusedImport) - error = checker.messages[0] - assert error.message == '%r imported but unused' - assert error.message_args == ('fu.bar', ) - assert error.lineno == 5 if self.withDoctest else 3 - - def test_assignRHSFirst(self): - self.flakes('import fu; fu = fu') - self.flakes('import fu; fu, bar = fu') - self.flakes('import fu; [fu, bar] = fu') - self.flakes('import fu; fu += fu') - - def test_tryingMultipleImports(self): - self.flakes(''' - try: - import fu - except ImportError: - import bar as fu - fu - ''') - - def test_nonGlobalDoesNotRedefine(self): - self.flakes(''' - import fu - def a(): - fu = 3 - return fu - fu - ''') - - def test_functionsRunLater(self): - self.flakes(''' - def a(): - fu - import fu - ''') - - def test_functionNamesAreBoundNow(self): - self.flakes(''' - import fu - def fu(): - fu - fu - ''', m.RedefinedWhileUnused) - - def test_ignoreNonImportRedefinitions(self): - self.flakes('a = 1; a = 2') - - @skip("todo") - def test_importingForImportError(self): - self.flakes(''' - try: - import fu - except ImportError: - pass - ''') - - def test_importedInClass(self): - """Imports in class scope can be used through self.""" - self.flakes(''' - class c: - import i - def __init__(self): - self.i - ''') - - def test_importUsedInMethodDefinition(self): - """ - Method named 'foo' with default args referring to module named 'foo'. - """ - self.flakes(''' - import foo - - class Thing(object): - def foo(self, parser=foo.parse_foo): - pass - ''') - - def test_futureImport(self): - """__future__ is special.""" - self.flakes('from __future__ import division') - self.flakes(''' - "docstring is allowed before future import" - from __future__ import division - ''') - - def test_futureImportFirst(self): - """ - __future__ imports must come before anything else. - """ - self.flakes(''' - x = 5 - from __future__ import division - ''', m.LateFutureImport) - self.flakes(''' - from foo import bar - from __future__ import division - bar - ''', m.LateFutureImport) - - def test_futureImportUsed(self): - """__future__ is special, but names are injected in the namespace.""" - self.flakes(''' - from __future__ import division - from __future__ import print_function - - assert print_function is not division - ''') - - def test_futureImportUndefined(self): - """Importing undefined names from __future__ fails.""" - self.flakes(''' - from __future__ import print_statement - ''', m.FutureFeatureNotDefined) - - def test_futureImportStar(self): - """Importing '*' from __future__ fails.""" - self.flakes(''' - from __future__ import * - ''', m.FutureFeatureNotDefined) - - -class TestSpecialAll(TestCase): - """ - Tests for suppression of unused import warnings by C{__all__}. - """ - def test_ignoredInFunction(self): - """ - An C{__all__} definition does not suppress unused import warnings in a - function scope. - """ - self.flakes(''' - def foo(): - import bar - __all__ = ["bar"] - ''', m.UnusedImport, m.UnusedVariable) - - def test_ignoredInClass(self): - """ - An C{__all__} definition in a class does not suppress unused import warnings. - """ - self.flakes(''' - import bar - class foo: - __all__ = ["bar"] - ''', m.UnusedImport) - - def test_warningSuppressed(self): - """ - If a name is imported and unused but is named in C{__all__}, no warning - is reported. - """ - self.flakes(''' - import foo - __all__ = ["foo"] - ''') - self.flakes(''' - import foo - __all__ = ("foo",) - ''') - - def test_augmentedAssignment(self): - """ - The C{__all__} variable is defined incrementally. - """ - self.flakes(''' - import a - import c - __all__ = ['a'] - __all__ += ['b'] - if 1 < 3: - __all__ += ['c', 'd'] - ''', m.UndefinedExport, m.UndefinedExport) - - def test_unrecognizable(self): - """ - If C{__all__} is defined in a way that can't be recognized statically, - it is ignored. - """ - self.flakes(''' - import foo - __all__ = ["f" + "oo"] - ''', m.UnusedImport) - self.flakes(''' - import foo - __all__ = [] + ["foo"] - ''', m.UnusedImport) - - def test_unboundExported(self): - """ - If C{__all__} includes a name which is not bound, a warning is emitted. - """ - self.flakes(''' - __all__ = ["foo"] - ''', m.UndefinedExport) - - # Skip this in __init__.py though, since the rules there are a little - # different. - for filename in ["foo/__init__.py", "__init__.py"]: - self.flakes(''' - __all__ = ["foo"] - ''', filename=filename) - - def test_importStarExported(self): - """ - Do not report undefined if import * is used - """ - self.flakes(''' - from foolib import * - __all__ = ["foo"] - ''', m.ImportStarUsed) - - def test_importStarNotExported(self): - """Report unused import when not needed to satisfy __all__.""" - self.flakes(''' - from foolib import * - a = 1 - __all__ = ['a'] - ''', m.ImportStarUsed, m.UnusedImport) - - def test_usedInGenExp(self): - """ - Using a global in a generator expression results in no warnings. - """ - self.flakes('import fu; (fu for _ in range(1))') - self.flakes('import fu; (1 for _ in range(1) if fu)') - - def test_redefinedByGenExp(self): - """ - Re-using a global name as the loop variable for a generator - expression results in a redefinition warning. - """ - self.flakes('import fu; (1 for fu in range(1))', - m.RedefinedWhileUnused, m.UnusedImport) - - def test_usedAsDecorator(self): - """ - Using a global name in a decorator statement results in no warnings, - but using an undefined name in a decorator statement results in an - undefined name warning. - """ - self.flakes(''' - from interior import decorate - @decorate - def f(): - return "hello" - ''') - - self.flakes(''' - from interior import decorate - @decorate('value') - def f(): - return "hello" - ''') - - self.flakes(''' - @decorate - def f(): - return "hello" - ''', m.UndefinedName) - - -class Python26Tests(TestCase): - """ - Tests for checking of syntax which is valid in Python 2.6 and newer. - """ - - @skipIf(version_info < (2, 6), "Python >= 2.6 only") - def test_usedAsClassDecorator(self): - """ - Using an imported name as a class decorator results in no warnings, - but using an undefined name as a class decorator results in an - undefined name warning. - """ - self.flakes(''' - from interior import decorate - @decorate - class foo: - pass - ''') - - self.flakes(''' - from interior import decorate - @decorate("foo") - class bar: - pass - ''') - - self.flakes(''' - @decorate - class foo: - pass - ''', m.UndefinedName) diff --git a/pymode/libs/pyflakes/test/test_other.py b/pymode/libs/pyflakes/test/test_other.py deleted file mode 100644 index 6f020015..00000000 --- a/pymode/libs/pyflakes/test/test_other.py +++ /dev/null @@ -1,1871 +0,0 @@ -""" -Tests for various Pyflakes behavior. -""" - -from sys import version_info - -from pyflakes import messages as m -from pyflakes.test.harness import TestCase, skip, skipIf - - -class Test(TestCase): - - def test_duplicateArgs(self): - self.flakes('def fu(bar, bar): pass', m.DuplicateArgument) - - def test_localReferencedBeforeAssignment(self): - self.flakes(''' - a = 1 - def f(): - a; a=1 - f() - ''', m.UndefinedLocal, m.UnusedVariable) - - @skipIf(version_info >= (3,), - 'in Python 3 list comprehensions execute in a separate scope') - def test_redefinedInListComp(self): - """ - Test that shadowing a variable in a list comprehension raises - a warning. - """ - self.flakes(''' - a = 1 - [1 for a, b in [(1, 2)]] - ''', m.RedefinedInListComp) - self.flakes(''' - class A: - a = 1 - [1 for a, b in [(1, 2)]] - ''', m.RedefinedInListComp) - self.flakes(''' - def f(): - a = 1 - [1 for a, b in [(1, 2)]] - ''', m.RedefinedInListComp) - self.flakes(''' - [1 for a, b in [(1, 2)]] - [1 for a, b in [(1, 2)]] - ''') - self.flakes(''' - for a, b in [(1, 2)]: - pass - [1 for a, b in [(1, 2)]] - ''') - - def test_redefinedInGenerator(self): - """ - Test that reusing a variable in a generator does not raise - a warning. - """ - self.flakes(''' - a = 1 - (1 for a, b in [(1, 2)]) - ''') - self.flakes(''' - class A: - a = 1 - list(1 for a, b in [(1, 2)]) - ''') - self.flakes(''' - def f(): - a = 1 - (1 for a, b in [(1, 2)]) - ''', m.UnusedVariable) - self.flakes(''' - (1 for a, b in [(1, 2)]) - (1 for a, b in [(1, 2)]) - ''') - self.flakes(''' - for a, b in [(1, 2)]: - pass - (1 for a, b in [(1, 2)]) - ''') - - @skipIf(version_info < (2, 7), "Python >= 2.7 only") - def test_redefinedInSetComprehension(self): - """ - Test that reusing a variable in a set comprehension does not raise - a warning. - """ - self.flakes(''' - a = 1 - {1 for a, b in [(1, 2)]} - ''') - self.flakes(''' - class A: - a = 1 - {1 for a, b in [(1, 2)]} - ''') - self.flakes(''' - def f(): - a = 1 - {1 for a, b in [(1, 2)]} - ''', m.UnusedVariable) - self.flakes(''' - {1 for a, b in [(1, 2)]} - {1 for a, b in [(1, 2)]} - ''') - self.flakes(''' - for a, b in [(1, 2)]: - pass - {1 for a, b in [(1, 2)]} - ''') - - @skipIf(version_info < (2, 7), "Python >= 2.7 only") - def test_redefinedInDictComprehension(self): - """ - Test that reusing a variable in a dict comprehension does not raise - a warning. - """ - self.flakes(''' - a = 1 - {1: 42 for a, b in [(1, 2)]} - ''') - self.flakes(''' - class A: - a = 1 - {1: 42 for a, b in [(1, 2)]} - ''') - self.flakes(''' - def f(): - a = 1 - {1: 42 for a, b in [(1, 2)]} - ''', m.UnusedVariable) - self.flakes(''' - {1: 42 for a, b in [(1, 2)]} - {1: 42 for a, b in [(1, 2)]} - ''') - self.flakes(''' - for a, b in [(1, 2)]: - pass - {1: 42 for a, b in [(1, 2)]} - ''') - - def test_redefinedFunction(self): - """ - Test that shadowing a function definition with another one raises a - warning. - """ - self.flakes(''' - def a(): pass - def a(): pass - ''', m.RedefinedWhileUnused) - - def test_redefinedClassFunction(self): - """ - Test that shadowing a function definition in a class suite with another - one raises a warning. - """ - self.flakes(''' - class A: - def a(): pass - def a(): pass - ''', m.RedefinedWhileUnused) - - def test_redefinedIfElseFunction(self): - """ - Test that shadowing a function definition twice in an if - and else block does not raise a warning. - """ - self.flakes(''' - if True: - def a(): pass - else: - def a(): pass - ''') - - def test_redefinedIfFunction(self): - """ - Test that shadowing a function definition within an if block - raises a warning. - """ - self.flakes(''' - if True: - def a(): pass - def a(): pass - ''', m.RedefinedWhileUnused) - - def test_redefinedTryExceptFunction(self): - """ - Test that shadowing a function definition twice in try - and except block does not raise a warning. - """ - self.flakes(''' - try: - def a(): pass - except: - def a(): pass - ''') - - def test_redefinedTryFunction(self): - """ - Test that shadowing a function definition within a try block - raises a warning. - """ - self.flakes(''' - try: - def a(): pass - def a(): pass - except: - pass - ''', m.RedefinedWhileUnused) - - def test_redefinedIfElseInListComp(self): - """ - Test that shadowing a variable in a list comprehension in - an if and else block does not raise a warning. - """ - self.flakes(''' - if False: - a = 1 - else: - [a for a in '12'] - ''') - - @skipIf(version_info >= (3,), - 'in Python 3 list comprehensions execute in a separate scope') - def test_redefinedElseInListComp(self): - """ - Test that shadowing a variable in a list comprehension in - an else (or if) block raises a warning. - """ - self.flakes(''' - if False: - pass - else: - a = 1 - [a for a in '12'] - ''', m.RedefinedInListComp) - - def test_functionDecorator(self): - """ - Test that shadowing a function definition with a decorated version of - that function does not raise a warning. - """ - self.flakes(''' - from somewhere import somedecorator - - def a(): pass - a = somedecorator(a) - ''') - - def test_classFunctionDecorator(self): - """ - Test that shadowing a function definition in a class suite with a - decorated version of that function does not raise a warning. - """ - self.flakes(''' - class A: - def a(): pass - a = classmethod(a) - ''') - - @skipIf(version_info < (2, 6), "Python >= 2.6 only") - def test_modernProperty(self): - self.flakes(""" - class A: - @property - def t(self): - pass - @t.setter - def t(self, value): - pass - @t.deleter - def t(self): - pass - """) - - def test_unaryPlus(self): - """Don't die on unary +.""" - self.flakes('+1') - - def test_undefinedBaseClass(self): - """ - If a name in the base list of a class definition is undefined, a - warning is emitted. - """ - self.flakes(''' - class foo(foo): - pass - ''', m.UndefinedName) - - def test_classNameUndefinedInClassBody(self): - """ - If a class name is used in the body of that class's definition and - the name is not already defined, a warning is emitted. - """ - self.flakes(''' - class foo: - foo - ''', m.UndefinedName) - - def test_classNameDefinedPreviously(self): - """ - If a class name is used in the body of that class's definition and - the name was previously defined in some other way, no warning is - emitted. - """ - self.flakes(''' - foo = None - class foo: - foo - ''') - - def test_classRedefinition(self): - """ - If a class is defined twice in the same module, a warning is emitted. - """ - self.flakes(''' - class Foo: - pass - class Foo: - pass - ''', m.RedefinedWhileUnused) - - def test_functionRedefinedAsClass(self): - """ - If a function is redefined as a class, a warning is emitted. - """ - self.flakes(''' - def Foo(): - pass - class Foo: - pass - ''', m.RedefinedWhileUnused) - - def test_classRedefinedAsFunction(self): - """ - If a class is redefined as a function, a warning is emitted. - """ - self.flakes(''' - class Foo: - pass - def Foo(): - pass - ''', m.RedefinedWhileUnused) - - def test_classWithReturn(self): - """ - If a return is used inside a class, a warning is emitted. - """ - self.flakes(''' - class Foo(object): - return - ''', m.ReturnOutsideFunction) - - def test_moduleWithReturn(self): - """ - If a return is used at the module level, a warning is emitted. - """ - self.flakes(''' - return - ''', m.ReturnOutsideFunction) - - def test_classWithYield(self): - """ - If a yield is used inside a class, a warning is emitted. - """ - self.flakes(''' - class Foo(object): - yield - ''', m.YieldOutsideFunction) - - def test_moduleWithYield(self): - """ - If a yield is used at the module level, a warning is emitted. - """ - self.flakes(''' - yield - ''', m.YieldOutsideFunction) - - @skipIf(version_info < (3, 3), "Python >= 3.3 only") - def test_classWithYieldFrom(self): - """ - If a yield from is used inside a class, a warning is emitted. - """ - self.flakes(''' - class Foo(object): - yield from range(10) - ''', m.YieldOutsideFunction) - - @skipIf(version_info < (3, 3), "Python >= 3.3 only") - def test_moduleWithYieldFrom(self): - """ - If a yield from is used at the module level, a warning is emitted. - """ - self.flakes(''' - yield from range(10) - ''', m.YieldOutsideFunction) - - def test_continueOutsideLoop(self): - self.flakes(''' - continue - ''', m.ContinueOutsideLoop) - - self.flakes(''' - def f(): - continue - ''', m.ContinueOutsideLoop) - - self.flakes(''' - while True: - pass - else: - continue - ''', m.ContinueOutsideLoop) - - self.flakes(''' - while True: - pass - else: - if 1: - if 2: - continue - ''', m.ContinueOutsideLoop) - - self.flakes(''' - while True: - def f(): - continue - ''', m.ContinueOutsideLoop) - - self.flakes(''' - while True: - class A: - continue - ''', m.ContinueOutsideLoop) - - def test_continueInsideLoop(self): - self.flakes(''' - while True: - continue - ''') - - self.flakes(''' - for i in range(10): - continue - ''') - - self.flakes(''' - while True: - if 1: - continue - ''') - - self.flakes(''' - for i in range(10): - if 1: - continue - ''') - - self.flakes(''' - while True: - while True: - pass - else: - continue - else: - pass - ''') - - self.flakes(''' - while True: - try: - pass - finally: - while True: - continue - ''') - - def test_continueInFinally(self): - # 'continue' inside 'finally' is a special syntax error - self.flakes(''' - while True: - try: - pass - finally: - continue - ''', m.ContinueInFinally) - - self.flakes(''' - while True: - try: - pass - finally: - if 1: - if 2: - continue - ''', m.ContinueInFinally) - - # Even when not in a loop, this is the error Python gives - self.flakes(''' - try: - pass - finally: - continue - ''', m.ContinueInFinally) - - def test_breakOutsideLoop(self): - self.flakes(''' - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - def f(): - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - while True: - pass - else: - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - while True: - pass - else: - if 1: - if 2: - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - while True: - def f(): - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - while True: - class A: - break - ''', m.BreakOutsideLoop) - - self.flakes(''' - try: - pass - finally: - break - ''', m.BreakOutsideLoop) - - def test_breakInsideLoop(self): - self.flakes(''' - while True: - break - ''') - - self.flakes(''' - for i in range(10): - break - ''') - - self.flakes(''' - while True: - if 1: - break - ''') - - self.flakes(''' - for i in range(10): - if 1: - break - ''') - - self.flakes(''' - while True: - while True: - pass - else: - break - else: - pass - ''') - - self.flakes(''' - while True: - try: - pass - finally: - while True: - break - ''') - - self.flakes(''' - while True: - try: - pass - finally: - break - ''') - - self.flakes(''' - while True: - try: - pass - finally: - if 1: - if 2: - break - ''') - - def test_defaultExceptLast(self): - """ - A default except block should be last. - - YES: - - try: - ... - except Exception: - ... - except: - ... - - NO: - - try: - ... - except: - ... - except Exception: - ... - """ - self.flakes(''' - try: - pass - except ValueError: - pass - ''') - - self.flakes(''' - try: - pass - except ValueError: - pass - except: - pass - ''') - - self.flakes(''' - try: - pass - except: - pass - ''') - - self.flakes(''' - try: - pass - except ValueError: - pass - else: - pass - ''') - - self.flakes(''' - try: - pass - except: - pass - else: - pass - ''') - - self.flakes(''' - try: - pass - except ValueError: - pass - except: - pass - else: - pass - ''') - - def test_defaultExceptNotLast(self): - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - except ValueError: - pass - ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - else: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except: - pass - else: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - else: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - except ValueError: - pass - else: - pass - ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - except ValueError: - pass - finally: - pass - ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - else: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except: - pass - else: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - else: - pass - finally: - pass - ''', m.DefaultExceptNotLast) - - self.flakes(''' - try: - pass - except: - pass - except ValueError: - pass - except: - pass - except ValueError: - pass - else: - pass - finally: - pass - ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast) - - @skipIf(version_info < (3,), "Python 3 only") - def test_starredAssignmentNoError(self): - """ - Python 3 extended iterable unpacking - """ - self.flakes(''' - a, *b = range(10) - ''') - - self.flakes(''' - *a, b = range(10) - ''') - - self.flakes(''' - a, *b, c = range(10) - ''') - - self.flakes(''' - (a, *b) = range(10) - ''') - - self.flakes(''' - (*a, b) = range(10) - ''') - - self.flakes(''' - (a, *b, c) = range(10) - ''') - - self.flakes(''' - [a, *b] = range(10) - ''') - - self.flakes(''' - [*a, b] = range(10) - ''') - - self.flakes(''' - [a, *b, c] = range(10) - ''') - - # Taken from test_unpack_ex.py in the cPython source - s = ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \ - ", *rest = range(1<<8)" - self.flakes(s) - - s = "(" + ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \ - ", *rest) = range(1<<8)" - self.flakes(s) - - s = "[" + ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \ - ", *rest] = range(1<<8)" - self.flakes(s) - - @skipIf(version_info < (3, ), "Python 3 only") - def test_starredAssignmentErrors(self): - """ - SyntaxErrors (not encoded in the ast) surrounding Python 3 extended - iterable unpacking - """ - # Taken from test_unpack_ex.py in the cPython source - s = ", ".join("a%d" % i for i in range(1 << 8)) + \ - ", *rest = range(1<<8 + 1)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - s = "(" + ", ".join("a%d" % i for i in range(1 << 8)) + \ - ", *rest) = range(1<<8 + 1)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - s = "[" + ", ".join("a%d" % i for i in range(1 << 8)) + \ - ", *rest] = range(1<<8 + 1)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - s = ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \ - ", *rest = range(1<<8 + 2)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - s = "(" + ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \ - ", *rest) = range(1<<8 + 2)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - s = "[" + ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \ - ", *rest] = range(1<<8 + 2)" - self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - # No way we can actually test this! - # s = "*rest, " + ", ".join("a%d" % i for i in range(1<<24)) + \ - # ", *rest = range(1<<24 + 1)" - # self.flakes(s, m.TooManyExpressionsInStarredAssignment) - - self.flakes(''' - a, *b, *c = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - a, *b, c, *d = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - *a, *b, *c = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - (a, *b, *c) = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - (a, *b, c, *d) = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - (*a, *b, *c) = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - [a, *b, *c] = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - [a, *b, c, *d] = range(10) - ''', m.TwoStarredExpressions) - - self.flakes(''' - [*a, *b, *c] = range(10) - ''', m.TwoStarredExpressions) - - @skip("todo: Too hard to make this warn but other cases stay silent") - def test_doubleAssignment(self): - """ - If a variable is re-assigned to without being used, no warning is - emitted. - """ - self.flakes(''' - x = 10 - x = 20 - ''', m.RedefinedWhileUnused) - - def test_doubleAssignmentConditionally(self): - """ - If a variable is re-assigned within a conditional, no warning is - emitted. - """ - self.flakes(''' - x = 10 - if True: - x = 20 - ''') - - def test_doubleAssignmentWithUse(self): - """ - If a variable is re-assigned to after being used, no warning is - emitted. - """ - self.flakes(''' - x = 10 - y = x * 2 - x = 20 - ''') - - def test_comparison(self): - """ - If a defined name is used on either side of any of the six comparison - operators, no warning is emitted. - """ - self.flakes(''' - x = 10 - y = 20 - x < y - x <= y - x == y - x != y - x >= y - x > y - ''') - - def test_identity(self): - """ - If a defined name is used on either side of an identity test, no - warning is emitted. - """ - self.flakes(''' - x = 10 - y = 20 - x is y - x is not y - ''') - - def test_containment(self): - """ - If a defined name is used on either side of a containment test, no - warning is emitted. - """ - self.flakes(''' - x = 10 - y = 20 - x in y - x not in y - ''') - - def test_loopControl(self): - """ - break and continue statements are supported. - """ - self.flakes(''' - for x in [1, 2]: - break - ''') - self.flakes(''' - for x in [1, 2]: - continue - ''') - - def test_ellipsis(self): - """ - Ellipsis in a slice is supported. - """ - self.flakes(''' - [1, 2][...] - ''') - - def test_extendedSlice(self): - """ - Extended slices are supported. - """ - self.flakes(''' - x = 3 - [1, 2][x,:] - ''') - - def test_varAugmentedAssignment(self): - """ - Augmented assignment of a variable is supported. - We don't care about var refs. - """ - self.flakes(''' - foo = 0 - foo += 1 - ''') - - def test_attrAugmentedAssignment(self): - """ - Augmented assignment of attributes is supported. - We don't care about attr refs. - """ - self.flakes(''' - foo = None - foo.bar += foo.baz - ''') - - def test_globalDeclaredInDifferentScope(self): - """ - A 'global' can be declared in one scope and reused in another. - """ - self.flakes(''' - def f(): global foo - def g(): foo = 'anything'; foo.is_used() - ''') - - -class TestUnusedAssignment(TestCase): - """ - Tests for warning about unused assignments. - """ - - def test_unusedVariable(self): - """ - Warn when a variable in a function is assigned a value that's never - used. - """ - self.flakes(''' - def a(): - b = 1 - ''', m.UnusedVariable) - - def test_unusedVariableAsLocals(self): - """ - Using locals() it is perfectly valid to have unused variables - """ - self.flakes(''' - def a(): - b = 1 - return locals() - ''') - - def test_unusedVariableNoLocals(self): - """ - Using locals() in wrong scope should not matter - """ - self.flakes(''' - def a(): - locals() - def a(): - b = 1 - return - ''', m.UnusedVariable) - - @skip("todo: Difficult because it doesn't apply in the context of a loop") - def test_unusedReassignedVariable(self): - """ - Shadowing a used variable can still raise an UnusedVariable warning. - """ - self.flakes(''' - def a(): - b = 1 - b.foo() - b = 2 - ''', m.UnusedVariable) - - def test_variableUsedInLoop(self): - """ - Shadowing a used variable cannot raise an UnusedVariable warning in the - context of a loop. - """ - self.flakes(''' - def a(): - b = True - while b: - b = False - ''') - - def test_assignToGlobal(self): - """ - Assigning to a global and then not using that global is perfectly - acceptable. Do not mistake it for an unused local variable. - """ - self.flakes(''' - b = 0 - def a(): - global b - b = 1 - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_assignToNonlocal(self): - """ - Assigning to a nonlocal and then not using that binding is perfectly - acceptable. Do not mistake it for an unused local variable. - """ - self.flakes(''' - b = b'0' - def a(): - nonlocal b - b = b'1' - ''') - - def test_assignToMember(self): - """ - Assigning to a member of another object and then not using that member - variable is perfectly acceptable. Do not mistake it for an unused - local variable. - """ - # XXX: Adding this test didn't generate a failure. Maybe not - # necessary? - self.flakes(''' - class b: - pass - def a(): - b.foo = 1 - ''') - - def test_assignInForLoop(self): - """ - Don't warn when a variable in a for loop is assigned to but not used. - """ - self.flakes(''' - def f(): - for i in range(10): - pass - ''') - - def test_assignInListComprehension(self): - """ - Don't warn when a variable in a list comprehension is - assigned to but not used. - """ - self.flakes(''' - def f(): - [None for i in range(10)] - ''') - - def test_generatorExpression(self): - """ - Don't warn when a variable in a generator expression is - assigned to but not used. - """ - self.flakes(''' - def f(): - (None for i in range(10)) - ''') - - def test_assignmentInsideLoop(self): - """ - Don't warn when a variable assignment occurs lexically after its use. - """ - self.flakes(''' - def f(): - x = None - for i in range(10): - if i > 2: - return x - x = i * 2 - ''') - - def test_tupleUnpacking(self): - """ - Don't warn when a variable included in tuple unpacking is unused. It's - very common for variables in a tuple unpacking assignment to be unused - in good Python code, so warning will only create false positives. - """ - self.flakes(''' - def f(tup): - (x, y) = tup - ''') - self.flakes(''' - def f(): - (x, y) = 1, 2 - ''', m.UnusedVariable, m.UnusedVariable) - self.flakes(''' - def f(): - (x, y) = coords = 1, 2 - if x > 1: - print(coords) - ''') - self.flakes(''' - def f(): - (x, y) = coords = 1, 2 - ''', m.UnusedVariable) - self.flakes(''' - def f(): - coords = (x, y) = 1, 2 - ''', m.UnusedVariable) - - def test_listUnpacking(self): - """ - Don't warn when a variable included in list unpacking is unused. - """ - self.flakes(''' - def f(tup): - [x, y] = tup - ''') - self.flakes(''' - def f(): - [x, y] = [1, 2] - ''', m.UnusedVariable, m.UnusedVariable) - - def test_closedOver(self): - """ - Don't warn when the assignment is used in an inner function. - """ - self.flakes(''' - def barMaker(): - foo = 5 - def bar(): - return foo - return bar - ''') - - def test_doubleClosedOver(self): - """ - Don't warn when the assignment is used in an inner function, even if - that inner function itself is in an inner function. - """ - self.flakes(''' - def barMaker(): - foo = 5 - def bar(): - def baz(): - return foo - return bar - ''') - - def test_tracebackhideSpecialVariable(self): - """ - Do not warn about unused local variable __tracebackhide__, which is - a special variable for py.test. - """ - self.flakes(""" - def helper(): - __tracebackhide__ = True - """) - - def test_ifexp(self): - """ - Test C{foo if bar else baz} statements. - """ - self.flakes("a = 'moo' if True else 'oink'") - self.flakes("a = foo if True else 'oink'", m.UndefinedName) - self.flakes("a = 'moo' if True else bar", m.UndefinedName) - - def test_withStatementNoNames(self): - """ - No warnings are emitted for using inside or after a nameless C{with} - statement a name defined beforehand. - """ - self.flakes(''' - from __future__ import with_statement - bar = None - with open("foo"): - bar - bar - ''') - - def test_withStatementSingleName(self): - """ - No warnings are emitted for using a name defined by a C{with} statement - within the suite or afterwards. - """ - self.flakes(''' - from __future__ import with_statement - with open('foo') as bar: - bar - bar - ''') - - def test_withStatementAttributeName(self): - """ - No warnings are emitted for using an attribute as the target of a - C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - import foo - with open('foo') as foo.bar: - pass - ''') - - def test_withStatementSubscript(self): - """ - No warnings are emitted for using a subscript as the target of a - C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - import foo - with open('foo') as foo[0]: - pass - ''') - - def test_withStatementSubscriptUndefined(self): - """ - An undefined name warning is emitted if the subscript used as the - target of a C{with} statement is not defined. - """ - self.flakes(''' - from __future__ import with_statement - import foo - with open('foo') as foo[bar]: - pass - ''', m.UndefinedName) - - def test_withStatementTupleNames(self): - """ - No warnings are emitted for using any of the tuple of names defined by - a C{with} statement within the suite or afterwards. - """ - self.flakes(''' - from __future__ import with_statement - with open('foo') as (bar, baz): - bar, baz - bar, baz - ''') - - def test_withStatementListNames(self): - """ - No warnings are emitted for using any of the list of names defined by a - C{with} statement within the suite or afterwards. - """ - self.flakes(''' - from __future__ import with_statement - with open('foo') as [bar, baz]: - bar, baz - bar, baz - ''') - - def test_withStatementComplicatedTarget(self): - """ - If the target of a C{with} statement uses any or all of the valid forms - for that part of the grammar (See - U{http://docs.python.org/reference/compound_stmts.html#the-with-statement}), - the names involved are checked both for definedness and any bindings - created are respected in the suite of the statement and afterwards. - """ - self.flakes(''' - from __future__ import with_statement - c = d = e = g = h = i = None - with open('foo') as [(a, b), c[d], e.f, g[h:i]]: - a, b, c, d, e, g, h, i - a, b, c, d, e, g, h, i - ''') - - def test_withStatementSingleNameUndefined(self): - """ - An undefined name warning is emitted if the name first defined by a - C{with} statement is used before the C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - bar - with open('foo') as bar: - pass - ''', m.UndefinedName) - - def test_withStatementTupleNamesUndefined(self): - """ - An undefined name warning is emitted if a name first defined by the - tuple-unpacking form of the C{with} statement is used before the - C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - baz - with open('foo') as (bar, baz): - pass - ''', m.UndefinedName) - - def test_withStatementSingleNameRedefined(self): - """ - A redefined name warning is emitted if a name bound by an import is - rebound by the name defined by a C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - import bar - with open('foo') as bar: - pass - ''', m.RedefinedWhileUnused) - - def test_withStatementTupleNamesRedefined(self): - """ - A redefined name warning is emitted if a name bound by an import is - rebound by one of the names defined by the tuple-unpacking form of a - C{with} statement. - """ - self.flakes(''' - from __future__ import with_statement - import bar - with open('foo') as (bar, baz): - pass - ''', m.RedefinedWhileUnused) - - def test_withStatementUndefinedInside(self): - """ - An undefined name warning is emitted if a name is used inside the - body of a C{with} statement without first being bound. - """ - self.flakes(''' - from __future__ import with_statement - with open('foo') as bar: - baz - ''', m.UndefinedName) - - def test_withStatementNameDefinedInBody(self): - """ - A name defined in the body of a C{with} statement can be used after - the body ends without warning. - """ - self.flakes(''' - from __future__ import with_statement - with open('foo') as bar: - baz = 10 - baz - ''') - - def test_withStatementUndefinedInExpression(self): - """ - An undefined name warning is emitted if a name in the I{test} - expression of a C{with} statement is undefined. - """ - self.flakes(''' - from __future__ import with_statement - with bar as baz: - pass - ''', m.UndefinedName) - - self.flakes(''' - from __future__ import with_statement - with bar as bar: - pass - ''', m.UndefinedName) - - @skipIf(version_info < (2, 7), "Python >= 2.7 only") - def test_dictComprehension(self): - """ - Dict comprehensions are properly handled. - """ - self.flakes(''' - a = {1: x for x in range(10)} - ''') - - @skipIf(version_info < (2, 7), "Python >= 2.7 only") - def test_setComprehensionAndLiteral(self): - """ - Set comprehensions are properly handled. - """ - self.flakes(''' - a = {1, 2, 3} - b = {x for x in range(10)} - ''') - - def test_exceptionUsedInExcept(self): - as_exc = ', ' if version_info < (2, 6) else ' as ' - self.flakes(''' - try: pass - except Exception%se: e - ''' % as_exc) - - self.flakes(''' - def download_review(): - try: pass - except Exception%se: e - ''' % as_exc) - - def test_exceptWithoutNameInFunction(self): - """ - Don't issue false warning when an unnamed exception is used. - Previously, there would be a false warning, but only when the - try..except was in a function - """ - self.flakes(''' - import tokenize - def foo(): - try: pass - except tokenize.TokenError: pass - ''') - - def test_exceptWithoutNameInFunctionTuple(self): - """ - Don't issue false warning when an unnamed exception is used. - This example catches a tuple of exception types. - """ - self.flakes(''' - import tokenize - def foo(): - try: pass - except (tokenize.TokenError, IndentationError): pass - ''') - - def test_augmentedAssignmentImportedFunctionCall(self): - """ - Consider a function that is called on the right part of an - augassign operation to be used. - """ - self.flakes(''' - from foo import bar - baz = 0 - baz += bar() - ''') - - def test_assert_without_message(self): - """An assert without a message is not an error.""" - self.flakes(''' - a = 1 - assert a - ''') - - def test_assert_with_message(self): - """An assert with a message is not an error.""" - self.flakes(''' - a = 1 - assert a, 'x' - ''') - - def test_assert_tuple(self): - """An assert of a non-empty tuple is always True.""" - self.flakes(''' - assert (False, 'x') - assert (False, ) - ''', m.AssertTuple, m.AssertTuple) - - def test_assert_tuple_empty(self): - """An assert of an empty tuple is always False.""" - self.flakes(''' - assert () - ''') - - def test_assert_static(self): - """An assert of a static value is not an error.""" - self.flakes(''' - assert True - assert 1 - ''') - - @skipIf(version_info < (3, 3), 'new in Python 3.3') - def test_yieldFromUndefined(self): - """ - Test C{yield from} statement - """ - self.flakes(''' - def bar(): - yield from foo() - ''', m.UndefinedName) - - @skipIf(version_info < (3, 6), 'new in Python 3.6') - def test_f_string(self): - """Test PEP 498 f-strings are treated as a usage.""" - self.flakes(''' - baz = 0 - print(f'\x7b4*baz\N{RIGHT CURLY BRACKET}') - ''') - - -class TestAsyncStatements(TestCase): - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncDef(self): - self.flakes(''' - async def bar(): - return 42 - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncDefAwait(self): - self.flakes(''' - async def read_data(db): - await db.fetch('SELECT ...') - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncDefUndefined(self): - self.flakes(''' - async def bar(): - return foo() - ''', m.UndefinedName) - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncFor(self): - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - output.append(row) - return output - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_loopControlInAsyncFor(self): - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - if row[0] == 'skip': - continue - output.append(row) - return output - ''') - - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - if row[0] == 'stop': - break - output.append(row) - return output - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_loopControlInAsyncForElse(self): - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - output.append(row) - else: - continue - return output - ''', m.ContinueOutsideLoop) - - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - output.append(row) - else: - break - return output - ''', m.BreakOutsideLoop) - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_continueInAsyncForFinally(self): - self.flakes(''' - async def read_data(db): - output = [] - async for row in db.cursor(): - try: - output.append(row) - finally: - continue - return output - ''', m.ContinueInFinally) - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncWith(self): - self.flakes(''' - async def commit(session, data): - async with session.transaction(): - await session.update(data) - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_asyncWithItem(self): - self.flakes(''' - async def commit(session, data): - async with session.transaction() as trans: - await trans.begin() - ... - await trans.end() - ''') - - @skipIf(version_info < (3, 5), 'new in Python 3.5') - def test_matmul(self): - self.flakes(''' - def foo(a, b): - return a @ b - ''') - - @skipIf(version_info < (3, 6), 'new in Python 3.6') - def test_formatstring(self): - self.flakes(''' - hi = 'hi' - mom = 'mom' - f'{hi} {mom}' - ''') - - @skipIf(version_info < (3, 6), 'new in Python 3.6') - def test_variable_annotations(self): - self.flakes(''' - name: str - age: int - ''') - self.flakes(''' - name: str = 'Bob' - age: int = 18 - ''') - self.flakes(''' - class C: - name: str - age: int - ''') - self.flakes(''' - class C: - name: str = 'Bob' - age: int = 18 - ''') - self.flakes(''' - def f(): - name: str - age: int - ''') - self.flakes(''' - def f(): - name: str = 'Bob' - age: int = 18 - foo: not_a_real_type = None - ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable) - self.flakes(''' - def f(): - name: str - print(name) - ''', m.UndefinedName) - self.flakes(''' - foo: not_a_real_type - ''', m.UndefinedName) - self.flakes(''' - foo: not_a_real_type = None - ''', m.UndefinedName) - self.flakes(''' - class C: - foo: not_a_real_type - ''', m.UndefinedName) - self.flakes(''' - class C: - foo: not_a_real_type = None - ''', m.UndefinedName) - self.flakes(''' - def f(): - class C: - foo: not_a_real_type - ''', m.UndefinedName) - self.flakes(''' - def f(): - class C: - foo: not_a_real_type = None - ''', m.UndefinedName) diff --git a/pymode/libs/pyflakes/test/test_return_with_arguments_inside_generator.py b/pymode/libs/pyflakes/test/test_return_with_arguments_inside_generator.py deleted file mode 100644 index fc1272a9..00000000 --- a/pymode/libs/pyflakes/test/test_return_with_arguments_inside_generator.py +++ /dev/null @@ -1,34 +0,0 @@ - -from sys import version_info - -from pyflakes import messages as m -from pyflakes.test.harness import TestCase, skipIf - - -class Test(TestCase): - @skipIf(version_info >= (3, 3), 'new in Python 3.3') - def test_return(self): - self.flakes(''' - class a: - def b(): - for x in a.c: - if x: - yield x - return a - ''', m.ReturnWithArgsInsideGenerator) - - @skipIf(version_info >= (3, 3), 'new in Python 3.3') - def test_returnNone(self): - self.flakes(''' - def a(): - yield 12 - return None - ''', m.ReturnWithArgsInsideGenerator) - - @skipIf(version_info >= (3, 3), 'new in Python 3.3') - def test_returnYieldExpression(self): - self.flakes(''' - def a(): - b = yield a - return b - ''', m.ReturnWithArgsInsideGenerator) diff --git a/pymode/libs/pyflakes/test/test_undefined_names.py b/pymode/libs/pyflakes/test/test_undefined_names.py deleted file mode 100644 index 1464d8e4..00000000 --- a/pymode/libs/pyflakes/test/test_undefined_names.py +++ /dev/null @@ -1,806 +0,0 @@ - -from _ast import PyCF_ONLY_AST -from sys import version_info - -from pyflakes import messages as m, checker -from pyflakes.test.harness import TestCase, skipIf, skip - - -class Test(TestCase): - def test_undefined(self): - self.flakes('bar', m.UndefinedName) - - def test_definedInListComp(self): - self.flakes('[a for a in range(10) if a]') - - @skipIf(version_info < (3,), - 'in Python 2 list comprehensions execute in the same scope') - def test_undefinedInListComp(self): - self.flakes(''' - [a for a in range(10)] - a - ''', - m.UndefinedName) - - @skipIf(version_info < (3,), - 'in Python 2 exception names stay bound after the except: block') - def test_undefinedExceptionName(self): - """Exception names can't be used after the except: block.""" - self.flakes(''' - try: - raise ValueError('ve') - except ValueError as exc: - pass - exc - ''', - m.UndefinedName) - - def test_namesDeclaredInExceptBlocks(self): - """Locals declared in except: blocks can be used after the block. - - This shows the example in test_undefinedExceptionName is - different.""" - self.flakes(''' - try: - raise ValueError('ve') - except ValueError as exc: - e = exc - e - ''') - - @skip('error reporting disabled due to false positives below') - def test_undefinedExceptionNameObscuringLocalVariable(self): - """Exception names obscure locals, can't be used after. - - Last line will raise UnboundLocalError on Python 3 after exiting - the except: block. Note next two examples for false positives to - watch out for.""" - self.flakes(''' - exc = 'Original value' - try: - raise ValueError('ve') - except ValueError as exc: - pass - exc - ''', - m.UndefinedName) - - @skipIf(version_info < (3,), - 'in Python 2 exception names stay bound after the except: block') - def test_undefinedExceptionNameObscuringLocalVariable2(self): - """Exception names are unbound after the `except:` block. - - Last line will raise UnboundLocalError on Python 3 but would print out - 've' on Python 2.""" - self.flakes(''' - try: - raise ValueError('ve') - except ValueError as exc: - pass - print(exc) - exc = 'Original value' - ''', - m.UndefinedName) - - def test_undefinedExceptionNameObscuringLocalVariableFalsePositive1(self): - """Exception names obscure locals, can't be used after. Unless. - - Last line will never raise UnboundLocalError because it's only - entered if no exception was raised.""" - self.flakes(''' - exc = 'Original value' - try: - raise ValueError('ve') - except ValueError as exc: - print('exception logged') - raise - exc - ''') - - def test_delExceptionInExcept(self): - """The exception name can be deleted in the except: block.""" - self.flakes(''' - try: - pass - except Exception as exc: - del exc - ''') - - def test_undefinedExceptionNameObscuringLocalVariableFalsePositive2(self): - """Exception names obscure locals, can't be used after. Unless. - - Last line will never raise UnboundLocalError because `error` is - only falsy if the `except:` block has not been entered.""" - self.flakes(''' - exc = 'Original value' - error = None - try: - raise ValueError('ve') - except ValueError as exc: - error = 'exception logged' - if error: - print(error) - else: - exc - ''') - - @skip('error reporting disabled due to false positives below') - def test_undefinedExceptionNameObscuringGlobalVariable(self): - """Exception names obscure globals, can't be used after. - - Last line will raise UnboundLocalError on both Python 2 and - Python 3 because the existence of that exception name creates - a local scope placeholder for it, obscuring any globals, etc.""" - self.flakes(''' - exc = 'Original value' - def func(): - try: - pass # nothing is raised - except ValueError as exc: - pass # block never entered, exc stays unbound - exc - ''', - m.UndefinedLocal) - - @skip('error reporting disabled due to false positives below') - def test_undefinedExceptionNameObscuringGlobalVariable2(self): - """Exception names obscure globals, can't be used after. - - Last line will raise NameError on Python 3 because the name is - locally unbound after the `except:` block, even if it's - nonlocal. We should issue an error in this case because code - only working correctly if an exception isn't raised, is invalid. - Unless it's explicitly silenced, see false positives below.""" - self.flakes(''' - exc = 'Original value' - def func(): - global exc - try: - raise ValueError('ve') - except ValueError as exc: - pass # block never entered, exc stays unbound - exc - ''', - m.UndefinedLocal) - - def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive1(self): - """Exception names obscure globals, can't be used after. Unless. - - Last line will never raise NameError because it's only entered - if no exception was raised.""" - self.flakes(''' - exc = 'Original value' - def func(): - global exc - try: - raise ValueError('ve') - except ValueError as exc: - print('exception logged') - raise - exc - ''') - - def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive2(self): - """Exception names obscure globals, can't be used after. Unless. - - Last line will never raise NameError because `error` is only - falsy if the `except:` block has not been entered.""" - self.flakes(''' - exc = 'Original value' - def func(): - global exc - error = None - try: - raise ValueError('ve') - except ValueError as exc: - error = 'exception logged' - if error: - print(error) - else: - exc - ''') - - def test_functionsNeedGlobalScope(self): - self.flakes(''' - class a: - def b(): - fu - fu = 1 - ''') - - def test_builtins(self): - self.flakes('range(10)') - - def test_builtinWindowsError(self): - """ - C{WindowsError} is sometimes a builtin name, so no warning is emitted - for using it. - """ - self.flakes('WindowsError') - - def test_magicGlobalsFile(self): - """ - Use of the C{__file__} magic global should not emit an undefined name - warning. - """ - self.flakes('__file__') - - def test_magicGlobalsBuiltins(self): - """ - Use of the C{__builtins__} magic global should not emit an undefined - name warning. - """ - self.flakes('__builtins__') - - def test_magicGlobalsName(self): - """ - Use of the C{__name__} magic global should not emit an undefined name - warning. - """ - self.flakes('__name__') - - def test_magicGlobalsPath(self): - """ - Use of the C{__path__} magic global should not emit an undefined name - warning, if you refer to it from a file called __init__.py. - """ - self.flakes('__path__', m.UndefinedName) - self.flakes('__path__', filename='package/__init__.py') - - def test_globalImportStar(self): - """Can't find undefined names with import *.""" - self.flakes('from fu import *; bar', - m.ImportStarUsed, m.ImportStarUsage) - - @skipIf(version_info >= (3,), 'obsolete syntax') - def test_localImportStar(self): - """ - A local import * still allows undefined names to be found - in upper scopes. - """ - self.flakes(''' - def a(): - from fu import * - bar - ''', m.ImportStarUsed, m.UndefinedName, m.UnusedImport) - - @skipIf(version_info >= (3,), 'obsolete syntax') - def test_unpackedParameter(self): - """Unpacked function parameters create bindings.""" - self.flakes(''' - def a((bar, baz)): - bar; baz - ''') - - def test_definedByGlobal(self): - """ - "global" can make an otherwise undefined name in another function - defined. - """ - self.flakes(''' - def a(): global fu; fu = 1 - def b(): fu - ''') - self.flakes(''' - def c(): bar - def b(): global bar; bar = 1 - ''') - - def test_definedByGlobalMultipleNames(self): - """ - "global" can accept multiple names. - """ - self.flakes(''' - def a(): global fu, bar; fu = 1; bar = 2 - def b(): fu; bar - ''') - - def test_globalInGlobalScope(self): - """ - A global statement in the global scope is ignored. - """ - self.flakes(''' - global x - def foo(): - print(x) - ''', m.UndefinedName) - - def test_global_reset_name_only(self): - """A global statement does not prevent other names being undefined.""" - # Only different undefined names are reported. - # See following test that fails where the same name is used. - self.flakes(''' - def f1(): - s - - def f2(): - global m - ''', m.UndefinedName) - - @skip("todo") - def test_unused_global(self): - """An unused global statement does not define the name.""" - self.flakes(''' - def f1(): - m - - def f2(): - global m - ''', m.UndefinedName) - - def test_del(self): - """Del deletes bindings.""" - self.flakes('a = 1; del a; a', m.UndefinedName) - - def test_delGlobal(self): - """Del a global binding from a function.""" - self.flakes(''' - a = 1 - def f(): - global a - del a - a - ''') - - def test_delUndefined(self): - """Del an undefined name.""" - self.flakes('del a', m.UndefinedName) - - def test_delConditional(self): - """ - Ignores conditional bindings deletion. - """ - self.flakes(''' - context = None - test = True - if False: - del(test) - assert(test) - ''') - - def test_delConditionalNested(self): - """ - Ignored conditional bindings deletion even if they are nested in other - blocks. - """ - self.flakes(''' - context = None - test = True - if False: - with context(): - del(test) - assert(test) - ''') - - def test_delWhile(self): - """ - Ignore bindings deletion if called inside the body of a while - statement. - """ - self.flakes(''' - def test(): - foo = 'bar' - while False: - del foo - assert(foo) - ''') - - def test_delWhileTestUsage(self): - """ - Ignore bindings deletion if called inside the body of a while - statement and name is used inside while's test part. - """ - self.flakes(''' - def _worker(): - o = True - while o is not True: - del o - o = False - ''') - - def test_delWhileNested(self): - """ - Ignore bindings deletions if node is part of while's test, even when - del is in a nested block. - """ - self.flakes(''' - context = None - def _worker(): - o = True - while o is not True: - while True: - with context(): - del o - o = False - ''') - - def test_globalFromNestedScope(self): - """Global names are available from nested scopes.""" - self.flakes(''' - a = 1 - def b(): - def c(): - a - ''') - - def test_laterRedefinedGlobalFromNestedScope(self): - """ - Test that referencing a local name that shadows a global, before it is - defined, generates a warning. - """ - self.flakes(''' - a = 1 - def fun(): - a - a = 2 - return a - ''', m.UndefinedLocal) - - def test_laterRedefinedGlobalFromNestedScope2(self): - """ - Test that referencing a local name in a nested scope that shadows a - global declared in an enclosing scope, before it is defined, generates - a warning. - """ - self.flakes(''' - a = 1 - def fun(): - global a - def fun2(): - a - a = 2 - return a - ''', m.UndefinedLocal) - - def test_intermediateClassScopeIgnored(self): - """ - If a name defined in an enclosing scope is shadowed by a local variable - and the name is used locally before it is bound, an unbound local - warning is emitted, even if there is a class scope between the enclosing - scope and the local scope. - """ - self.flakes(''' - def f(): - x = 1 - class g: - def h(self): - a = x - x = None - print(x, a) - print(x) - ''', m.UndefinedLocal) - - def test_doubleNestingReportsClosestName(self): - """ - Test that referencing a local name in a nested scope that shadows a - variable declared in two different outer scopes before it is defined - in the innermost scope generates an UnboundLocal warning which - refers to the nearest shadowed name. - """ - exc = self.flakes(''' - def a(): - x = 1 - def b(): - x = 2 # line 5 - def c(): - x - x = 3 - return x - return x - return x - ''', m.UndefinedLocal).messages[0] - - # _DoctestMixin.flakes adds two lines preceding the code above. - expected_line_num = 7 if self.withDoctest else 5 - - self.assertEqual(exc.message_args, ('x', expected_line_num)) - - def test_laterRedefinedGlobalFromNestedScope3(self): - """ - Test that referencing a local name in a nested scope that shadows a - global, before it is defined, generates a warning. - """ - self.flakes(''' - def fun(): - a = 1 - def fun2(): - a - a = 1 - return a - return a - ''', m.UndefinedLocal) - - def test_undefinedAugmentedAssignment(self): - self.flakes( - ''' - def f(seq): - a = 0 - seq[a] += 1 - seq[b] /= 2 - c[0] *= 2 - a -= 3 - d += 4 - e[any] = 5 - ''', - m.UndefinedName, # b - m.UndefinedName, # c - m.UndefinedName, m.UnusedVariable, # d - m.UndefinedName, # e - ) - - def test_nestedClass(self): - """Nested classes can access enclosing scope.""" - self.flakes(''' - def f(foo): - class C: - bar = foo - def f(self): - return foo - return C() - - f(123).f() - ''') - - def test_badNestedClass(self): - """Free variables in nested classes must bind at class creation.""" - self.flakes(''' - def f(): - class C: - bar = foo - foo = 456 - return foo - f() - ''', m.UndefinedName) - - def test_definedAsStarArgs(self): - """Star and double-star arg names are defined.""" - self.flakes(''' - def f(a, *b, **c): - print(a, b, c) - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_definedAsStarUnpack(self): - """Star names in unpack are defined.""" - self.flakes(''' - a, *b = range(10) - print(a, b) - ''') - self.flakes(''' - *a, b = range(10) - print(a, b) - ''') - self.flakes(''' - a, *b, c = range(10) - print(a, b, c) - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_usedAsStarUnpack(self): - """ - Star names in unpack are used if RHS is not a tuple/list literal. - """ - self.flakes(''' - def f(): - a, *b = range(10) - ''') - self.flakes(''' - def f(): - (*a, b) = range(10) - ''') - self.flakes(''' - def f(): - [a, *b, c] = range(10) - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_unusedAsStarUnpack(self): - """ - Star names in unpack are unused if RHS is a tuple/list literal. - """ - self.flakes(''' - def f(): - a, *b = any, all, 4, 2, 'un' - ''', m.UnusedVariable, m.UnusedVariable) - self.flakes(''' - def f(): - (*a, b) = [bool, int, float, complex] - ''', m.UnusedVariable, m.UnusedVariable) - self.flakes(''' - def f(): - [a, *b, c] = 9, 8, 7, 6, 5, 4 - ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable) - - @skipIf(version_info < (3,), 'new in Python 3') - def test_keywordOnlyArgs(self): - """Keyword-only arg names are defined.""" - self.flakes(''' - def f(*, a, b=None): - print(a, b) - ''') - - self.flakes(''' - import default_b - def f(*, a, b=default_b): - print(a, b) - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_keywordOnlyArgsUndefined(self): - """Typo in kwonly name.""" - self.flakes(''' - def f(*, a, b=default_c): - print(a, b) - ''', m.UndefinedName) - - @skipIf(version_info < (3,), 'new in Python 3') - def test_annotationUndefined(self): - """Undefined annotations.""" - self.flakes(''' - from abc import note1, note2, note3, note4, note5 - def func(a: note1, *args: note2, - b: note3=12, **kw: note4) -> note5: pass - ''') - - self.flakes(''' - def func(): - d = e = 42 - def func(a: {1, d}) -> (lambda c: e): pass - ''') - - @skipIf(version_info < (3,), 'new in Python 3') - def test_metaClassUndefined(self): - self.flakes(''' - from abc import ABCMeta - class A(metaclass=ABCMeta): pass - ''') - - def test_definedInGenExp(self): - """ - Using the loop variable of a generator expression results in no - warnings. - """ - self.flakes('(a for a in [1, 2, 3] if a)') - - self.flakes('(b for b in (a for a in [1, 2, 3] if a) if b)') - - def test_undefinedInGenExpNested(self): - """ - The loop variables of generator expressions nested together are - not defined in the other generator. - """ - self.flakes('(b for b in (a for a in [1, 2, 3] if b) if b)', - m.UndefinedName) - - self.flakes('(b for b in (a for a in [1, 2, 3] if a) if a)', - m.UndefinedName) - - def test_undefinedWithErrorHandler(self): - """ - Some compatibility code checks explicitly for NameError. - It should not trigger warnings. - """ - self.flakes(''' - try: - socket_map - except NameError: - socket_map = {} - ''') - self.flakes(''' - try: - _memoryview.contiguous - except (NameError, AttributeError): - raise RuntimeError("Python >= 3.3 is required") - ''') - # If NameError is not explicitly handled, generate a warning - self.flakes(''' - try: - socket_map - except: - socket_map = {} - ''', m.UndefinedName) - self.flakes(''' - try: - socket_map - except Exception: - socket_map = {} - ''', m.UndefinedName) - - def test_definedInClass(self): - """ - Defined name for generator expressions and dict/set comprehension. - """ - self.flakes(''' - class A: - T = range(10) - - Z = (x for x in T) - L = [x for x in T] - B = dict((i, str(i)) for i in T) - ''') - - if version_info >= (2, 7): - self.flakes(''' - class A: - T = range(10) - - X = {x for x in T} - Y = {x:x for x in T} - ''') - - def test_definedInClassNested(self): - """Defined name for nested generator expressions in a class.""" - self.flakes(''' - class A: - T = range(10) - - Z = (x for x in (a for a in T)) - ''') - - def test_undefinedInLoop(self): - """ - The loop variable is defined after the expression is computed. - """ - self.flakes(''' - for i in range(i): - print(i) - ''', m.UndefinedName) - self.flakes(''' - [42 for i in range(i)] - ''', m.UndefinedName) - self.flakes(''' - (42 for i in range(i)) - ''', m.UndefinedName) - - @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist') - def test_definedFromLambdaInDictionaryComprehension(self): - """ - Defined name referenced from a lambda function within a dict/set - comprehension. - """ - self.flakes(''' - {lambda: id(x) for x in range(10)} - ''') - - def test_definedFromLambdaInGenerator(self): - """ - Defined name referenced from a lambda function within a generator - expression. - """ - self.flakes(''' - any(lambda: id(x) for x in range(10)) - ''') - - @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist') - def test_undefinedFromLambdaInDictionaryComprehension(self): - """ - Undefined name referenced from a lambda function within a dict/set - comprehension. - """ - self.flakes(''' - {lambda: id(y) for x in range(10)} - ''', m.UndefinedName) - - def test_undefinedFromLambdaInComprehension(self): - """ - Undefined name referenced from a lambda function within a generator - expression. - """ - self.flakes(''' - any(lambda: id(y) for x in range(10)) - ''', m.UndefinedName) - - -class NameTests(TestCase): - """ - Tests for some extra cases of name handling. - """ - def test_impossibleContext(self): - """ - A Name node with an unrecognized context results in a RuntimeError being - raised. - """ - tree = compile("x = 10", "", "exec", PyCF_ONLY_AST) - # Make it into something unrecognizable. - tree.body[0].targets[0].ctx = object() - self.assertRaises(RuntimeError, checker.Checker, tree) diff --git a/pymode/libs/pylint/__init__.py b/pymode/libs/pylint/__init__.py index d7bb9ab0..ba882ea6 100644 --- a/pymode/libs/pylint/__init__.py +++ b/pymode/libs/pylint/__init__.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -12,13 +12,6 @@ def run_pylint(): from pylint.lint import Run Run(sys.argv[1:]) -def run_pylint_gui(): - """run pylint-gui""" - try: - from pylint.gui import Run - Run(sys.argv[1:]) - except ImportError: - sys.exit('tkinter is not available') def run_epylint(): """run pylint""" diff --git a/pymode/libs/pylint/__main__.py b/pymode/libs/pylint/__main__.py index 0c4e3712..f1ecf1b9 100644 --- a/pymode/libs/pylint/__main__.py +++ b/pymode/libs/pylint/__main__.py @@ -1,5 +1,4 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/__pkginfo__.py b/pymode/libs/pylint/__pkginfo__.py index 953ea953..099da4ba 100644 --- a/pymode/libs/pylint/__pkginfo__.py +++ b/pymode/libs/pylint/__pkginfo__.py @@ -1,30 +1,56 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING # pylint: disable=W0622,C0103 """pylint packaging information""" + from __future__ import absolute_import from os.path import join +from sys import version_info as py_version +from pkg_resources import parse_version +from setuptools import __version__ as setuptools_version modname = distname = 'pylint' -numversion = (1, 6, 4) +numversion = (1, 7, 2) version = '.'.join([str(num) for num in numversion]) install_requires = [ - 'astroid>=1.4.5,<1.5.0', + 'astroid>=1.5.1', 'six', 'isort >= 4.2.5', 'mccabe', ] +dependency_links = [] + extras_require = {} extras_require[':sys_platform=="win32"'] = ['colorama'] -extras_require[':python_version=="2.7"'] = ['configparser', 'backports.functools_lru_cache'] + + +def has_environment_marker_range_operators_support(): + """Code extracted from 'pytest/setup.py' + https://github.com/pytest-dev/pytest/blob/7538680c/setup.py#L31 + The first known release to support environment marker with range operators + it is 17.1, see: https://setuptools.readthedocs.io/en/latest/history.html#id113 + """ + return parse_version(setuptools_version) >= parse_version('17.1') + + +if has_environment_marker_range_operators_support(): + extras_require[':python_version=="2.7"'] = ['configparser', 'backports.functools_lru_cache'] + extras_require[':python_version<"3.4"'] = ['singledispatch'] +else: + if (py_version.major, py_version.minor) == (2, 7): + install_requires.extend(['configparser', 'backports.functools_lru_cache']) + if py_version < (3, 4): + install_requires.extend(['singledispatch']) license = 'GPL' @@ -62,11 +88,11 @@ . Additionally, it is possible to write plugins to add your own checks. . - Pylint is shipped with "pylint-gui", "pyreverse" (UML diagram generator) + Pylint is shipped with "pyreverse" (UML diagram generator) and "symilar" (an independent similarities checker).""" scripts = [join('bin', filename) - for filename in ('pylint', 'pylint-gui', "symilar", "epylint", + for filename in ('pylint', "symilar", "epylint", "pyreverse")] include_dirs = [join('pylint', 'test')] diff --git a/pymode/libs/pylint/checkers/__init__.py b/pymode/libs/pylint/checkers/__init__.py index 07b05a59..78921870 100644 --- a/pymode/libs/pylint/checkers/__init__.py +++ b/pymode/libs/pylint/checkers/__init__.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -22,7 +24,8 @@ 14: string_constant 15: stdlib 16: python3 -17-50: not yet used: reserved for future internal checkers. +17: refactoring +18-50: not yet used: reserved for future internal checkers. 51-99: perhaps used: reserved for external checkers The raw_metrics checker has no number associated since it doesn't emit any @@ -31,8 +34,8 @@ """ import sys -import warnings import tokenize +import warnings from pylint.config import OptionsProviderMixIn from pylint.reporters import diff_string diff --git a/pymode/libs/pylint/checkers/async.py b/pymode/libs/pylint/checkers/async.py index 38860360..6d759b24 100644 --- a/pymode/libs/pylint/checkers/async.py +++ b/pymode/libs/pylint/checkers/async.py @@ -1,10 +1,12 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """Checker for anything related to the async protocol (PEP 492).""" +import sys + import astroid from astroid import exceptions @@ -36,7 +38,8 @@ def open(self): @checker_utils.check_messages('yield-inside-async-function') def visit_asyncfunctiondef(self, node): for child in node.nodes_of_class(astroid.Yield): - if child.scope() is node: + if child.scope() is node and (sys.version_info[:2] == (3, 5) or + isinstance(child, astroid.YieldFrom)): self.add_message('yield-inside-async-function', node=child) @checker_utils.check_messages('not-async-context-manager') diff --git a/pymode/libs/pylint/checkers/base.py b/pymode/libs/pylint/checkers/base.py index bc918595..a0d8c431 100644 --- a/pymode/libs/pylint/checkers/base.py +++ b/pymode/libs/pylint/checkers/base.py @@ -1,5 +1,18 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# -*- coding: utf-8 -*- +# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2012-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2014 Brett Cannon +# Copyright (c) 2015 Radu Ciorba +# Copyright (c) 2015 Michael Kefeder +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2015 Stephane Wirtel +# Copyright (c) 2015 Nick Bastin +# Copyright (c) 2016 Alex Jurkiewicz +# Copyright (c) 2016 Yannack +# Copyright (c) 2016 Laura Médioni +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -16,29 +29,13 @@ import astroid import astroid.bases import astroid.scoped_nodes -from astroid import are_exclusive, InferenceError - -from pylint.interfaces import (IAstroidChecker, ITokenChecker, INFERENCE, - INFERENCE_FAILURE, HIGH) -from pylint.utils import EmptyReport, deprecated_option -from pylint.reporters import diff_string -from pylint.checkers import BaseChecker, BaseTokenChecker -from pylint.checkers.utils import ( - check_messages, - clobber_in_except, - is_builtin_object, - is_inside_except, - overrides_a_method, - get_argument_from_call, - node_frame_class, - NoSuchArgumentError, - error_of_type, - unimplemented_abstract_methods, - has_known_bases, - safe_infer, - is_comprehension - ) -from pylint.reporters.ureports.nodes import Table + +from pylint import checkers +from pylint import exceptions +from pylint import interfaces +from pylint.checkers import utils +from pylint import reporters +from pylint.reporters.ureports import nodes as reporter_nodes # regex for class/function/variable/constant name @@ -46,7 +43,7 @@ MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$') CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$') COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$') -DEFAULT_NAME_RGX = re.compile('[a-z_][a-z0-9_]{2,30}$') +DEFAULT_NAME_RGX = re.compile('(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$') CLASS_ATTRIBUTE_RGX = re.compile(r'([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$') # do not require a doc string on private/system methods NO_REQUIRED_DOC_RGX = re.compile('^_') @@ -65,7 +62,7 @@ PY35 = sys.version_info >= (3, 5) # Name categories that are always consistent with all naming conventions. -EXEMPT_NAME_CATEGORIES = set(('exempt', 'ignore')) +EXEMPT_NAME_CATEGORIES = {'exempt', 'ignore'} # A mapping from builtin-qname -> symbol, to be used when generating messages # about dangerous default values as arguments @@ -75,7 +72,6 @@ ) REVERSED_COMPS = {'<': '>', '<=': '>=', '>': '<', '>=': '<='} -del re def _redefines_import(node): """ Detect that the given node (AssName) is inside an @@ -85,7 +81,7 @@ def _redefines_import(node): current = node while current and not isinstance(current.parent, astroid.ExceptHandler): current = current.parent - if not current or not error_of_type(current.parent, ImportError): + if not current or not utils.error_of_type(current.parent, ImportError): return False try_block = current.parent.parent for import_node in try_block.nodes_of_class((astroid.ImportFrom, astroid.Import)): @@ -97,6 +93,7 @@ def _redefines_import(node): return True return False + def in_loop(node): """return True if the node is inside a kind of for loop""" parent = node.parent @@ -107,6 +104,7 @@ def in_loop(node): parent = parent.parent return False + def in_nested_list(nested_list, obj): """return true if the object is an element of or of a nested list @@ -119,6 +117,7 @@ def in_nested_list(nested_list, obj): return True return False + def _loop_exits_early(loop): """Returns true if a loop has a break statement in its body.""" loop_nodes = (astroid.For, astroid.While) @@ -136,11 +135,12 @@ def _loop_exits_early(loop): return True return False + def _is_multi_naming_match(match, node_type, confidence): return (match is not None and match.lastgroup is not None and match.lastgroup not in EXEMPT_NAME_CATEGORIES - and (node_type != 'method' or confidence != INFERENCE_FAILURE)) + and (node_type != 'method' or confidence != interfaces.INFERENCE_FAILURE)) if sys.version_info < (3, 0): @@ -188,7 +188,7 @@ def _determine_function_name_type(node, config=None): if (isinstance(decorator, astroid.Name) or (isinstance(decorator, astroid.Attribute) and decorator.attrname in property_names)): - infered = safe_infer(decorator) + infered = utils.safe_infer(decorator) if infered and infered.qname() in property_classes: return 'attr' # If the function is decorated using the prop_method.{setter,getter} @@ -199,13 +199,6 @@ def _determine_function_name_type(node, config=None): return 'method' -def _is_none(node): - return (node is None or - (isinstance(node, astroid.Const) and node.value is None) or - (isinstance(node, astroid.Name) and node.name == 'None') - ) - - def _has_abstract_methods(node): """ Determine if the given `node` has abstract methods. @@ -213,7 +206,7 @@ def _has_abstract_methods(node): The methods should be made abstract by decorating them with `abc` decorators. """ - return len(unimplemented_abstract_methods(node)) > 0 + return len(utils.unimplemented_abstract_methods(node)) > 0 def report_by_type_stats(sect, stats, old_stats): @@ -228,7 +221,7 @@ def report_by_type_stats(sect, stats, old_stats): try: total = stats[node_type] except KeyError: - raise EmptyReport() + raise exceptions.EmptyReportError() nice_stats[node_type] = {} if total != 0: try: @@ -248,13 +241,14 @@ def report_by_type_stats(sect, stats, old_stats): new = stats[node_type] old = old_stats.get(node_type, None) if old is not None: - diff_str = diff_string(old, new) + diff_str = reporters.diff_string(old, new) else: old, diff_str = 'NC', 'NC' lines += (node_type, str(new), str(old), diff_str, nice_stats[node_type].get('percent_documented', '0'), nice_stats[node_type].get('percent_badname', '0')) - sect.append(Table(children=lines, cols=6, rheaders=1)) + sect.append(reporter_nodes.Table(children=lines, cols=6, rheaders=1)) + def redefined_by_decorator(node): """return True if the object is a method redefined via decorator. @@ -273,31 +267,11 @@ def x(self, value): self._x = value return False -def _node_type(node): - """Return the inferred type for `node` - - If there is more than one possible type, or if inferred type is YES or None, - return None - """ - # check there is only one possible type for the assign node. Else we - # don't handle it for now - types = set() - try: - for var_type in node.infer(): - if var_type == astroid.YES or _is_none(var_type): - continue - types.add(var_type) - if len(types) > 1: - return - except InferenceError: - return - return types.pop() if types else None - - -class _BasicChecker(BaseChecker): - __implements__ = IAstroidChecker +class _BasicChecker(checkers.BaseChecker): + __implements__ = interfaces.IAstroidChecker name = 'basic' + class BasicErrorChecker(_BasicChecker): msgs = { 'E0100': ('__init__ method is a generator', @@ -373,14 +347,19 @@ class BasicErrorChecker(_BasicChecker): 'Emitted when a nonlocal variable does not have an attached ' 'name somewhere in the parent scopes', {'minversion': (3, 0)}), + 'E0118': ("Name %r is used prior to global declaration", + 'used-prior-global-declaration', + 'Emitted when a name is used prior a global declaration, ' + 'which results in an error since Python 3.6.', + {'minversion': (3, 6)}), } - @check_messages('function-redefined') + @utils.check_messages('function-redefined') def visit_classdef(self, node): self._check_redefinition('class', node) - @check_messages('too-many-star-expressions', - 'invalid-star-assignment-target') + @utils.check_messages('too-many-star-expressions', + 'invalid-star-assignment-target') def visit_assign(self, node): starred = list(node.targets[0].nodes_of_class(astroid.Starred)) if len(starred) > 1: @@ -390,7 +369,7 @@ def visit_assign(self, node): if isinstance(node.targets[0], astroid.Starred): self.add_message('invalid-star-assignment-target', node=node) - @check_messages('star-needs-assignment-target') + @utils.check_messages('star-needs-assignment-target') def visit_starred(self, node): """Check that a Starred expression is used in an assignment target.""" if isinstance(node.parent, astroid.Call): @@ -410,12 +389,15 @@ def visit_starred(self, node): if stmt.value is node or stmt.value.parent_of(node): self.add_message('star-needs-assignment-target', node=node) - @check_messages('init-is-generator', 'return-in-init', - 'function-redefined', 'return-arg-in-generator', - 'duplicate-argument-name', 'nonlocal-and-global') + @utils.check_messages('init-is-generator', 'return-in-init', + 'function-redefined', 'return-arg-in-generator', + 'duplicate-argument-name', 'nonlocal-and-global', + 'used-prior-global-declaration') def visit_functiondef(self, node): self._check_nonlocal_and_global(node) - if not redefined_by_decorator(node): + self._check_name_used_prior_global(node) + if (not redefined_by_decorator(node) and + not utils.is_registered_in_singledispatch_function(node)): self._check_redefinition(node.is_method() and 'method' or 'function', node) # checks for max returns, branch, return in __init__ returns = node.nodes_of_class(astroid.Return, @@ -427,7 +409,7 @@ def visit_functiondef(self, node): else: values = [r.value for r in returns] # Are we returning anything but None from constructors - if [v for v in values if not _is_none(v)]: + if any(v for v in values if not utils.is_none(v)): self.add_message('return-in-init', node=node) elif node.is_generator(): # make sure we don't mix non-None returns and yields @@ -447,6 +429,29 @@ def visit_functiondef(self, node): visit_asyncfunctiondef = visit_functiondef + def _check_name_used_prior_global(self, node): + + scope_globals = { + name: child + for child in node.nodes_of_class(astroid.Global) + for name in child.names + if child.scope() is node + } + + for node_name in node.nodes_of_class(astroid.Name): + if node_name.scope() is not node: + continue + + name = node_name.name + corresponding_global = scope_globals.get(name) + if not corresponding_global: + continue + + global_lineno = corresponding_global.fromlineno + if global_lineno and global_lineno > node_name.fromlineno: + self.add_message('used-prior-global-declaration', + node=node_name, args=(name, )) + def _check_nonlocal_and_global(self, node): """Check that a name is both nonlocal and global.""" def same_scope(current): @@ -463,36 +468,36 @@ def same_scope(current): self.add_message('nonlocal-and-global', args=(name, ), node=node) - @check_messages('return-outside-function') + @utils.check_messages('return-outside-function') def visit_return(self, node): if not isinstance(node.frame(), astroid.FunctionDef): self.add_message('return-outside-function', node=node) - @check_messages('yield-outside-function') + @utils.check_messages('yield-outside-function') def visit_yield(self, node): self._check_yield_outside_func(node) - @check_messages('yield-outside-function') + @utils.check_messages('yield-outside-function') def visit_yieldfrom(self, node): self._check_yield_outside_func(node) - @check_messages('not-in-loop', 'continue-in-finally') + @utils.check_messages('not-in-loop', 'continue-in-finally') def visit_continue(self, node): self._check_in_loop(node, 'continue') - @check_messages('not-in-loop') + @utils.check_messages('not-in-loop') def visit_break(self, node): self._check_in_loop(node, 'break') - @check_messages('useless-else-on-loop') + @utils.check_messages('useless-else-on-loop') def visit_for(self, node): self._check_else_on_loop(node) - @check_messages('useless-else-on-loop') + @utils.check_messages('useless-else-on-loop') def visit_while(self, node): self._check_else_on_loop(node) - @check_messages('nonexistent-operator') + @utils.check_messages('nonexistent-operator') def visit_unaryop(self, node): """check use of the non-existent ++ and -- operator operator""" if ((node.op in '+-') and @@ -520,12 +525,12 @@ def _check_nonlocal_without_binding(self, node, name): self.add_message('nonlocal-without-binding', args=(name, ), node=node) - @check_messages('nonlocal-without-binding') + @utils.check_messages('nonlocal-without-binding') def visit_nonlocal(self, node): for name in node.names: self._check_nonlocal_without_binding(node, name) - @check_messages('abstract-class-instantiated') + @utils.check_messages('abstract-class-instantiated') def visit_call(self, node): """ Check instantiating abstract class with abc.ABCMeta as metaclass. @@ -538,7 +543,7 @@ def visit_call(self, node): if not isinstance(infered, astroid.ClassDef): return - klass = node_frame_class(node) + klass = utils.node_frame_class(node) if klass is infered: # Don't emit the warning if the class is instantiated # in its own body or if the call is not an instance @@ -599,12 +604,11 @@ def _check_in_loop(self, node, node_name): def _check_redefinition(self, redeftype, node): """check for redefinition of a function / method / class name""" defined_self = node.parent.frame()[node.name] - if defined_self is not node and not are_exclusive(node, defined_self): + if defined_self is not node and not astroid.are_exclusive(node, defined_self): self.add_message('function-redefined', node=node, args=(redeftype, defined_self.fromlineno)) - class BasicChecker(_BasicChecker): """checks for : * doc strings @@ -616,7 +620,7 @@ class BasicChecker(_BasicChecker): * uses of the global statement """ - __implements__ = IAstroidChecker + __implements__ = interfaces.IAstroidChecker name = 'basic' msgs = { @@ -656,7 +660,7 @@ class BasicChecker(_BasicChecker): 'exec-used', 'Used when you use the "exec" statement (function for Python ' '3), to discourage its usage. That doesn\'t ' - 'mean you can not use it !'), + 'mean you cannot use it !'), 'W0123': ('Use of eval', 'eval-used', 'Used when you use the "eval" function, to discourage its ' @@ -694,12 +698,6 @@ class BasicChecker(_BasicChecker): } - options = (('required-attributes', - deprecated_option(opt_type='csv', - help_msg="Required attributes for module. " - "This option is obsolete.", - deprecation_msg="This option %r will be removed in Pylint 2.0")), - ) reports = (('RP0101', 'Statistics by type', report_by_type_stats),) def __init__(self, linter): @@ -714,15 +712,15 @@ def open(self): self.stats = self.linter.add_stats(module=0, function=0, method=0, class_=0) - @check_messages('using-constant-test') + @utils.check_messages('using-constant-test') def visit_if(self, node): self._check_using_constant_test(node, node.test) - @check_messages('using-constant-test') + @utils.check_messages('using-constant-test') def visit_ifexp(self, node): self._check_using_constant_test(node, node.test) - @check_messages('using-constant-test') + @utils.check_messages('using-constant-test') def visit_comprehension(self, node): if node.ifs: for if_test in node.ifs: @@ -749,7 +747,7 @@ def _check_using_constant_test(self, node, test): inferred = None emit = isinstance(test, (astroid.Const, ) + structs + const_nodes) if not isinstance(test, except_nodes): - inferred = safe_infer(test) + inferred = utils.safe_infer(test) if emit or isinstance(inferred, const_nodes): self.add_message('using-constant-test', node=node) @@ -765,8 +763,8 @@ def visit_classdef(self, node): # pylint: disable=unused-argument """ self.stats['class'] += 1 - @check_messages('pointless-statement', 'pointless-string-statement', - 'expression-not-assigned') + @utils.check_messages('pointless-statement', 'pointless-string-statement', + 'expression-not-assigned') def visit_expr(self, node): """check for various kind of statements without effect""" expr = node.value @@ -827,7 +825,7 @@ def _has_variadic_argument(args, variadic_name): return True return False - @check_messages('unnecessary-lambda') + @utils.check_messages('unnecessary-lambda') def visit_lambda(self, node): """check whether or not the lambda is suspicious """ @@ -879,7 +877,7 @@ def visit_lambda(self, node): self.add_message('unnecessary-lambda', line=node.fromlineno, node=node) - @check_messages('dangerous-default-value') + @utils.check_messages('dangerous-default-value') def visit_functiondef(self, node): """check function name, docstring, arguments, redefinition, variable names, max locals @@ -927,7 +925,7 @@ def _check_dangerous_default(self, node): node=node, args=(msg, )) - @check_messages('unreachable', 'lost-exception') + @utils.check_messages('unreachable', 'lost-exception') def visit_return(self, node): """1 - check is the node has a right sibling (if so, that's some unreachable code) @@ -938,14 +936,14 @@ def visit_return(self, node): # Is it inside final body of a try...finally bloc ? self._check_not_in_finally(node, 'return', (astroid.FunctionDef,)) - @check_messages('unreachable') + @utils.check_messages('unreachable') def visit_continue(self, node): """check is the node has a right sibling (if so, that's some unreachable code) """ self._check_unreachable(node) - @check_messages('unreachable', 'lost-exception') + @utils.check_messages('unreachable', 'lost-exception') def visit_break(self, node): """1 - check is the node has a right sibling (if so, that's some unreachable code) @@ -957,19 +955,19 @@ def visit_break(self, node): # 2 - Is it inside final body of a try...finally bloc ? self._check_not_in_finally(node, 'break', (astroid.For, astroid.While,)) - @check_messages('unreachable') + @utils.check_messages('unreachable') def visit_raise(self, node): """check if the node has a right sibling (if so, that's some unreachable code) """ self._check_unreachable(node) - @check_messages('exec-used') + @utils.check_messages('exec-used') def visit_exec(self, node): """just print a warning on exec statements""" self.add_message('exec-used', node=node) - @check_messages('eval-used', 'exec-used', 'bad-reversed-sequence') + @utils.check_messages('eval-used', 'exec-used', 'bad-reversed-sequence') def visit_call(self, node): """visit a CallFunc node -> check if this is not a blacklisted builtin call and check for * or ** use @@ -987,14 +985,14 @@ def visit_call(self, node): elif name == 'eval': self.add_message('eval-used', node=node) - @check_messages('assert-on-tuple') + @utils.check_messages('assert-on-tuple') def visit_assert(self, node): """check the use of an assert statement on a tuple.""" if node.fail is None and isinstance(node.test, astroid.Tuple) and \ len(node.test.elts) == 2: self.add_message('assert-on-tuple', node=node) - @check_messages('duplicate-key') + @utils.check_messages('duplicate-key') def visit_dict(self, node): """check duplicate key in dictionary""" keys = set() @@ -1040,8 +1038,8 @@ def _check_not_in_finally(self, node, node_name, breaker_classes=()): def _check_reversed(self, node): """ check that the argument to `reversed` is a sequence """ try: - argument = safe_infer(get_argument_from_call(node, position=0)) - except NoSuchArgumentError: + argument = utils.safe_infer(utils.get_argument_from_call(node, position=0)) + except utils.NoSuchArgumentError: pass else: if argument is astroid.YES: @@ -1052,19 +1050,19 @@ def _check_reversed(self, node): if isinstance(node.args[0], astroid.Call): try: func = next(node.args[0].func.infer()) - except InferenceError: + except astroid.InferenceError: return if (getattr(func, 'name', None) == 'iter' and - is_builtin_object(func)): + utils.is_builtin_object(func)): self.add_message('bad-reversed-sequence', node=node) return if isinstance(argument, astroid.Instance): if (argument._proxied.name == 'dict' and - is_builtin_object(argument._proxied)): + utils.is_builtin_object(argument._proxied)): self.add_message('bad-reversed-sequence', node=node) return - elif any(ancestor.name == 'dict' and is_builtin_object(ancestor) + elif any(ancestor.name == 'dict' and utils.is_builtin_object(ancestor) for ancestor in argument._proxied.ancestors()): # Mappings aren't accepted by reversed(), unless # they provide explicitly a __reversed__ method. @@ -1088,7 +1086,7 @@ def _check_reversed(self, node): # everything else is not a proper sequence for reversed() self.add_message('bad-reversed-sequence', node=node) - @check_messages('confusing-with-statement') + @utils.check_messages('confusing-with-statement') def visit_with(self, node): if not PY3K: # in Python 2 a "with" statement with multiple managers coresponds @@ -1129,6 +1127,7 @@ def visit_with(self, node): 'inlinevar': (COMP_VAR_RGX, 'inline iteration'), } + def _create_naming_options(): name_options = [] for name_type, (rgx, human_readable_name) in six.iteritems(_NAME_TYPES): @@ -1143,7 +1142,9 @@ def _create_naming_options(): 'help': 'Naming hint for %s names' % (human_readable_name,)})) return tuple(name_options) + class NameChecker(_BasicChecker): + msgs = { 'C0102': ('Black listed name "%s"', 'blacklisted-name', @@ -1153,6 +1154,10 @@ class NameChecker(_BasicChecker): 'invalid-name', 'Used when the name doesn\'t match the regular expression ' 'associated to its type (constant, variable, class...).'), + 'W0111': ('Name %s will become a keyword in Python %s', + 'assign-to-new-keyword', + 'Used when assignment will become invalid in future ' + 'Python release due to introducing new keyword'), } options = (('good-names', @@ -1188,6 +1193,10 @@ class NameChecker(_BasicChecker): ), ) + _create_naming_options() + KEYWORD_ONSET = { + (3, 0): {'True', 'False'}, + (3, 7): {'async', 'await'} + } def __init__(self, linter): _BasicChecker.__init__(self, linter) @@ -1208,7 +1217,7 @@ def open(self): for name_type in group.split(':'): self._name_group[name_type] = 'group_%s' % (group,) - @check_messages('blacklisted-name', 'invalid-name') + @utils.check_messages('blacklisted-name', 'invalid-name') def visit_module(self, node): self._check_name('module', node.name.split('.')[-1], node) self._bad_names = {} @@ -1231,23 +1240,23 @@ def leave_module(self, node): # pylint: disable=unused-argument for args in warnings: self._raise_name_warning(*args) - @check_messages('blacklisted-name', 'invalid-name') + @utils.check_messages('blacklisted-name', 'invalid-name') def visit_classdef(self, node): self._check_name('class', node.name, node) for attr, anodes in six.iteritems(node.instance_attrs): if not any(node.instance_attr_ancestors(attr)): self._check_name('attr', attr, anodes[0]) - @check_messages('blacklisted-name', 'invalid-name') + @utils.check_messages('blacklisted-name', 'invalid-name') def visit_functiondef(self, node): # Do not emit any warnings if the method is just an implementation # of a base class method. - confidence = HIGH + confidence = interfaces.HIGH if node.is_method(): - if overrides_a_method(node.parent.frame(), node.name): + if utils.overrides_a_method(node.parent.frame(), node.name): return - confidence = (INFERENCE if has_known_bases(node.parent.frame()) - else INFERENCE_FAILURE) + confidence = (interfaces.INFERENCE if utils.has_known_bases(node.parent.frame()) + else interfaces.INFERENCE_FAILURE) self._check_name(_determine_function_name_type(node, config=self.config), @@ -1259,21 +1268,29 @@ def visit_functiondef(self, node): visit_asyncfunctiondef = visit_functiondef - @check_messages('blacklisted-name', 'invalid-name') + @utils.check_messages('blacklisted-name', 'invalid-name') def visit_global(self, node): for name in node.names: self._check_name('const', name, node) - @check_messages('blacklisted-name', 'invalid-name') + @utils.check_messages('blacklisted-name', 'invalid-name') def visit_assignname(self, node): """check module level assigned names""" + keyword_first_version = self._name_became_keyword_in_version( + node.name, self.KEYWORD_ONSET + ) + if keyword_first_version is not None: + self.add_message('assign-to-new-keyword', + node=node, args=(node.name, keyword_first_version), + confidence=interfaces.HIGH) + frame = node.frame() ass_type = node.assign_type() if isinstance(ass_type, astroid.Comprehension): self._check_name('inlinevar', node.name, node) elif isinstance(frame, astroid.Module): if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type): - if isinstance(safe_infer(ass_type.value), astroid.ClassDef): + if isinstance(utils.safe_infer(ass_type.value), astroid.ClassDef): self._check_name('class', node.name, node) else: if not _redefines_import(node): @@ -1311,10 +1328,10 @@ def _raise_name_warning(self, node, node_type, name, confidence): confidence=confidence) self.stats['badname_' + node_type] += 1 - def _check_name(self, node_type, name, node, confidence=HIGH): + def _check_name(self, node_type, name, node, confidence=interfaces.HIGH): """check for a name using the type's regexp""" - if is_inside_except(node): - clobbering, _ = clobber_in_except(node) + if utils.is_inside_except(node): + clobbering, _ = utils.clobber_in_except(node) if clobbering: return if name in self.config.good_names: @@ -1335,6 +1352,13 @@ def _check_name(self, node_type, name, node, confidence=HIGH): if match is None: self._raise_name_warning(node, node_type, name, confidence) + @staticmethod + def _name_became_keyword_in_version(name, rules): + for version, keywords in rules.items(): + if name in keywords and sys.version_info < version: + return '.'.join(map(str, version)) + return None + class DocStringChecker(_BasicChecker): msgs = { @@ -1363,17 +1387,17 @@ class DocStringChecker(_BasicChecker): ), ) - def open(self): self.stats = self.linter.add_stats(undocumented_module=0, undocumented_function=0, undocumented_method=0, undocumented_class=0) - @check_messages('missing-docstring', 'empty-docstring') + + @utils.check_messages('missing-docstring', 'empty-docstring') def visit_module(self, node): self._check_docstring('module', node) - @check_messages('missing-docstring', 'empty-docstring') + @utils.check_messages('missing-docstring', 'empty-docstring') def visit_classdef(self, node): if self.config.no_docstring_rgx.match(node.name) is None: self._check_docstring('class', node) @@ -1387,17 +1411,17 @@ def _is_setter_or_deleter(node): return True return False - @check_messages('missing-docstring', 'empty-docstring') + @utils.check_messages('missing-docstring', 'empty-docstring') def visit_functiondef(self, node): if self.config.no_docstring_rgx.match(node.name) is None: - ftype = node.is_method() and 'method' or 'function' + ftype = 'method' if node.is_method() else 'function' if node.decorators and self._is_setter_or_deleter(node): return if isinstance(node.parent.frame(), astroid.ClassDef): overridden = False - confidence = (INFERENCE if has_known_bases(node.parent.frame()) - else INFERENCE_FAILURE) + confidence = (interfaces.INFERENCE if utils.has_known_bases(node.parent.frame()) + else interfaces.INFERENCE_FAILURE) # check if node is from a method overridden by its ancestor for ancestor in node.parent.frame().ancestors(): if node.name in ancestor and \ @@ -1413,7 +1437,7 @@ def visit_functiondef(self, node): visit_asyncfunctiondef = visit_functiondef def _check_docstring(self, node_type, node, report_missing=True, - confidence=HIGH): + confidence=interfaces.HIGH): """check the node has a non empty docstring""" docstring = node.doc if docstring is None: @@ -1436,7 +1460,7 @@ def _check_docstring(self, node_type, node, report_missing=True, if (node.body and isinstance(node.body[0], astroid.Expr) and isinstance(node.body[0].value, astroid.Call)): # Most likely a string with a format call. Let's see. - func = safe_infer(node.body[0].value.func) + func = utils.safe_infer(node.body[0].value.func) if (isinstance(func, astroid.BoundMethod) and isinstance(func.bound, astroid.Instance)): # Strings in Python 3, others in Python 2. @@ -1459,7 +1483,8 @@ class PassChecker(_BasicChecker): 'Used when a "pass" statement that can be avoided is ' 'encountered.'), } - @check_messages('unnecessary-pass') + + @utils.check_messages('unnecessary-pass') def visit_pass(self, node): if len(node.parent.child_sequence(node)) > 1: self.add_message('unnecessary-pass', node=node) @@ -1480,7 +1505,7 @@ class LambdaForComprehensionChecker(_BasicChecker): {'maxversion': (3, 0)}), } - @check_messages('deprecated-lambda') + @utils.check_messages('deprecated-lambda') def visit_call(self, node): """visit a CallFunc node, check if map or filter are called with a lambda @@ -1489,104 +1514,12 @@ def visit_call(self, node): return if not isinstance(node.args[0], astroid.Lambda): return - infered = safe_infer(node.func) - if (is_builtin_object(infered) + infered = utils.safe_infer(node.func) + if (utils.is_builtin_object(infered) and infered.name in ['map', 'filter']): self.add_message('deprecated-lambda', node=node) -class RecommandationChecker(_BasicChecker): - msgs = {'C0200': ('Consider using enumerate instead of iterating with range and len', - 'consider-using-enumerate', - 'Emitted when code that iterates with range and len is ' - 'encountered. Such code can be simplified by using the ' - 'enumerate builtin.'), - 'C0201': ('Consider iterating the dictionary directly instead of calling .keys()', - 'consider-iterating-dictionary', - 'Emitted when the keys of a dictionary are iterated through the .keys() ' - 'method. It is enough to just iterate through the dictionary itself, as ' - 'in "for key in dictionary".'), - } - - @staticmethod - def _is_builtin(node, function): - inferred = safe_infer(node) - if not inferred: - return False - return is_builtin_object(inferred) and inferred.name == function - - @check_messages('consider-iterating-dictionary') - def visit_call(self, node): - inferred = safe_infer(node.func) - if inferred in (astroid.YES, None): - return - - if not isinstance(inferred, astroid.BoundMethod): - return - if not isinstance(inferred.bound, astroid.Dict) or inferred.name != 'keys': - return - - # Check if the statement is what we're expecting to have. - statement = node.statement() - if isinstance(statement, astroid.Expr): - statement = statement.value - - if isinstance(statement, astroid.For) or is_comprehension(statement): - self.add_message('consider-iterating-dictionary', node=node) - - @check_messages('consider-using-enumerate') - def visit_for(self, node): - """Emit a convention whenever range and len are used for indexing.""" - # Verify that we have a `range(len(...))` call and that the object - # which is iterated is used as a subscript in the body of the for. - - # Is it a proper range call? - if not isinstance(node.iter, astroid.Call): - return - if not self._is_builtin(node.iter.func, 'range'): - return - if len(node.iter.args) != 1: - return - - # Is it a proper len call? - if not isinstance(node.iter.args[0], astroid.Call): - return - second_func = node.iter.args[0].func - if not self._is_builtin(second_func, 'len'): - return - len_args = node.iter.args[0].args - if not len_args or len(len_args) != 1: - return - iterating_object = len_args[0] - if not isinstance(iterating_object, astroid.Name): - return - - # Verify that the body of the for loop uses a subscript - # with the object that was iterated. This uses some heuristics - # in order to make sure that the same object is used in the - # for body. - for child in node.body: - for subscript in child.nodes_of_class(astroid.Subscript): - if not isinstance(subscript.value, astroid.Name): - continue - if not isinstance(subscript.slice, astroid.Index): - continue - if not isinstance(subscript.slice.value, astroid.Name): - continue - if subscript.slice.value.name != node.target.name: - continue - if iterating_object.name != subscript.value.name: - continue - if subscript.value.scope() != node.scope(): - # Ignore this subscript if it's not in the same - # scope. This means that in the body of the for - # loop, another scope was created, where the same - # name for the iterating object was used. - continue - self.add_message('consider-using-enumerate', node=node) - return - - def _is_one_arg_pos_call(call): """Is this a call with exactly 1 argument, where that argument is positional? @@ -1609,7 +1542,7 @@ class ComparisonChecker(_BasicChecker): 'values like True, False or None.'), 'C0122': ('Comparison should be %s', 'misplaced-comparison-constant', - 'Used when the constant is placed on the left side' + 'Used when the constant is placed on the left side ' 'of a comparison. It is usually clearer in intent to ' 'place it in the right hand side of the comparison.'), 'C0123': ('Using type() instead of isinstance() for a typecheck.', @@ -1619,6 +1552,11 @@ class ComparisonChecker(_BasicChecker): 'type(x) == Y, type(x) is Y. Though there are unusual ' 'situations where these give different results.', {'old_names': [('W0154', 'unidiomatic-typecheck')]}), + 'R0123': ('Comparison to literal', + 'literal-comparison', + 'Used when comparing an object to a literal, which is usually ' + 'what you do not want to do, since you can compare to a different ' + 'literal than what was expected altogether.'), } def _check_singleton_comparison(self, singleton, root_node): @@ -1637,6 +1575,23 @@ def _check_singleton_comparison(self, singleton, root_node): node=root_node, args=(None, "'expr is None'")) + def _check_literal_comparison(self, literal, node): + """Check if we compare to a literal, which is usually what we do not want to do.""" + nodes = (astroid.List, + astroid.Tuple, + astroid.Dict, + astroid.Set) + is_other_literal = isinstance(literal, nodes) + is_const = False + if isinstance(literal, astroid.Const): + if literal.value in (True, False, None): + # Not interested in this values. + return + is_const = isinstance(literal.value, (bytes, str, int, float)) + + if is_const or is_other_literal: + self.add_message('literal-comparison', node=node) + def _check_misplaced_constant(self, node, left, right, operator): if isinstance(right, astroid.Const): return @@ -1645,14 +1600,15 @@ def _check_misplaced_constant(self, node, left, right, operator): self.add_message('misplaced-comparison-constant', node=node, args=(suggestion,)) - @check_messages('singleton-comparison', 'misplaced-comparison-constant', - 'unidiomatic-typecheck') + @utils.check_messages('singleton-comparison', 'misplaced-comparison-constant', + 'unidiomatic-typecheck', 'literal-comparison') def visit_compare(self, node): self._check_unidiomatic_typecheck(node) # NOTE: this checker only works with binary comparisons like 'x == 42' # but not 'x == y == 42' if len(node.ops) != 1: return + left = node.left operator, right = node.ops[0] if (operator in ('<', '<=', '>', '>=', '!=', '==') @@ -1664,6 +1620,8 @@ def visit_compare(self, node): self._check_singleton_comparison(left, node) elif isinstance(right, astroid.Const): self._check_singleton_comparison(right, node) + if operator in ('is', 'is not'): + self._check_literal_comparison(right, node) def _check_unidiomatic_typecheck(self, node): operator, right = node.ops[0] @@ -1674,342 +1632,23 @@ def _check_unidiomatic_typecheck(self, node): def _check_type_x_is_y(self, node, left, operator, right): """Check for expressions like type(x) == Y.""" - left_func = safe_infer(left.func) + left_func = utils.safe_infer(left.func) if not (isinstance(left_func, astroid.ClassDef) and left_func.qname() == TYPE_QNAME): return if operator in ('is', 'is not') and _is_one_arg_pos_call(right): - right_func = safe_infer(right.func) + right_func = utils.safe_infer(right.func) if (isinstance(right_func, astroid.ClassDef) and right_func.qname() == TYPE_QNAME): # type(x) == type(a) - right_arg = safe_infer(right.args[0]) + right_arg = utils.safe_infer(right.args[0]) if not isinstance(right_arg, LITERAL_NODE_TYPES): # not e.g. type(x) == type([]) return self.add_message('unidiomatic-typecheck', node=node) -class ElifChecker(BaseTokenChecker): - """Checks needing to distinguish "else if" from "elif" - - This checker mixes the astroid and the token approaches in order to create - knowledge about whether a "else if" node is a true "else if" node, or a - "elif" node. - - The following checks depend on this implementation: - - check for too many nested blocks (if/elif structures aren't considered - as nested) - - to be continued - """ - __implements__ = (ITokenChecker, IAstroidChecker) - name = 'elif' - msgs = {'R0101': ('Too many nested blocks (%s/%s)', - 'too-many-nested-blocks', - 'Used when a function or a method has too many nested ' - 'blocks. This makes the code less understandable and ' - 'maintainable.'), - 'R0102': ('The if statement can be replaced with %s', - 'simplifiable-if-statement', - 'Used when an if statement can be replaced with ' - '\'bool(test)\'. '), - } - options = (('max-nested-blocks', - {'default' : 5, 'type' : 'int', 'metavar' : '', - 'help': 'Maximum number of nested blocks for function / ' - 'method body'} - ),) - - def __init__(self, linter=None): - BaseTokenChecker.__init__(self, linter) - self._init() - - def _init(self): - self._nested_blocks = [] - self._elifs = [] - self._if_counter = 0 - self._nested_blocks_msg = None - - @staticmethod - def _is_bool_const(node): - return (isinstance(node.value, astroid.Const) - and isinstance(node.value.value, bool)) - - def _is_actual_elif(self, node): - """Check if the given node is an actual elif - - This is a problem we're having with the builtin ast module, - which splits `elif` branches into a separate if statement. - Unfortunately we need to know the exact type in certain - cases. - """ - - if isinstance(node.parent, astroid.If): - orelse = node.parent.orelse - # current if node must directly follow a "else" - if orelse and orelse == [node]: - if self._elifs[self._if_counter]: - return True - return False - - def _check_simplifiable_if(self, node): - """Check if the given if node can be simplified. - - The if statement can be reduced to a boolean expression - in some cases. For instance, if there are two branches - and both of them return a boolean value that depends on - the result of the statement's test, then this can be reduced - to `bool(test)` without losing any functionality. - """ - - if self._is_actual_elif(node): - # Not interested in if statements with multiple branches. - return - if len(node.orelse) != 1 or len(node.body) != 1: - return - - # Check if both branches can be reduced. - first_branch = node.body[0] - else_branch = node.orelse[0] - if isinstance(first_branch, astroid.Return): - if not isinstance(else_branch, astroid.Return): - return - first_branch_is_bool = self._is_bool_const(first_branch) - else_branch_is_bool = self._is_bool_const(else_branch) - reduced_to = "'return bool(test)'" - elif isinstance(first_branch, astroid.Assign): - if not isinstance(else_branch, astroid.Assign): - return - first_branch_is_bool = self._is_bool_const(first_branch) - else_branch_is_bool = self._is_bool_const(else_branch) - reduced_to = "'var = bool(test)'" - else: - return - - if not first_branch_is_bool or not else_branch_is_bool: - return - if not first_branch.value.value: - # This is a case that can't be easily simplified and - # if it can be simplified, it will usually result in a - # code that's harder to understand and comprehend. - # Let's take for instance `arg and arg <= 3`. This could theoretically be - # reduced to `not arg or arg > 3`, but the net result is that now the - # condition is harder to understand, because it requires understanding of - # an extra clause: - # * first, there is the negation of truthness with `not arg` - # * the second clause is `arg > 3`, which occurs when arg has a - # a truth value, but it implies that `arg > 3` is equivalent - # with `arg and arg > 3`, which means that the user must - # think about this assumption when evaluating `arg > 3`. - # The original form is easier to grasp. - return - - self.add_message('simplifiable-if-statement', node=node, - args=(reduced_to, )) - - def process_tokens(self, tokens): - # Process tokens and look for 'if' or 'elif' - for _, token, _, _, _ in tokens: - if token == 'elif': - self._elifs.append(True) - elif token == 'if': - self._elifs.append(False) - - def leave_module(self, _): - self._init() - - @check_messages('too-many-nested-blocks') - def visit_tryexcept(self, node): - self._check_nested_blocks(node) - - visit_tryfinally = visit_tryexcept - visit_while = visit_tryexcept - visit_for = visit_while - - def visit_ifexp(self, _): - self._if_counter += 1 - - def visit_comprehension(self, node): - self._if_counter += len(node.ifs) - - @check_messages('too-many-nested-blocks', 'simplifiable-if-statement') - def visit_if(self, node): - self._check_simplifiable_if(node) - self._check_nested_blocks(node) - self._if_counter += 1 - - @check_messages('too-many-nested-blocks') - def leave_functiondef(self, _): - # new scope = reinitialize the stack of nested blocks - self._nested_blocks = [] - # if there is a waiting message left, send it - if self._nested_blocks_msg: - self.add_message('too-many-nested-blocks', - node=self._nested_blocks_msg[0], - args=self._nested_blocks_msg[1]) - self._nested_blocks_msg = None - - def _check_nested_blocks(self, node): - """Update and check the number of nested blocks - """ - # only check block levels inside functions or methods - if not isinstance(node.scope(), astroid.FunctionDef): - return - # messages are triggered on leaving the nested block. Here we save the - # stack in case the current node isn't nested in the previous one - nested_blocks = self._nested_blocks[:] - if node.parent == node.scope(): - self._nested_blocks = [node] - else: - # go through ancestors from the most nested to the less - for ancestor_node in reversed(self._nested_blocks): - if ancestor_node == node.parent: - break - self._nested_blocks.pop() - # if the node is a elif, this should not be another nesting level - if isinstance(node, astroid.If) and self._elifs[self._if_counter]: - if self._nested_blocks: - self._nested_blocks.pop() - self._nested_blocks.append(node) - # send message only once per group of nested blocks - if len(nested_blocks) > self.config.max_nested_blocks: - if len(nested_blocks) > len(self._nested_blocks): - self.add_message('too-many-nested-blocks', node=nested_blocks[0], - args=(len(nested_blocks), - self.config.max_nested_blocks)) - self._nested_blocks_msg = None - else: - # if time has not come yet to send the message (ie the stack of - # nested nodes is still increasing), save it in case the - # current node is the last one of the function - self._nested_blocks_msg = (self._nested_blocks[0], - (len(self._nested_blocks), - self.config.max_nested_blocks)) - -class NotChecker(_BasicChecker): - """checks for too many not in comparison expressions - - - "not not" should trigger a warning - - "not" followed by a comparison should trigger a warning - """ - msgs = {'C0113': ('Consider changing "%s" to "%s"', - 'unneeded-not', - 'Used when a boolean expression contains an unneeded ' - 'negation.'), - } - - reverse_op = {'<': '>=', '<=': '>', '>': '<=', '>=': '<', '==': '!=', - '!=': '==', 'in': 'not in', 'is': 'is not'} - # sets are not ordered, so for example "not set(LEFT_VALS) <= set(RIGHT_VALS)" is - # not equivalent to "set(LEFT_VALS) > set(RIGHT_VALS)" - skipped_nodes = (astroid.Set, ) - # 'builtins' py3, '__builtin__' py2 - skipped_classnames = ['%s.%s' % (six.moves.builtins.__name__, qname) - for qname in ('set', 'frozenset')] - - @check_messages('unneeded-not') - def visit_unaryop(self, node): - if node.op != 'not': - return - operand = node.operand - - if isinstance(operand, astroid.UnaryOp) and operand.op == 'not': - self.add_message('unneeded-not', node=node, - args=(node.as_string(), - operand.operand.as_string())) - elif isinstance(operand, astroid.Compare): - left = operand.left - # ignore multiple comparisons - if len(operand.ops) > 1: - return - operator, right = operand.ops[0] - if operator not in self.reverse_op: - return - # Ignore __ne__ as function of __eq__ - frame = node.frame() - if frame.name == '__ne__' and operator == '==': - return - for _type in (_node_type(left), _node_type(right)): - if not _type: - return - if isinstance(_type, self.skipped_nodes): - return - if (isinstance(_type, astroid.Instance) and - _type.qname() in self.skipped_classnames): - return - suggestion = '%s %s %s' % (left.as_string(), - self.reverse_op[operator], - right.as_string()) - self.add_message('unneeded-not', node=node, - args=(node.as_string(), suggestion)) - - -class MultipleTypesChecker(BaseChecker): - """Checks for variable type redefinitions (NoneType excepted) - - At a function, method, class or module scope - - This rule could be improved: - - Currently, if an attribute is set to different types in 2 methods of a - same class, it won't be detected (see functional test) - - One could improve the support for inference on assignment with tuples, - ifexpr, etc. Also it would be great to have support for inference on - str.split() - """ - __implements__ = IAstroidChecker - - name = 'multiple_types' - msgs = {'R0204': ('Redefinition of %s type from %s to %s', - 'redefined-variable-type', - 'Used when the type of a variable changes inside a ' - 'method or a function.' - ), - } - - def visit_classdef(self, _): - self._assigns.append({}) - - @check_messages('redefined-variable-type') - def leave_classdef(self, _): - self._check_and_add_messages() - - visit_functiondef = visit_classdef - leave_functiondef = leave_module = leave_classdef - - def visit_module(self, _): - self._assigns = [{}] - - def _check_and_add_messages(self): - assigns = self._assigns.pop() - for name, args in assigns.items(): - if len(args) <= 1: - continue - _, orig_type = args[0] - # Check if there is a type in the following nodes that would be - # different from orig_type. - for redef_node, redef_type in args[1:]: - if redef_type != orig_type: - orig_type = orig_type.replace(BUILTINS + ".", '') - redef_type = redef_type.replace(BUILTINS + ".", '') - self.add_message('redefined-variable-type', node=redef_node, - args=(name, orig_type, redef_type)) - break - - def visit_assign(self, node): - # we don't handle multiple assignment nor slice assignment - target = node.targets[0] - if isinstance(target, (astroid.Tuple, astroid.Subscript)): - return - # ignore NoneType - if _is_none(node): - return - _type = _node_type(node.value) - if _type: - self._assigns[-1].setdefault(target.as_string(), []).append( - (node, _type.pytype())) - - def register(linter): """required method to auto register this checker""" linter.register_checker(BasicErrorChecker(linter)) @@ -2019,7 +1658,3 @@ def register(linter): linter.register_checker(PassChecker(linter)) linter.register_checker(LambdaForComprehensionChecker(linter)) linter.register_checker(ComparisonChecker(linter)) - linter.register_checker(NotChecker(linter)) - linter.register_checker(RecommandationChecker(linter)) - linter.register_checker(ElifChecker(linter)) - linter.register_checker(MultipleTypesChecker(linter)) diff --git a/pymode/libs/pylint/checkers/classes.py b/pymode/libs/pylint/checkers/classes.py index 1b1ff8ce..9975220b 100644 --- a/pymode/libs/pylint/checkers/classes.py +++ b/pymode/libs/pylint/checkers/classes.py @@ -1,5 +1,11 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# -*- coding: utf-8 -*- +# Copyright (c) 2006-2016 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2012, 2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2016 Moises Lopez - https://www.vauxoo.com/ +# Copyright (c) 2016 Łukasz Rogalski + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -7,14 +13,15 @@ """ from __future__ import generators +import collections import sys -from collections import defaultdict import six import astroid from astroid.bases import Generator, BUILTINS from astroid.exceptions import InconsistentMroError, DuplicateBasesError +from astroid import decorators from astroid import objects from astroid.scoped_nodes import function_to_method from pylint.interfaces import IAstroidChecker @@ -25,23 +32,170 @@ is_attr_protected, node_frame_class, is_builtin_object, decorated_with_property, unimplemented_abstract_methods, decorated_with, class_is_abstract, - safe_infer, has_known_bases) -from pylint.utils import deprecated_option, get_global_option + safe_infer, has_known_bases, is_iterable, is_comprehension) +from pylint.utils import get_global_option if sys.version_info >= (3, 0): NEXT_METHOD = '__next__' else: NEXT_METHOD = 'next' -ITER_METHODS = ('__iter__', '__getitem__') INVALID_BASE_CLASSES = {'bool', 'range', 'slice', 'memoryview'} -def _get_method_args(method): - args = method.args.args +# Dealing with useless override detection, with regard +# to parameters vs arguments + +_CallSignature = collections.namedtuple( + '_CallSignature', 'args kws starred_args starred_kws') +_ParameterSignature = collections.namedtuple( + '_ParameterSignature', + 'args kwonlyargs varargs kwargs', +) + + +def _signature_from_call(call): + kws = {} + args = [] + starred_kws = [] + starred_args = [] + for keyword in call.keywords or []: + arg, value = keyword.arg, keyword.value + if arg is None and isinstance(value, astroid.Name): + # Starred node and we are interested only in names, + # otherwise some transformation might occur for the parameter. + starred_kws.append(value.name) + elif isinstance(value, astroid.Name): + kws[arg] = value.name + else: + kws[arg] = None + + for arg in call.args: + if isinstance(arg, astroid.Starred) and isinstance(arg.value, astroid.Name): + # Positional variadic and a name, otherwise some transformation + # might have occurred. + starred_args.append(arg.value.name) + elif isinstance(arg, astroid.Name): + args.append(arg.name) + else: + args.append(None) + + return _CallSignature(args, kws, starred_args, starred_kws) + + +def _signature_from_arguments(arguments): + kwarg = arguments.kwarg + vararg = arguments.vararg + args = [arg.name for arg in arguments.args if arg.name != 'self'] + kwonlyargs = [arg.name for arg in arguments.kwonlyargs] + return _ParameterSignature(args, kwonlyargs, vararg, kwarg) + + +def _definition_equivalent_to_call(definition, call): + '''Check if a definition signature is equivalent to a call.''' + if definition.kwargs: + same_kw_variadics = definition.kwargs in call.starred_kws + else: + same_kw_variadics = not call.starred_kws + if definition.varargs: + same_args_variadics = definition.varargs in call.starred_args + else: + same_args_variadics = not call.starred_args + same_kwonlyargs = all(kw in call.kws for kw in definition.kwonlyargs) + same_args = definition.args == call.args + + no_additional_kwarg_arguments = True + if call.kws: + for keyword in call.kws: + is_arg = keyword in call.args + is_kwonly = keyword in definition.kwonlyargs + if not is_arg and not is_kwonly: + # Maybe this argument goes into **kwargs, + # or it is an extraneous argument. + # In any case, the signature is different than + # the call site, which stops our search. + no_additional_kwarg_arguments = False + break + + return all(( + same_args, + same_kwonlyargs, + same_args_variadics, + same_kw_variadics, + no_additional_kwarg_arguments, + )) + +# Deal with parameters overridding in two methods. + +def _positional_parameters(method): + positional = method.args.args if method.type in ('classmethod', 'method'): - return len(args) - 1 - return len(args) + positional = positional[1:] + return positional + + +def _has_different_parameters(original, overridden, dummy_parameter_regex): + zipped = six.moves.zip_longest(original, overridden) + for original_param, overridden_param in zipped: + params = (original_param, overridden_param) + if not all(params): + return True + + names = [param.name for param in params] + if any(map(dummy_parameter_regex.match, names)): + continue + if original_param.name != overridden_param.name: + return True + return False + + +def _different_parameters(original, overridden, dummy_parameter_regex): + """Determine if the two methods have different parameters + + They are considered to have different parameters if: + + * they have different positional parameters, including different names + + * one of the methods is having variadics, while the other is not + + * they have different keyword only parameters. + + """ + original_parameters = _positional_parameters(original) + overridden_parameters = _positional_parameters(overridden) + + different_positional = _has_different_parameters( + original_parameters, + overridden_parameters, + dummy_parameter_regex) + different_kwonly = _has_different_parameters( + original.args.kwonlyargs, + overridden.args.kwonlyargs, + dummy_parameter_regex) + if original.name in PYMETHODS: + # Ignore the difference for special methods. If the parameter + # numbers are different, then that is going to be caught by + # unexpected-special-method-signature. + # If the names are different, it doesn't matter, since they can't + # be used as keyword arguments anyway. + different_positional = different_kwonly = False + + # Both or none should have extra variadics, otherwise the method + # loses or gains capabilities that are not reflected into the parent method, + # leading to potential inconsistencies in the code. + different_kwarg = sum( + 1 for param in (original.args.kwarg, overridden.args.kwarg) + if not param) == 1 + different_vararg = sum( + 1 for param in (original.args.vararg, overridden.args.vararg) + if not param) == 1 + + return any(( + different_positional, + different_kwarg, + different_vararg, + different_kwonly + )) def _is_invalid_base_class(cls): @@ -122,6 +276,7 @@ def _is_attribute_property(name, klass): return True return False + def _has_bare_super_call(fundef_node): for call in fundef_node.nodes_of_class(astroid.Call): func = call.func @@ -131,6 +286,7 @@ def _has_bare_super_call(fundef_node): return True return False + def _safe_infer_call_result(node, caller, context=None): """ Safely infer the return value of a function. @@ -153,6 +309,7 @@ def _safe_infer_call_result(node, caller, context=None): except StopIteration: return value + MSGS = { 'F0202': ('Unable to check methods signature (%s / %s)', 'method-check-failed', @@ -197,7 +354,7 @@ def _safe_infer_call_result(node, caller, context=None): 'from regular instance methods.'), 'C0203': ('Metaclass method %s should have %s as first argument', 'bad-mcs-method-argument', - 'Used when a metaclass method has a first agument named ' + 'Used when a metaclass method has a first argument named ' 'differently than the value specified in valid-classmethod-first' '-arg option (default to "cls"), recommended to easily ' 'differentiate them from regular instance methods.'), @@ -219,7 +376,7 @@ def _safe_infer_call_result(node, caller, context=None): 'Used when a method doesn\'t use its bound instance, and so could ' 'be written as a function.' ), - 'W0221': ('Arguments number differs from %s %r method', + 'W0221': ('Parameters differ from %s %r method', 'arguments-differ', 'Used when a method has a different number of arguments than in ' 'the implemented interface or in an overridden method.'), @@ -244,6 +401,11 @@ def _safe_infer_call_result(node, caller, context=None): 'non-parent-init-called', 'Used when an __init__ method is called on a class which is not ' 'in the direct ancestors for the analysed class.'), + 'W0235': ('Useless super delegation in method %r', + 'useless-super-delegation', + 'Used whenever we can detect that an overridden method is useless, ' + 'relying on super() delegation to do the same thing as another method ' + 'from the MRO.'), 'E0236': ('Invalid object %r in __slots__, must contain ' 'only non empty strings', 'invalid-slots-object', @@ -262,7 +424,7 @@ def _safe_infer_call_result(node, caller, context=None): 'class.'), 'E0240': ('Inconsistent method resolution order for class %r', 'inconsistent-mro', - 'Used when a class has an inconsistent method resolutin order.'), + 'Used when a class has an inconsistent method resolution order.'), 'E0241': ('Duplicate bases for class %r', 'duplicate-bases', 'Used when a class has duplicate bases.'), @@ -274,9 +436,35 @@ def _safe_infer_call_result(node, caller, context=None): 'no-staticmethod-decorator', 'Used when a static method is defined without using the decorator ' 'syntax.'), + 'C0205': ('Class __slots__ should be a non-string iterable', + 'single-string-used-for-slots', + 'Used when a class __slots__ is a simple string, rather ' + 'than an iterable.'), } +class ScopeAccessMap(object): + """Store the accessed variables per scope.""" + + def __init__(self): + self._scopes = collections.defaultdict( + lambda: collections.defaultdict(list) + ) + + def set_accessed(self, node): + """Set the given node as accessed.""" + + frame = node_frame_class(node) + if frame is None: + # The node does not live in a class. + return + self._scopes[frame][node.attrname].append(node) + + def accessed(self, scope): + """Get the accessed variables for the given scope.""" + return self._scopes.get(scope, {}) + + class ClassChecker(BaseChecker): """checks for : * methods without self as first argument @@ -294,13 +482,7 @@ class ClassChecker(BaseChecker): msgs = MSGS priority = -2 # configuration options - options = (('ignore-iface-methods', - deprecated_option(opt_type="csv", - help_msg="This is deprecated, because " - "it is not used anymore.", - deprecation_msg="This option %r will be " - "removed in Pylint 2.0")), - ('defining-attr-methods', + options = (('defining-attr-methods', {'default' : ('__init__', '__new__', 'setUp'), 'type' : 'csv', 'metavar' : '', @@ -334,14 +516,23 @@ class ClassChecker(BaseChecker): def __init__(self, linter=None): BaseChecker.__init__(self, linter) - self._accessed = [] + self._accessed = ScopeAccessMap() self._first_attrs = [] self._meth_could_be_func = None + @decorators.cachedproperty + def _dummy_rgx(self): + return get_global_option( + self, 'dummy-variables-rgx', default=None) + + @decorators.cachedproperty + def _ignore_mixin(self): + return get_global_option( + self, 'ignore-mixin-members', default=True) + def visit_classdef(self, node): """init visit variable _accessed """ - self._accessed.append(defaultdict(list)) self._check_bases_classes(node) # if not an exception or a metaclass if node.type == 'class' and has_known_bases(node): @@ -389,15 +580,13 @@ def leave_classdef(self, cnode): access to existent members """ # check access to existent members on non metaclass classes - ignore_mixins = get_global_option(self, 'ignore-mixin-members', - default=True) - if ignore_mixins and cnode.name[-5:].lower() == 'mixin': + if self._ignore_mixin and cnode.name[-5:].lower() == 'mixin': # We are in a mixin class. No need to try to figure out if # something is missing, since it is most likely that it will # miss. return - accessed = self._accessed.pop() + accessed = self._accessed.accessed(cnode) if cnode.type != 'metaclass': self._check_accessed_members(cnode, accessed) # checks attributes are defined in an allowed method such as __init__ @@ -449,6 +638,9 @@ def visit_functiondef(self, node): # ignore actual functions if not node.is_method(): return + + self._check_useless_super_delegation(node) + klass = node.parent.frame() self._meth_could_be_func = True # check first argument is self if this is actually a method @@ -496,23 +688,87 @@ def visit_functiondef(self, node): visit_asyncfunctiondef = visit_functiondef + def _check_useless_super_delegation(self, function): + '''Check if the given function node is an useless method override + + We consider it *useless* if it uses the super() builtin, but having + nothing additional whatsoever than not implementing the method at all. + If the method uses super() to delegate an operation to the rest of the MRO, + and if the method called is the same as the current one, the arguments + passed to super() are the same as the parameters that were passed to + this method, then the method could be removed altogether, by letting + other implementation to take precedence. + ''' + + if not function.is_method(): + return + + if function.decorators: + # With decorators is a change of use + return + + body = function.body + if len(body) != 1: + # Multiple statements, which means this overridden method + # could do multiple things we are not aware of. + return + + statement = body[0] + if not isinstance(statement, (astroid.Expr, astroid.Return)): + # Doing something else than what we are interested into. + return + + call = statement.value + if not isinstance(call, astroid.Call): + return + if not isinstance(call.func, astroid.Attribute): + # Not a super() attribute access. + return + + # Should be a super call. + try: + super_call = next(call.func.expr.infer()) + except astroid.InferenceError: + return + else: + if not isinstance(super_call, objects.Super): + return + + # The name should be the same. + if call.func.attrname != function.name: + return + + # Should be a super call with the MRO pointer being the current class + # and the type being the current instance. + current_scope = function.parent.scope() + if super_call.mro_pointer != current_scope: + return + if not isinstance(super_call.type, astroid.Instance): + return + if super_call.type.name != current_scope.name: + return + + # Detect if the parameters are the same as the call's arguments. + params = _signature_from_arguments(function.args) + args = _signature_from_call(call) + if _definition_equivalent_to_call(params, args): + self.add_message('useless-super-delegation', node=function, + args=(function.name, )) + def _check_slots(self, node): if '__slots__' not in node.locals: return for slots in node.igetattr('__slots__'): # check if __slots__ is a valid type - for meth in ITER_METHODS: - try: - slots.getattr(meth) - break - except astroid.NotFoundError: - continue - else: + if slots is astroid.YES: + continue + if not is_iterable(slots) and not is_comprehension(slots): self.add_message('invalid-slots', node=node) continue if isinstance(slots, astroid.Const): # a string, ignore the following checks + self.add_message('single-string-used-for-slots', node=node) continue if not hasattr(slots, 'itered'): # we can't obtain the values, maybe a .deque? @@ -572,10 +828,9 @@ def visit_attribute(self, node): class member from outside its class (but ignore __special__ methods) """ - attrname = node.attrname # Check self - if self.is_first_attr(node): - self._accessed[-1][attrname].append(node) + if self._uses_mandatory_method_param(node): + self._accessed.set_accessed(node) return if not self.linter.is_message_enabled('protected-access'): return @@ -583,8 +838,9 @@ class member from outside its class (but ignore __special__ self._check_protected_attribute_access(node) def visit_assignattr(self, node): - if isinstance(node.assign_type(), astroid.AugAssign) and self.is_first_attr(node): - self._accessed[-1][node.attrname].append(node) + if (isinstance(node.assign_type(), astroid.AugAssign) and + self._uses_mandatory_method_param(node)): + self._accessed.set_accessed(node) self._check_in_slots(node) def _check_in_slots(self, node): @@ -630,7 +886,7 @@ def visit_assign(self, assign_node): if not isinstance(node, astroid.AssignAttr): return - if self.is_first_attr(node): + if self._uses_mandatory_method_param(node): return self._check_protected_attribute_access(node) @@ -702,6 +958,10 @@ def _check_protected_attribute_access(self, node): node.expr.func.name == 'super': return + # If the expression begins with a call to type(self), that's ok. + if self._is_type_self_call(node.expr): + return + # We are in a class, one remaining valid cases, Klass._attr inside # Klass if not (callee == klass.name or callee in klass.basenames): @@ -721,6 +981,12 @@ def _check_protected_attribute_access(self, node): self.add_message('protected-access', node=node, args=attrname) + def _is_type_self_call(self, expr): + return (isinstance(expr, astroid.Call) and + isinstance(expr.func, astroid.Name) and + expr.func.name == 'type' and len(expr.args) == 1 and + self._is_mandatory_method_param(expr.args[0])) + def visit_name(self, node): """check if the name handle an access to a class member if so, register it @@ -932,16 +1198,14 @@ def _check_signature(self, method1, refmethod, class_type, cls): args=(method1, refmethod), node=method1) return - instance = cls.instanciate_class() + instance = cls.instantiate_class() method1 = function_to_method(method1, instance) refmethod = function_to_method(refmethod, instance) # Don't care about functions with unknown argument (builtins). if method1.args.args is None or refmethod.args.args is None: return - # If we use *args, **kwargs, skip the below checks. - if method1.args.vararg or method1.args.kwarg: - return + # Ignore private to class methods. if is_attr_private(method1.name): return @@ -953,9 +1217,9 @@ def _check_signature(self, method1, refmethod, class_type, cls): decorator.attrname == 'setter'): return - method1_args = _get_method_args(method1) - refmethod_args = _get_method_args(refmethod) - if method1_args != refmethod_args: + if _different_parameters( + refmethod, method1, + dummy_parameter_regex=self._dummy_rgx): self.add_message('arguments-differ', args=(class_type, method1.name), node=method1) @@ -964,12 +1228,20 @@ def _check_signature(self, method1, refmethod, class_type, cls): args=(class_type, method1.name), node=method1) - def is_first_attr(self, node): + def _uses_mandatory_method_param(self, node): """Check that attribute lookup name use first attribute variable name - (self for method, cls for classmethod and mcs for metaclass). + + Name is `self` for method, `cls` for classmethod and `mcs` for metaclass. + """ + return self._is_mandatory_method_param(node.expr) + + def _is_mandatory_method_param(self, node): + """Check if astroid.Name corresponds to first attribute variable name + + Name is `self` for method, `cls` for classmethod and `mcs` for metaclass. """ - return self._first_attrs and isinstance(node.expr, astroid.Name) and \ - node.expr.name == self._first_attrs[-1] + return (self._first_attrs and isinstance(node, astroid.Name) + and node.name == self._first_attrs[-1]) class SpecialMethodsChecker(BaseChecker): @@ -1018,8 +1290,8 @@ def _check_unexpected_method_signature(self, node): if expected_params is None: # This can support a variable number of parameters. return - if not len(node.args.args) and not node.args.vararg: - # Method has no parameter, will be catched + if not node.args.args and not node.args.vararg: + # Method has no parameter, will be caught # by no-method-argument. return @@ -1090,7 +1362,7 @@ def _check_iter(self, node): def _check_len(self, node): inferred = _safe_infer_call_result(node, node) - if inferred is None or inferred is astroid.YES: + if not inferred: return if not isinstance(inferred, astroid.Const): diff --git a/pymode/libs/pylint/checkers/design_analysis.py b/pymode/libs/pylint/checkers/design_analysis.py index 6fca4a38..c34ec4dc 100644 --- a/pymode/libs/pylint/checkers/design_analysis.py +++ b/pymode/libs/pylint/checkers/design_analysis.py @@ -1,21 +1,20 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2009-2010, 2012-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """check for signs of poor design""" -import re from collections import defaultdict from astroid import If, BoolOp +from astroid import decorators from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker from pylint.checkers.utils import check_messages - -# regexp for ignored argument name -IGNORED_ARGUMENT_NAMES = re.compile('_.*') +from pylint import utils MSGS = { @@ -93,12 +92,6 @@ class MisdesignChecker(BaseChecker): {'default' : 5, 'type' : 'int', 'metavar' : '', 'help': 'Maximum number of arguments for function / method'} ), - ('ignored-argument-names', - {'default' : IGNORED_ARGUMENT_NAMES, - 'type' :'regexp', 'metavar' : '', - 'help' : 'Argument names that match this expression will be ' - 'ignored. Default to name with leading underscore'} - ), ('max-locals', {'default' : 15, 'type' : 'int', 'metavar' : '', 'help': 'Maximum number of locals for function / method body'} @@ -166,19 +159,20 @@ def open(self): self._returns = [] self._branches = defaultdict(int) + @decorators.cachedproperty + def _ignored_argument_names(self): + return utils.get_global_option(self, 'ignored-argument-names', default=None) + @check_messages('too-many-ancestors', 'too-many-instance-attributes', 'too-few-public-methods', 'too-many-public-methods') def visit_classdef(self, node): """check size of inheritance hierarchy and number of instance attributes """ - # Is the total inheritance hierarchy is 7 or less? nb_parents = len(list(node.ancestors())) if nb_parents > self.config.max_parents: self.add_message('too-many-ancestors', node=node, args=(nb_parents, self.config.max_parents)) - # Does the class contain less than 20 attributes for - # non-GUI classes (40 for GUI)? - # FIXME detect gui classes + if len(node.instance_attrs) > self.config.max_attributes: self.add_message('too-many-instance-attributes', node=node, args=(len(node.instance_attrs), @@ -226,12 +220,14 @@ def visit_functiondef(self, node): self._returns.append(0) # check number of arguments args = node.args.args + ignored_argument_names = self._ignored_argument_names if args is not None: - ignored_args_num = len( - [arg for arg in args - if self.config.ignored_argument_names.match(arg.name)]) + ignored_args_num = 0 + if ignored_argument_names: + ignored_args_num = sum(1 for arg in args if ignored_argument_names.match(arg.name)) + argnum = len(args) - ignored_args_num - if argnum > self.config.max_args: + if argnum > self.config.max_args: self.add_message('too-many-arguments', node=node, args=(len(args), self.config.max_args)) else: diff --git a/pymode/libs/pylint/checkers/exceptions.py b/pymode/libs/pylint/checkers/exceptions.py index 57306ede..dde3ae62 100644 --- a/pymode/libs/pylint/checkers/exceptions.py +++ b/pymode/libs/pylint/checkers/exceptions.py @@ -1,10 +1,13 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2011, 2013-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2015 Steven Myint + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING -"""exceptions handling (raising, catching, exceptions classes) checker -""" +"""Checks for various exception related errors.""" + import inspect import sys @@ -12,15 +15,9 @@ from six.moves import builtins import astroid -from pylint.checkers import BaseChecker -from pylint.checkers.utils import ( - is_raising, - check_messages, - inherit_from_std_ex, - EXCEPTIONS_MODULE, - safe_infer, - has_known_bases) -from pylint.interfaces import IAstroidChecker +from pylint import checkers +from pylint.checkers import utils +from pylint import interfaces def _builtin_exceptions(): @@ -40,7 +37,7 @@ def _annotated_unpack_infer(stmt, context=None): """ if isinstance(stmt, (astroid.List, astroid.Tuple)): for elt in stmt.elts: - inferred = safe_infer(elt) + inferred = utils.safe_infer(elt) if inferred and inferred is not astroid.YES: yield elt, inferred return @@ -59,7 +56,7 @@ def _annotated_unpack_infer(stmt, context=None): 'bad-except-order', 'Used when except clauses are not in the correct order (from the ' 'more specific to the more generic). If you don\'t fix the order, ' - 'some exceptions may not be catched by the most specific handler.'), + 'some exceptions may not be caught by the most specific handler.'), 'E0702': ('Raising %s while only classes or instances are allowed', 'raising-bad-type', 'Used when something which is neither a class, an instance or a \ @@ -87,10 +84,10 @@ def _annotated_unpack_infer(stmt, context=None): 'notimplemented-raised', 'Used when NotImplemented is raised instead of \ NotImplementedError'), - 'E0712': ('Catching an exception which doesn\'t inherit from BaseException: %s', + 'E0712': ('Catching an exception which doesn\'t inherit from Exception: %s', 'catching-non-exception', 'Used when a class which doesn\'t inherit from \ - BaseException is used as an exception in an except clause.'), + Exception is used as an exception in an except clause.'), 'W0702': ('No exception type(s) specified', 'bare-except', 'Used when an except clause doesn\'t specify exceptions type to \ @@ -116,20 +113,107 @@ def _annotated_unpack_infer(stmt, context=None): } -class ExceptionsChecker(BaseChecker): - """checks for - * excepts without exception filter - * type of raise argument : string, Exceptions, other values - """ +class BaseVisitor(object): + """Base class for visitors defined in this module.""" + + def __init__(self, checker, node): + self._checker = checker + self._node = node + + def visit(self, node): + name = node.__class__.__name__.lower() + dispatch_meth = getattr(self, 'visit_' + name, None) + if dispatch_meth: + dispatch_meth(node) + else: + self.visit_default(node) + + def visit_default(self, node): # pylint: disable=unused-argument + """Default implementation for all the nodes.""" + + +class ExceptionRaiseRefVisitor(BaseVisitor): + """Visit references (anything that is not an AST leaf).""" + + def visit_name(self, name): + if name.name == 'NotImplemented': + self._checker.add_message( + 'notimplemented-raised', + node=self._node) + + def visit_call(self, call): + if isinstance(call.func, astroid.Name): + self.visit_name(call.func) + + +class ExceptionRaiseLeafVisitor(BaseVisitor): + """Visitor for handling leaf kinds of a raise value.""" + + def visit_const(self, const): + if not isinstance(const.value, str): + # raising-string will be emitted from python3 porting checker. + self._checker.add_message('raising-bad-type', node=self._node, + args=const.value.__class__.__name__) + + def visit_instance(self, instance): + # pylint: disable=protected-access + cls = instance._proxied + self.visit_classdef(cls) + + # Exception instances have a particular class type + visit_exceptioninstance = visit_instance + + def visit_classdef(self, cls): + if (not utils.inherit_from_std_ex(cls) and + utils.has_known_bases(cls)): + if cls.newstyle: + self._checker.add_message('raising-non-exception', node=self._node) + else: + self._checker.add_message('nonstandard-exception', node=self._node) + + def visit_tuple(self, tuple_node): + if PY3K or not tuple_node.elts: + self._checker.add_message('raising-bad-type', + node=self._node, + args='tuple') + return + + # On Python 2, using the following is not an error: + # raise (ZeroDivisionError, None) + # raise (ZeroDivisionError, ) + # What's left to do is to check that the first + # argument is indeed an exception. Verifying the other arguments + # is not the scope of this check. + first = tuple_node.elts[0] + inferred = utils.safe_infer(first) + if not inferred or inferred is astroid.Uninferable: + return + + if (isinstance(inferred, astroid.Instance) + and inferred.__class__.__name__ != 'Instance'): + # TODO: explain why + self.visit_default(tuple_node) + else: + self.visit(inferred) + + def visit_default(self, node): + name = getattr(node, 'name', node.__class__.__name__) + self._checker.add_message('raising-bad-type', + node=self._node, + args=name) - __implements__ = IAstroidChecker + +class ExceptionsChecker(checkers.BaseChecker): + """Exception related checks.""" + + __implements__ = interfaces.IAstroidChecker name = 'exceptions' msgs = MSGS priority = -4 options = (('overgeneral-exceptions', {'default' : OVERGENERAL_EXCEPTIONS, - 'type' :'csv', 'metavar' : '', + 'type' : 'csv', 'metavar' : '', 'help' : 'Exceptions that will emit a warning ' 'when being caught. Defaults to "%s"' % ( ', '.join(OVERGENERAL_EXCEPTIONS),)} @@ -137,29 +221,30 @@ class ExceptionsChecker(BaseChecker): ) def open(self): - self.builtin_exceptions = _builtin_exceptions() + self._builtin_exceptions = _builtin_exceptions() super(ExceptionsChecker, self).open() - @check_messages('nonstandard-exception', 'misplaced-bare-raise', - 'raising-bad-type', 'raising-non-exception', - 'notimplemented-raised', 'bad-exception-context') + @utils.check_messages('nonstandard-exception', 'misplaced-bare-raise', + 'raising-bad-type', 'raising-non-exception', + 'notimplemented-raised', 'bad-exception-context') def visit_raise(self, node): - """visit raise possibly inferring value""" if node.exc is None: self._check_misplaced_bare_raise(node) return + if PY3K and node.cause: self._check_bad_exception_context(node) expr = node.exc - if self._check_raise_value(node, expr): - return - else: - try: - value = next(astroid.unpack_infer(expr)) - except astroid.InferenceError: - return - self._check_raise_value(node, value) + try: + inferred_value = next(expr.infer()) + except astroid.InferenceError: + inferred_value = None + + ExceptionRaiseRefVisitor(self, node).visit(expr) + + if inferred_value: + ExceptionRaiseLeafVisitor(self, node).visit(inferred_value) def _check_misplaced_bare_raise(self, node): # Filter out if it's present in __exit__. @@ -177,8 +262,7 @@ def _check_misplaced_bare_raise(self, node): current = current.parent expected = (astroid.ExceptHandler,) - if (not current - or not isinstance(current.parent, expected)): + if not current or not isinstance(current.parent, expected): self.add_message('misplaced-bare-raise', node=node) def _check_bad_exception_context(self, node): @@ -186,84 +270,27 @@ def _check_bad_exception_context(self, node): An exception context can be only `None` or an exception. """ - cause = safe_infer(node.cause) + cause = utils.safe_infer(node.cause) if cause in (astroid.YES, None): return + if isinstance(cause, astroid.Const): if cause.value is not None: self.add_message('bad-exception-context', node=node) elif (not isinstance(cause, astroid.ClassDef) and - not inherit_from_std_ex(cause)): + not utils.inherit_from_std_ex(cause)): self.add_message('bad-exception-context', node=node) - def _check_raise_value(self, node, expr): - """check for bad values, string exception and class inheritance - """ - value_found = True - if isinstance(expr, astroid.Const): - value = expr.value - if not isinstance(value, str): - # raising-string will be emitted from python3 porting checker. - self.add_message('raising-bad-type', node=node, - args=value.__class__.__name__) - elif ((isinstance(expr, astroid.Name) and - expr.name in ('None', 'True', 'False')) or - isinstance(expr, (astroid.List, astroid.Dict, astroid.Tuple, - astroid.Module, astroid.FunctionDef))): - emit = True - if not PY3K and isinstance(expr, astroid.Tuple) and expr.elts: - # On Python 2, using the following is not an error: - # raise (ZeroDivisionError, None) - # raise (ZeroDivisionError, ) - # What's left to do is to check that the first - # argument is indeed an exception. - # Verifying the other arguments is not - # the scope of this check. - first = expr.elts[0] - inferred = safe_infer(first) - if isinstance(inferred, astroid.Instance): - # pylint: disable=protected-access - inferred = inferred._proxied - if (inferred is astroid.YES or - isinstance(inferred, astroid.ClassDef) - and inherit_from_std_ex(inferred)): - emit = False - if emit: - self.add_message('raising-bad-type', - node=node, - args=expr.name) - elif ((isinstance(expr, astroid.Name) and expr.name == 'NotImplemented') - or (isinstance(expr, astroid.Call) and - isinstance(expr.func, astroid.Name) and - expr.func.name == 'NotImplemented')): - self.add_message('notimplemented-raised', node=node) - elif isinstance(expr, (astroid.Instance, astroid.ClassDef)): - if isinstance(expr, astroid.Instance): - # pylint: disable=protected-access - expr = expr._proxied - if (isinstance(expr, astroid.ClassDef) and - not inherit_from_std_ex(expr) and - has_known_bases(expr)): - if expr.newstyle: - self.add_message('raising-non-exception', node=node) - else: - self.add_message('nonstandard-exception', node=node) - else: - value_found = False - else: - value_found = False - return value_found - def _check_catching_non_exception(self, handler, exc, part): if isinstance(exc, astroid.Tuple): # Check if it is a tuple of exceptions. - inferred = [safe_infer(elt) for elt in exc.elts] + inferred = [utils.safe_infer(elt) for elt in exc.elts] if any(node is astroid.YES for node in inferred): # Don't emit if we don't know every component. return - if all(node and inherit_from_std_ex(node) + if all(node and utils.inherit_from_std_ex(node) for node in inferred): return @@ -289,23 +316,23 @@ def _check_catching_non_exception(self, handler, exc, part): args=(part.as_string(), )) return - if (not inherit_from_std_ex(exc) and - exc.name not in self.builtin_exceptions): - if has_known_bases(exc): + if (not utils.inherit_from_std_ex(exc) and + exc.name not in self._builtin_exceptions): + if utils.has_known_bases(exc): self.add_message('catching-non-exception', node=handler.type, args=(exc.name, )) - @check_messages('bare-except', 'broad-except', - 'binary-op-exception', 'bad-except-order', - 'catching-non-exception', 'duplicate-except') + @utils.check_messages('bare-except', 'broad-except', + 'binary-op-exception', 'bad-except-order', + 'catching-non-exception', 'duplicate-except') def visit_tryexcept(self, node): """check for empty except""" exceptions_classes = [] nb_handlers = len(node.handlers) for index, handler in enumerate(node.handlers): if handler.type is None: - if not is_raising(handler.body): + if not utils.is_raising(handler.body): self.add_message('bare-except', node=handler) # check if a "except:" is followed by some other # except @@ -321,11 +348,12 @@ def visit_tryexcept(self, node): excs = list(_annotated_unpack_infer(handler.type)) except astroid.InferenceError: continue + for part, exc in excs: if exc is astroid.YES: continue if (isinstance(exc, astroid.Instance) - and inherit_from_std_ex(exc)): + and utils.inherit_from_std_ex(exc)): # pylint: disable=protected-access exc = exc._proxied @@ -336,6 +364,7 @@ def visit_tryexcept(self, node): exc_ancestors = [anc for anc in exc.ancestors() if isinstance(anc, astroid.ClassDef)] + for previous_exc in exceptions_classes: if previous_exc in exc_ancestors: msg = '%s is an ancestor class of %s' % ( @@ -343,8 +372,8 @@ def visit_tryexcept(self, node): self.add_message('bad-except-order', node=handler.type, args=msg) if (exc.name in self.config.overgeneral_exceptions - and exc.root().name == EXCEPTIONS_MODULE - and not is_raising(handler.body)): + and exc.root().name == utils.EXCEPTIONS_MODULE + and not utils.is_raising(handler.body)): self.add_message('broad-except', args=exc.name, node=handler.type) diff --git a/pymode/libs/pylint/checkers/format.py b/pymode/libs/pylint/checkers/format.py index 8b0a6834..691b41bc 100644 --- a/pymode/libs/pylint/checkers/format.py +++ b/pymode/libs/pylint/checkers/format.py @@ -1,5 +1,13 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2015 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Michal Nowikowski +# Copyright (c) 2015 Mike Frysinger +# Copyright (c) 2015 Mihai Balint +# Copyright (c) 2015 Fabio Natali +# Copyright (c) 2015 Harut +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -12,10 +20,10 @@ Some parts of the process_token method is based from The Tab Nanny std module. """ -from functools import reduce # pylint: disable=redefined-builtin import keyword -import tokenize import sys +import tokenize +from functools import reduce # pylint: disable=redefined-builtin import six from six.moves import zip, map, filter # pylint: disable=redefined-builtin @@ -27,6 +35,7 @@ from pylint.checkers.utils import check_messages from pylint.utils import WarningScope, OPTION_RGX +_ASYNC_TOKEN = 'async' _CONTINUATION_BLOCK_OPENERS = ['elif', 'except', 'for', 'if', 'while', 'def', 'class'] _KEYWORD_TOKENS = ['assert', 'del', 'elif', 'except', 'for', 'if', 'in', 'not', 'raise', 'return', 'while', 'yield'] @@ -294,7 +303,13 @@ def handle_line_start(self, pos): """Record the first non-junk token at the start of a line.""" if self._line_start > -1: return - self._is_block_opener = self._tokens.token(pos) in _CONTINUATION_BLOCK_OPENERS + + check_token_position = pos + if self._tokens.token(pos) == _ASYNC_TOKEN: + check_token_position += 1 + self._is_block_opener = self._tokens.token( + check_token_position + ) in _CONTINUATION_BLOCK_OPENERS self._line_start = pos def next_physical_line(self): @@ -339,7 +354,7 @@ def _hanging_indent_after_bracket(self, bracket, position): _Offsets(indentation + self._continuation_size, indentation), _BeforeBlockOffsets(indentation + self._continuation_size, indentation + self._continuation_size * 2)) - elif bracket == ':': + if bracket == ':': # If the dict key was on the same line as the open brace, the new # correct indent should be relative to the key instead of the # current indent level @@ -354,13 +369,12 @@ def _hanging_indent_after_bracket(self, bracket, position): # } # is handled by the special-casing for hanging continued string indents. return _ContinuedIndent(HANGING_DICT_VALUE, bracket, position, paren_align, next_align) - else: - return _ContinuedIndent( - HANGING, - bracket, - position, - _Offsets(indentation, indentation + self._continuation_size), - _Offsets(indentation + self._continuation_size)) + return _ContinuedIndent( + HANGING, + bracket, + position, + _Offsets(indentation, indentation + self._continuation_size), + _Offsets(indentation + self._continuation_size)) def _continuation_inside_bracket(self, bracket, pos): """Extracts indentation information for a continued indent.""" @@ -374,13 +388,12 @@ def _continuation_inside_bracket(self, bracket, pos): pos, _Offsets(token_start), _BeforeBlockOffsets(next_token_start, next_token_start + self._continuation_size)) - else: - return _ContinuedIndent( - CONTINUED, - bracket, - pos, - _Offsets(token_start), - _Offsets(next_token_start)) + return _ContinuedIndent( + CONTINUED, + bracket, + pos, + _Offsets(token_start), + _Offsets(next_token_start)) def pop_token(self): self._cont_stack.pop() @@ -434,6 +447,11 @@ class FormatChecker(BaseTokenChecker): {'default': False, 'type' : 'yn', 'metavar' : '', 'help' : ('Allow the body of an if to be on the same ' 'line as the test if there is no else.')}), + ('single-line-class-stmt', + {'default': False, 'type' : 'yn', 'metavar' : '', + 'help' : ('Allow the body of a class to be on the same ' + 'line as the declaration if body contains ' + 'single statement.')}), ('no-space-check', {'default': ','.join(_DEFAULT_NO_SPACE_CHECK_CHOICES), 'metavar': ','.join(_NO_SPACE_CHECK_CHOICES), @@ -451,7 +469,7 @@ class FormatChecker(BaseTokenChecker): 'help': 'Maximum number of lines in a module'} ), ('indent-string', - {'default' : ' ', 'type' : "string", 'metavar' : '', + {'default' : ' ', 'type' : "non_empty_string", 'metavar' : '', 'help' : 'String used as indentation unit. This is usually ' '" " (4 spaces) or "\\t" (1 tab).'}), ('indent-after-paren', @@ -596,9 +614,32 @@ def _closing_bracket(self, tokens, i): self._check_space(tokens, i, (policy_before, _IGNORE)) + def _has_valid_type_annotation(self, tokens, i): + """Extended check of PEP-484 type hint presence""" + if not self._inside_brackets('('): + return False + bracket_level = 0 + for token in tokens[i-1::-1]: + if token[1] == ':': + return True + if token[1] == '(': + return False + if token[1] == ']': + bracket_level += 1 + elif token[1] == '[': + bracket_level -= 1 + elif token[1] == ',': + if not bracket_level: + return False + elif token[0] not in (tokenize.NAME, tokenize.STRING): + return False + return False + def _check_equals_spacing(self, tokens, i): """Check the spacing of a single equals sign.""" - if self._inside_brackets('(') or self._inside_brackets('lambda'): + if self._has_valid_type_annotation(tokens, i): + self._check_space(tokens, i, (_MUST, _MUST)) + elif self._inside_brackets('(') or self._inside_brackets('lambda'): self._check_space(tokens, i, (_MUST_NOT, _MUST_NOT)) else: self._check_space(tokens, i, (_MUST, _MUST)) @@ -640,23 +681,20 @@ def _check_space(self, tokens, i, policies): def _policy_string(policy): if policy == _MUST: return 'Exactly one', 'required' - else: - return 'No', 'allowed' + return 'No', 'allowed' def _name_construct(token): if token[1] == ',': return 'comma' - elif token[1] == ':': + if token[1] == ':': return ':' - elif token[1] in '()[]{}': + if token[1] in '()[]{}': return 'bracket' - elif token[1] in ('<', '>', '<=', '>=', '!=', '=='): + if token[1] in ('<', '>', '<=', '>=', '!=', '=='): return 'comparison' - else: - if self._inside_brackets('('): - return 'keyword argument assignment' - else: - return 'assignment' + if self._inside_brackets('('): + return 'keyword argument assignment' + return 'assignment' good_space = [True, True] token = tokens[i] @@ -832,7 +870,6 @@ def _check_line_ending(self, line_ending, line_num): self.add_message('unexpected-line-ending-format', args=(line_ending, expected), line=line_num) - def _process_retained_warnings(self, tokens, current_pos): single_line_block_stmt = not _last_token_on_line_is(tokens, current_pos, ':') @@ -869,6 +906,7 @@ def same_token_around_nl(token_type): and tokens.start_col(next_idx) in valid_offsets): self._current_line.add_block_warning(next_idx, state, valid_offsets) elif tokens.start_col(next_idx) not in valid_offsets: + self._add_continuation_message(state, valid_offsets, tokens, next_idx) def _add_continuation_message(self, state, offsets, tokens, position): @@ -934,6 +972,9 @@ def _check_multi_statement_line(self, node, line): if (isinstance(node.parent, nodes.If) and not node.parent.orelse and self.config.single_line_if_stmt): return + if (isinstance(node.parent, nodes.ClassDef) and len(node.parent.body) == 1 + and self.config.single_line_class_stmt): + return self.add_message('multiple-statements', node=node) self._visited_lines[line] = 2 @@ -943,11 +984,12 @@ def check_lines(self, lines, i): max_chars = self.config.max_line_length ignore_long_line = self.config.ignore_long_lines - for line in lines.splitlines(True): + def check_line(line, i): if not line.endswith('\n'): self.add_message('missing-final-newline', line=i) else: - stripped_line = line.rstrip() + # exclude \f (formfeed) from the rstrip + stripped_line = line.rstrip('\t\n\r\v ') if not stripped_line and _EMPTY_LINE in self.config.no_space_check: # allow empty lines pass @@ -961,7 +1003,35 @@ def check_lines(self, lines, i): if len(line) > max_chars and not ignore_long_line.search(line): self.add_message('line-too-long', line=i, args=(len(line), max_chars)) - i += 1 + return i + 1 + + unsplit_ends = { + u'\v', + u'\x0b', + u'\f', + u'\x0c', + u'\x1c', + u'\x1d', + u'\x1e', + u'\x85', + u'\u2028', + u'\u2029' + } + unsplit = [] + for line in lines.splitlines(True): + if line[-1] in unsplit_ends: + unsplit.append(line) + continue + + if unsplit: + unsplit.append(line) + line = ''.join(unsplit) + unsplit = [] + + i = check_line(line, i) + + if unsplit: + check_line(''.join(unsplit), i) def check_indent_level(self, string, expected, line_num): """return the indent level of the string diff --git a/pymode/libs/pylint/checkers/imports.py b/pymode/libs/pylint/checkers/imports.py index a3de594b..4cae39da 100644 --- a/pymode/libs/pylint/checkers/imports.py +++ b/pymode/libs/pylint/checkers/imports.py @@ -1,14 +1,23 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2012-2014 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2015 Noam Yorav-Raphael +# Copyright (c) 2015 Cezar +# Copyright (c) 2015 James Morgensen +# Copyright (c) 2016 Moises Lopez - https://www.vauxoo.com/ +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """imports checkers for Python code""" import collections +from distutils import sysconfig import os import sys -from distutils import sysconfig +import copy import six @@ -18,7 +27,8 @@ import isort from pylint.interfaces import IAstroidChecker -from pylint.utils import EmptyReport, get_global_option +from pylint.utils import get_global_option +from pylint.exceptions import EmptyReportError from pylint.checkers import BaseChecker from pylint.checkers.utils import ( check_messages, @@ -75,23 +85,27 @@ def _get_first_import(node, context, name, base, level, alias): found = True break elif isinstance(first, astroid.ImportFrom): - if level != first.level: - continue - - for imported_name, imported_alias in first.names: - if fullname == '%s.%s' % (first.modname, imported_name): - found = True - break - if name != '*' and name == imported_name: - if alias or imported_alias: - continue - found = True + if level == first.level: + for imported_name, imported_alias in first.names: + if fullname == '%s.%s' % (first.modname, imported_name): + found = True + break + if name != '*' and name == imported_name and not (alias or imported_alias): + found = True + break + if found: break - if found: - break if found and not are_exclusive(first, node): return first + +def _ignore_import_failure(node, modname, ignored_modules): + for submodule in _qualified_names(modname): + if submodule in ignored_modules: + return True + + return node_ignores_exception(node, ImportError) + # utilities to represents import dependencies as tree and dot graph ########### def _make_tree_defs(mod_files_list): @@ -115,7 +129,7 @@ def _repr_tree_defs(data, indent_str=None): if not files: files = '' else: - files = '(%s)' % ','.join(files) + files = '(%s)' % ','.join(sorted(files)) if indent_str is None: lines.append('%s %s' % (mod, files)) sub_indent_str = ' ' @@ -139,10 +153,10 @@ def _dependencies_graph(filename, dep_info): for modname, dependencies in sorted(six.iteritems(dep_info)): done[modname] = 1 printer.emit_node(modname) - for modname in dependencies: - if modname not in done: - done[modname] = 1 - printer.emit_node(modname) + for depmodname in dependencies: + if depmodname not in done: + done[depmodname] = 1 + printer.emit_node(depmodname) for depmodname, dependencies in sorted(six.iteritems(dep_info)): for modname in dependencies: printer.emit_edge(modname, depmodname) @@ -165,6 +179,10 @@ def _make_graph(filename, dep_info, sect, gtype): 'import-error', 'Used when pylint has been unable to import a module.', {'old_names': [('F0401', 'import-error')]}), + 'E0402': ('Attempted relative import beyond top-level package', + 'relative-beyond-top-level', + 'Used when a relative import tries to access too many levels ' + 'in the current package.'), 'R0401': ('Cyclic import (%s)', 'cyclic-import', 'Used when a cyclic import between two or more modules is \ @@ -197,7 +215,7 @@ def _make_graph(filename, dep_info, sect, gtype): 'multiple-imports', 'Used when import statement importing multiple modules is ' 'detected.'), - 'C0411': ('%s comes before %s', + 'C0411': ('%s should be placed before %s', 'wrong-import-order', 'Used when PEP8 import order is not respected (standard imports ' 'first, then third-party libraries, then local imports)'), @@ -231,48 +249,51 @@ class ImportsChecker(BaseChecker): if six.PY2: deprecated_modules = ('regsub', 'TERMIOS', 'Bastion', 'rexec') - else: + elif sys.version_info < (3, 5): deprecated_modules = ('optparse', ) + else: + deprecated_modules = ('optparse', 'tkinter.tix') options = (('deprecated-modules', {'default' : deprecated_modules, 'type' : 'csv', 'metavar' : '', - 'help' : 'Deprecated modules which should not be used, \ -separated by a comma'} + 'help' : 'Deprecated modules which should not be used,' + ' separated by a comma'} ), ('import-graph', {'default' : '', 'type' : 'string', 'metavar' : '', - 'help' : 'Create a graph of every (i.e. internal and \ -external) dependencies in the given file (report RP0402 must not be disabled)'} + 'help' : 'Create a graph of every (i.e. internal and' + ' external) dependencies in the given file' + ' (report RP0402 must not be disabled)'} ), ('ext-import-graph', {'default' : '', 'type' : 'string', 'metavar' : '', - 'help' : 'Create a graph of external dependencies in the \ -given file (report RP0402 must not be disabled)'} + 'help' : 'Create a graph of external dependencies in the' + ' given file (report RP0402 must not be disabled)'} ), ('int-import-graph', {'default' : '', 'type' : 'string', 'metavar' : '', - 'help' : 'Create a graph of internal dependencies in the \ -given file (report RP0402 must not be disabled)'} + 'help' : 'Create a graph of internal dependencies in the' + ' given file (report RP0402 must not be disabled)'} ), ('known-standard-library', {'default': DEFAULT_STANDARD_LIBRARY, 'type': 'csv', 'metavar': '', - 'help': 'Force import order to recognize a module as part of' \ + 'help': 'Force import order to recognize a module as part of' ' the standard compatibility libraries.'} ), ('known-third-party', {'default': DEFAULT_KNOWN_THIRD_PARTY, 'type': 'csv', 'metavar': '', - 'help': 'Force import order to recognize a module as part of' \ + 'help': 'Force import order to recognize a module as part of' ' a third party library.'} ), ('analyse-fallback-blocks', @@ -282,8 +303,13 @@ class ImportsChecker(BaseChecker): 'help': 'Analyse import fallback blocks. This can be used to ' 'support both Python 2 and 3 compatible code, which means that ' 'the block might have code that exists only in one or another ' - 'interpreter, leading to false positives when analysed.'}), - + 'interpreter, leading to false positives when analysed.'}, + ), + ('allow-wildcard-with-all', + {'default': False, + 'type': 'yn', + 'metavar': '', + 'help': 'Allow wildcard imports from modules that define __all__.'}), ) def __init__(self, linter=None): @@ -328,15 +354,22 @@ def open(self): self.linter.add_stats(cycles=[]) self.stats = self.linter.stats self.import_graph = collections.defaultdict(set) + self._excluded_edges = collections.defaultdict(set) self._ignored_modules = get_global_option( self, 'ignored-modules', default=[]) + def _import_graph_without_ignored_edges(self): + filtered_graph = copy.deepcopy(self.import_graph) + for node in filtered_graph: + filtered_graph[node].difference_update(self._excluded_edges[node]) + return filtered_graph + def close(self): """called before visiting project (i.e set of modules)""" - # don't try to compute cycles if the associated message is disabled if self.linter.is_message_enabled('cyclic-import'): - vertices = list(self.import_graph) - for cycle in get_cycles(self.import_graph, vertices=vertices): + graph = self._import_graph_without_ignored_edges() + vertices = list(graph) + for cycle in get_cycles(graph, vertices=vertices): self.add_message('cyclic-import', args=' -> '.join(cycle)) @check_messages('wrong-import-position', 'multiple-imports', @@ -352,43 +385,44 @@ def visit_import(self, node): for name in names: self._check_deprecated_module(node, name) - importedmodnode = self._get_imported_module(node, name) + imported_module = self._get_imported_module(node, name) if isinstance(node.parent, astroid.Module): # Allow imports nested self._check_position(node) if isinstance(node.scope(), astroid.Module): - self._record_import(node, importedmodnode) + self._record_import(node, imported_module) - if importedmodnode is None: + if imported_module is None: continue - self._check_relative_import(modnode, node, importedmodnode, name) - self._add_imported_module(node, importedmodnode.name) + self._check_relative_import(modnode, node, imported_module, name) + self._add_imported_module(node, imported_module.name) @check_messages(*(MSGS.keys())) def visit_importfrom(self, node): """triggered when a from statement is seen""" basename = node.modname + imported_module = self._get_imported_module(node, basename) + self._check_misplaced_future(node) self._check_deprecated_module(node, basename) - self._check_wildcard_imports(node) + self._check_wildcard_imports(node, imported_module) self._check_same_line_imports(node) self._check_reimport(node, basename=basename, level=node.level) - modnode = node.root() - importedmodnode = self._get_imported_module(node, basename) if isinstance(node.parent, astroid.Module): # Allow imports nested self._check_position(node) if isinstance(node.scope(), astroid.Module): - self._record_import(node, importedmodnode) - if importedmodnode is None: + self._record_import(node, imported_module) + if imported_module is None: return - self._check_relative_import(modnode, node, importedmodnode, basename) + modnode = node.root() + self._check_relative_import(modnode, node, imported_module, basename) for name, _ in node.names: if name != '*': - self._add_imported_module(node, '%s.%s' % (importedmodnode.name, name)) + self._add_imported_module(node, '%s.%s' % (imported_module.name, name)) @check_messages('wrong-import-order', 'ungrouped-imports', 'wrong-import-position') @@ -519,7 +553,7 @@ def _is_fallback_import(node, imports): return any(astroid.are_exclusive(import_node, node) for import_node in imports) - def _check_imports_order(self, node): + def _check_imports_order(self, _module_node): """Checks imports of module `node` are grouped by category Imports must follow this order: standard, 3rd party, local @@ -567,22 +601,21 @@ def _check_imports_order(self, node): def _get_imported_module(self, importnode, modname): try: return importnode.do_import_module(modname) - except astroid.InferenceError as ex: - dotted_modname = _get_import_name(importnode, modname) - if str(ex) != modname: - args = '%r (%s)' % (dotted_modname, ex) - else: - args = repr(dotted_modname) + except astroid.TooManyLevelsError: + if _ignore_import_failure(importnode, modname, self._ignored_modules): + return None - for submodule in _qualified_names(modname): - if submodule in self._ignored_modules: - return None + self.add_message('relative-beyond-top-level', node=importnode) + except astroid.AstroidBuildingException: + if _ignore_import_failure(importnode, modname, self._ignored_modules): + return None if not self.config.analyse_fallback_blocks and is_from_fallback_block(importnode): return None - if not node_ignores_exception(importnode, ImportError): - self.add_message("import-error", args=args, node=importnode) + dotted_modname = _get_import_name(importnode, modname) + self.add_message('import-error', args=repr(dotted_modname), + node=importnode) def _check_relative_import(self, modnode, importnode, importedmodnode, importedasname): @@ -632,10 +665,11 @@ def _add_imported_module(self, node, importedmodname): importedmodname, set()) if context_name not in importedmodnames: importedmodnames.add(context_name) + # update import graph - mgraph = self.import_graph[context_name] - if importedmodname not in mgraph: - mgraph.add(importedmodname) + self.import_graph[context_name].add(importedmodname) + if not self.linter.is_message_enabled('cyclic-import'): + self._excluded_edges[context_name].add(importedmodname) def _check_deprecated_module(self, node, mod_path): """check if the module is deprecated""" @@ -654,28 +688,31 @@ def _check_reimport(self, node, basename=None, level=None): if root is not frame: contexts.append((root, None)) - for context, level in contexts: + for known_context, known_level in contexts: for name, alias in node.names: - first = _get_first_import(node, context, name, basename, level, alias) + first = _get_first_import( + node, known_context, + name, basename, + known_level, alias) if first is not None: self.add_message('reimported', node=node, args=(name, first.fromlineno)) - def _report_external_dependencies(self, sect, _, dummy): + def _report_external_dependencies(self, sect, _, _dummy): """return a verbatim layout for displaying dependencies""" dep_info = _make_tree_defs(six.iteritems(self._external_dependencies_info())) if not dep_info: - raise EmptyReport() + raise EmptyReportError() tree_str = _repr_tree_defs(dep_info) sect.append(VerbatimText(tree_str)) - def _report_dependencies_graph(self, sect, _, dummy): + def _report_dependencies_graph(self, sect, _, _dummy): """write dependencies as a dot (graphviz) file""" dep_info = self.stats['dependencies'] if not dep_info or not (self.config.import_graph or self.config.ext_import_graph or self.config.int_import_graph): - raise EmptyReport() + raise EmptyReportError() filename = self.config.import_graph if filename: _make_graph(filename, dep_info, sect, '') @@ -712,11 +749,19 @@ def _internal_dependencies_info(self): result[importee] = importers return self.__int_dep_info - def _check_wildcard_imports(self, node): + def _check_wildcard_imports(self, node, imported_module): + wildcard_import_is_allowed = ( + self._wildcard_import_is_allowed(imported_module) + ) for name, _ in node.names: - if name == '*': + if name == '*' and not wildcard_import_is_allowed: self.add_message('wildcard-import', args=node.modname, node=node) + def _wildcard_import_is_allowed(self, imported_module): + return (self.config.allow_wildcard_with_all + and imported_module is not None + and '__all__' in imported_module.locals) + def register(linter): """required method to auto register this checker """ diff --git a/pymode/libs/pylint/checkers/logging.py b/pymode/libs/pylint/checkers/logging.py index ed243d11..d9c1fd78 100644 --- a/pymode/libs/pylint/checkers/logging.py +++ b/pymode/libs/pylint/checkers/logging.py @@ -1,9 +1,13 @@ -# Copyright (c) 2009-2016 Google, Inc. +# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Google, Inc. +# Copyright (c) 2015-2016 Claudiu Popa +# Copyright (c) 2016 Ashley Whetter # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """checker for use of Python logging """ +import string import six @@ -46,37 +50,36 @@ the end of a conversion specifier.'), 'E1205': ('Too many arguments for logging format string', 'logging-too-many-args', - 'Used when a logging format string is given too few arguments.'), + 'Used when a logging format string is given too many arguments.'), 'E1206': ('Not enough arguments for logging format string', 'logging-too-few-args', - 'Used when a logging format string is given too many arguments'), + 'Used when a logging format string is given too few arguments.'), } -CHECKED_CONVENIENCE_FUNCTIONS = set([ - 'critical', 'debug', 'error', 'exception', 'fatal', 'info', 'warn', - 'warning']) +CHECKED_CONVENIENCE_FUNCTIONS = { + 'critical', 'debug', 'error', 'exception', 'fatal', 'info', 'warn', 'warning' +} + + +def is_method_call(func, types=(), methods=()): + """Determines if a BoundMethod node represents a method call. -def is_method_call(callfunc_node, types=(), methods=()): - """Determines if a CallFunc node represents a method call. Args: - callfunc_node (astroid.CallFunc): The CallFunc AST node to check. + func (astroid.BoundMethod): The BoundMethod AST node to check. types (Optional[String]): Optional sequence of caller type names to restrict check. methods (Optional[String]): Optional sequence of method names to restrict check. + Returns: bool: true if the node represents a method call for the given type and method names, False otherwise. """ - if not isinstance(callfunc_node, astroid.Call): - return False - func = utils.safe_infer(callfunc_node.func) return (isinstance(func, astroid.BoundMethod) and isinstance(func.bound, astroid.Instance) and (func.bound.name in types if types else True) and (func.name in methods if methods else True)) - class LoggingChecker(checkers.BaseChecker): """Checks use of the logging module.""" @@ -178,15 +181,18 @@ def _check_log_method(self, node, name): elif isinstance(node.args[format_pos], astroid.Const): self._check_format_string(node, format_pos) - def _check_call_func(self, callfunc_node): + def _check_call_func(self, node): """Checks that function call is not format_string.format(). Args: - callfunc_node (astroid.node_classes.NodeNG): + node (astroid.node_classes.CallFunc): CallFunc AST node to be checked. """ - if is_method_call(callfunc_node, ('str', 'unicode'), ('format',)): - self.add_message('logging-format-interpolation', node=callfunc_node) + func = utils.safe_infer(node.func) + types = ('str', 'unicode') + methods = ('format',) + if is_method_call(func, types, methods) and not is_complex_format_str(func.bound): + self.add_message('logging-format-interpolation', node=node) def _check_format_string(self, node, format_arg): """Checks that format string tokens match the supplied arguments. @@ -227,6 +233,23 @@ def _check_format_string(self, node, format_arg): self.add_message('logging-too-few-args', node=node) +def is_complex_format_str(node): + """Checks if node represents a string with complex formatting specs. + + Args: + node (astroid.node_classes.NodeNG): AST node to check + Returns: + bool: True if inferred string uses complex formatting, False otherwise + """ + inferred = utils.safe_infer(node) + if inferred is None or not isinstance(inferred.value, six.string_types): + return True + for _, _, format_spec, _ in string.Formatter().parse(inferred.value): + if format_spec: + return True + return False + + def _count_supplied_tokens(args): """Counts the number of tokens in an args list. diff --git a/pymode/libs/pylint/checkers/misc.py b/pymode/libs/pylint/checkers/misc.py index 5253de6c..104f0dfc 100644 --- a/pymode/libs/pylint/checkers/misc.py +++ b/pymode/libs/pylint/checkers/misc.py @@ -1,5 +1,8 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2009-2013 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014 Alexandru Coman +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -61,7 +64,7 @@ def _check_note(self, notes, lineno, line): match = notes.search(line) if not match: return - self.add_message('fixme', args=line[match.start(1):-1], line=lineno) + self.add_message('fixme', args=line[match.start(1):].rstrip(), line=lineno) def _check_encoding(self, lineno, line, file_encoding): try: @@ -76,7 +79,7 @@ def process_module(self, module): """ if self.config.notes: notes = re.compile( - r'.*?#\s*(%s)(:*\s*.+)' % "|".join(self.config.notes)) + r'.*?#\s*(%s)(:*\s*.*)' % "|".join(self.config.notes)) else: notes = None if module.file_encoding: diff --git a/pymode/libs/pylint/checkers/newstyle.py b/pymode/libs/pylint/checkers/newstyle.py index 0e46eae0..6071ea5c 100644 --- a/pymode/libs/pylint/checkers/newstyle.py +++ b/pymode/libs/pylint/checkers/newstyle.py @@ -1,5 +1,6 @@ -# Copyright (c) 2005-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2008-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -43,7 +44,7 @@ {'maxversion': (3, 0)}), 'C1001': ('Old-style class defined.', 'old-style-class', - 'Used when a class is defined that does not inherit from another' + 'Used when a class is defined that does not inherit from another ' 'class and does not inherit explicitly from "object".', {'maxversion': (3, 0)}) } @@ -109,9 +110,11 @@ def visit_functiondef(self, node): if node_frame_class(stmt) != node_frame_class(node): # Don't look down in other scopes. continue + expr = stmt.func if not isinstance(expr, astroid.Attribute): continue + call = expr.expr # skip the test if using super if not (isinstance(call, astroid.Call) and @@ -124,18 +127,36 @@ def visit_functiondef(self, node): self.add_message('super-on-old-class', node=node) else: # super first arg should be the class - if not call.args and sys.version_info[0] == 3: - # unless Python 3 + if not call.args: + if sys.version_info[0] == 3: + # unless Python 3 + continue + else: + self.add_message('missing-super-argument', node=call) + continue + + # calling super(type(self), self) can lead to recursion loop + # in derived classes + arg0 = call.args[0] + if isinstance(arg0, astroid.Call) and \ + isinstance(arg0.func, astroid.Name) and \ + arg0.func.name == 'type': + self.add_message('bad-super-call', node=call, args=('type', )) continue - try: - supcls = (call.args and next(call.args[0].infer()) - or None) - except astroid.InferenceError: + # calling super(self.__class__, self) can lead to recursion loop + # in derived classes + if len(call.args) >= 2 and \ + isinstance(call.args[1], astroid.Name) and \ + call.args[1].name == 'self' and \ + isinstance(arg0, astroid.Attribute) and \ + arg0.attrname == '__class__': + self.add_message('bad-super-call', node=call, args=('self.__class__', )) continue - if supcls is None: - self.add_message('missing-super-argument', node=call) + try: + supcls = call.args and next(call.args[0].infer(), None) + except astroid.InferenceError: continue if klass is not supcls: @@ -143,12 +164,11 @@ def visit_functiondef(self, node): # if supcls is not YES, then supcls was infered # and use its name. Otherwise, try to look # for call.args[0].name - if supcls is not astroid.YES: + if supcls: name = supcls.name - else: - if hasattr(call.args[0], 'name'): - name = call.args[0].name - if name is not None: + elif call.args and hasattr(call.args[0], 'name'): + name = call.args[0].name + if name: self.add_message('bad-super-call', node=call, args=(name, )) visit_asyncfunctiondef = visit_functiondef diff --git a/pymode/libs/pylint/checkers/python3.py b/pymode/libs/pylint/checkers/python3.py index ec37ca1b..971072ee 100644 --- a/pymode/libs/pylint/checkers/python3.py +++ b/pymode/libs/pylint/checkers/python3.py @@ -1,4 +1,6 @@ -# Copyright (c) 2014-2016 Google, Inc. +# Copyright (c) 2014-2015 Brett Cannon +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Pavel Roskin # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -6,12 +8,18 @@ from __future__ import absolute_import, print_function import re +import sys import tokenize +from collections import namedtuple + +import six + import astroid from astroid import bases from pylint import checkers, interfaces +from pylint.interfaces import INFERENCE_FAILURE, INFERENCE from pylint.utils import WarningScope from pylint.checkers import utils @@ -21,7 +29,7 @@ def _is_old_octal(literal): if _ZERO.match(literal): return False - if re.match('0\d+', literal): + if re.match(r'0\d+', literal): try: int(literal, 8) except ValueError: @@ -34,7 +42,7 @@ def _check_dict_node(node): inferred = node.infer() for inferred_node in inferred: inferred_types.add(inferred_node) - except (astroid.InferenceError, astroid.UnresolvableName): + except astroid.InferenceError: pass return (not inferred_types or any(isinstance(x, astroid.Dict) for x in inferred_types)) @@ -80,6 +88,15 @@ def _in_iterating_context(node): return False +def _is_conditional_import(node): + """Checks if a import node is in the context of a conditional. + """ + parent = node.parent + return isinstance(parent, (astroid.TryExcept, astroid.ExceptHandler, + astroid.If, astroid.IfExp)) + +Branch = namedtuple('Branch', ['node', 'is_py2_only']) + class Python3Checker(checkers.BaseChecker): __implements__ = interfaces.IAstroidChecker @@ -331,6 +348,57 @@ class Python3Checker(checkers.BaseChecker): 'Python 3. Using either `key` or `functools.cmp_to_key` ' 'should be preferred.', {'maxversion': (3, 0)}), + 'W1641': ('Implementing __eq__ without also implementing __hash__', + 'eq-without-hash', + 'Used when a class implements __eq__ but not __hash__. In Python 2, objects ' + 'get object.__hash__ as the default implementation, in Python 3 objects get ' + 'None as their default __hash__ implementation if they also implement __eq__.', + {'maxversion': (3, 0)}), + 'W1642': ('__div__ method defined', + 'div-method', + 'Used when a __div__ method is defined. Using `__truediv__` and setting' + '__div__ = __truediv__ should be preferred.' + '(method is not used by Python 3)', + {'maxversion': (3, 0)}), + 'W1643': ('__idiv__ method defined', + 'idiv-method', + 'Used when a __idiv__ method is defined. Using `__itruediv__` and setting' + '__idiv__ = __itruediv__ should be preferred.' + '(method is not used by Python 3)', + {'maxversion': (3, 0)}), + 'W1644': ('__rdiv__ method defined', + 'rdiv-method', + 'Used when a __rdiv__ method is defined. Using `__rtruediv__` and setting' + '__rdiv__ = __rtruediv__ should be preferred.' + '(method is not used by Python 3)', + {'maxversion': (3, 0)}), + 'W1645': ('Exception.message removed in Python 3', + 'exception-message-attribute', + 'Used when the message attribute is accessed on an Exception. Use ' + 'str(exception) instead.', + {'maxversion': (3, 0)}), + 'W1646': ('non-text encoding used in str.decode', + 'invalid-str-codec', + 'Used when using str.encode or str.decode with a non-text encoding. Use ' + 'codecs module to handle arbitrary codecs.', + {'maxversion': (3, 0)}), + 'W1647': ('sys.maxint removed in Python 3', + 'sys-max-int', + 'Used when accessing sys.maxint. Use sys.maxsize instead.', + {'maxversion': (3, 0)}), + 'W1648': ('Module moved in Python 3', + 'bad-python3-import', + 'Used when importing a module that no longer exists in Python 3.', + {'maxversion': (3, 0)}), + 'W1649': ('Accessing a function method on the string module', + 'deprecated-string-function', + 'Used when accessing a string function that has been deprecated in Python 3.', + {'maxversion': (3, 0)}), + 'W1650': ('Using str.translate with deprecated deletechars parameters', + 'deprecated-str-translate-call', + 'Used when using the deprecated deletechars parameters from str.translate. Use' + 're.sub to remove the desired characters ', + {'maxversion': (3, 0)}), } _bad_builtins = frozenset([ @@ -363,14 +431,110 @@ class Python3Checker(checkers.BaseChecker): '__hex__', '__nonzero__', '__cmp__', + '__div__', + '__idiv__', + '__rdiv__', + ]) + + _invalid_encodings = frozenset([ + 'base64_codec', + 'base64', + 'base_64', + 'bz2_codec', + 'bz2', + 'hex_codec', + 'hex', + 'quopri_codec', + 'quopri', + 'quotedprintable', + 'quoted_printable', + 'uu_codec', + 'uu', + 'zlib_codec', + 'zlib', + 'zip', + 'rot13', + 'rot_13', ]) + _bad_python3_module_map = { + 'sys-max-int': { + 'sys': frozenset(['maxint']) + }, + 'bad-python3-import': frozenset([ + 'anydbm', 'BaseHTTPServer', '__builtin__', 'CGIHTTPServer', 'ConfigParser', 'copy_reg', + 'cPickle', 'cProfile', 'cStringIO', 'Cookie', 'cookielib', 'dbhash', 'dbm', 'dumbdbm', + 'dumbdb', 'Dialog', 'DocXMLRPCServer', 'FileDialog', 'FixTk', 'gdbm', 'htmlentitydefs', + 'HTMLParser', 'httplib', 'markupbase', 'Queue', 'repr', 'robotparser', 'ScrolledText', + 'SimpleDialog', 'SimpleHTTPServer', 'SimpleXMLRPCServer', 'StringIO', 'dummy_thread', + 'SocketServer', 'test.test_support', 'Tkinter', 'Tix', 'Tkconstants', 'tkColorChooser', + 'tkCommonDialog', 'Tkdnd', 'tkFileDialog', 'tkFont', 'tkMessageBox', 'tkSimpleDialog', + 'turtle', 'UserList', 'UserString', 'whichdb', '_winreg', 'xmlrpclib', 'audiodev', + 'Bastion', 'bsddb185', 'bsddb3', 'Canvas', 'cfmfile', 'cl', 'commands', 'compiler', + 'dircache', 'dl', 'exception', 'fpformat', 'htmllib', 'ihooks', 'imageop', 'imputil', + 'linuxaudiodev', 'md5', 'mhlib', 'mimetools', 'MimeWriter', 'mimify', 'multifile', + 'mutex', 'new', 'popen2', 'posixfile', 'pure', 'rexec', 'rfc822', 'sha', 'sgmllib', + 'sre', 'stat', 'stringold', 'sunaudio', 'sv', 'test.testall', 'thread', 'timing', + 'toaiff', 'user', 'urllib2', 'urlparse' + ]), + 'deprecated-string-function': { + 'string': frozenset([ + 'maketrans', 'atof', 'atoi', 'atol', 'capitalize', 'expandtabs', 'find', 'rfind', + 'index', 'rindex', 'count', 'lower', 'split', 'rsplit', 'splitfields', 'join', + 'joinfields', 'lstrip', 'rstrip', 'strip', 'swapcase', 'translate', 'upper', + 'ljust', 'rjust', 'center', 'zfill', 'replace' + ]) + } + } + + if (3, 4) <= sys.version_info < (3, 4, 4): + # Python 3.4.0 -> 3.4.3 has a bug which breaks `repr_tree()`: + # https://bugs.python.org/issue23572 + _python_2_tests = frozenset() + else: + _python_2_tests = frozenset( + [astroid.extract_node(x).repr_tree() for x in [ + 'sys.version_info[0] == 2', + 'sys.version_info[0] < 3', + 'sys.version_info == (2, 7)', + 'sys.version_info <= (2, 7)', + 'sys.version_info < (3, 0)', + ]]) + def __init__(self, *args, **kwargs): self._future_division = False self._future_absolute_import = False + self._modules_warned_about = set() + self._branch_stack = [] super(Python3Checker, self).__init__(*args, **kwargs) - def visit_module(self, node): # pylint: disable=unused-argument + def add_message(self, msg_id, always_warn=False, # pylint: disable=arguments-differ + *args, **kwargs): + if always_warn or not (self._branch_stack and self._branch_stack[-1].is_py2_only): + super(Python3Checker, self).add_message(msg_id, *args, **kwargs) + + def _is_py2_test(self, node): + if isinstance(node.test, astroid.Attribute) and isinstance(node.test.expr, astroid.Name): + if node.test.expr.name == 'six' and node.test.attrname == 'PY2': + return True + elif (isinstance(node.test, astroid.Compare) and + node.test.repr_tree() in self._python_2_tests): + return True + return False + + def visit_if(self, node): + self._branch_stack.append(Branch(node, self._is_py2_test(node))) + + def leave_if(self, node): + assert self._branch_stack.pop().node == node + + def visit_ifexp(self, node): + self._branch_stack.append(Branch(node, self._is_py2_test(node))) + + def leave_ifexp(self, node): + assert self._branch_stack.pop().node == node + + def visit_module(self, node): # pylint: disable=unused-argument """Clear checker state after previous module.""" self._future_division = False self._future_absolute_import = False @@ -398,7 +562,17 @@ def visit_name(self, node): @utils.check_messages('print-statement') def visit_print(self, node): - self.add_message('print-statement', node=node) + self.add_message('print-statement', node=node, always_warn=True) + + def _warn_if_deprecated(self, node, module, attributes, report_on_modules=True): + for message, module_map in six.iteritems(self._bad_python3_module_map): + if module in module_map and module not in self._modules_warned_about: + if isinstance(module_map, frozenset): + if report_on_modules: + self._modules_warned_about.add(module) + self.add_message(message, node=node) + elif attributes and module_map[module].intersection(attributes): + self.add_message(message, node=node) def visit_importfrom(self, node): if node.modname == '__future__': @@ -407,23 +581,32 @@ def visit_importfrom(self, node): self._future_division = True elif name == 'absolute_import': self._future_absolute_import = True - elif not self._future_absolute_import: - if self.linter.is_message_enabled('no-absolute-import'): - self.add_message('no-absolute-import', node=node) + else: + if not self._future_absolute_import: + if self.linter.is_message_enabled('no-absolute-import'): + self.add_message('no-absolute-import', node=node) + if not _is_conditional_import(node): + self._warn_if_deprecated(node, node.modname, {x[0] for x in node.names}) + if node.names[0][0] == '*': if self.linter.is_message_enabled('import-star-module-level'): if not isinstance(node.scope(), astroid.Module): self.add_message('import-star-module-level', node=node) - @utils.check_messages('no-absolute-import') def visit_import(self, node): if not self._future_absolute_import: self.add_message('no-absolute-import', node=node) + if not _is_conditional_import(node): + for name, _ in node.names: + self._warn_if_deprecated(node, name, None) @utils.check_messages('metaclass-assignment') def visit_classdef(self, node): if '__metaclass__' in node.locals: self.add_message('metaclass-assignment', node=node) + locals_and_methods = set(node.locals).union(x.name for x in node.mymethods()) + if '__eq__' in locals_and_methods and '__hash__' not in locals_and_methods: + self.add_message('eq-without-hash', node=node) @utils.check_messages('old-division') def visit_binop(self, node): @@ -463,11 +646,73 @@ def _check_cmp_argument(self, node): self.add_message('using-cmp-argument', node=node) return + @staticmethod + def _is_constant_string_or_name(node): + if isinstance(node, astroid.Const): + return isinstance(node.value, six.string_types) + return isinstance(node, astroid.Name) + + @staticmethod + def _is_none(node): + return isinstance(node, astroid.Const) and node.value is None + + @staticmethod + def _has_only_n_positional_args(node, number_of_args): + return len(node.args) == number_of_args and all(node.args) and not node.keywords + + @staticmethod + def _could_be_string(inferred_types): + confidence = INFERENCE if inferred_types else INFERENCE_FAILURE + for inferred_type in inferred_types: + if inferred_type is astroid.Uninferable: + confidence = INFERENCE_FAILURE + elif not (isinstance(inferred_type, astroid.Const) and + isinstance(inferred_type.value, six.string_types)): + return None + return confidence + def visit_call(self, node): self._check_cmp_argument(node) if isinstance(node.func, astroid.Attribute): - if any([node.args, node.keywords]): + inferred_types = set() + try: + for inferred_receiver in node.func.expr.infer(): + inferred_types.add(inferred_receiver) + if isinstance(inferred_receiver, astroid.Module): + self._warn_if_deprecated(node, inferred_receiver.name, + {node.func.attrname}, + report_on_modules=False) + except astroid.InferenceError: + pass + if node.args: + is_str_confidence = self._could_be_string(inferred_types) + if is_str_confidence: + if (node.func.attrname in ('encode', 'decode') and + len(node.args) >= 1 and node.args[0]): + first_arg = node.args[0] + self._validate_encoding(first_arg, node) + if (node.func.attrname == 'translate' and + self._has_only_n_positional_args(node, 2) and + self._is_none(node.args[0]) and + self._is_constant_string_or_name(node.args[1])): + # The above statement looking for calls of the form: + # + # foo.translate(None, 'abc123') + # + # or + # + # foo.translate(None, some_variable) + # + # This check is somewhat broad and _may_ have some false positives, but + # after checking several large codebases it did not have any false + # positives while finding several real issues. This call pattern seems + # rare enough that the trade off is worth it. + self.add_message('deprecated-str-translate-call', + node=node, + confidence=is_str_confidence) + return + if node.keywords: return if node.func.attrname == 'next': self.add_message('next-method-called', node=node) @@ -484,20 +729,54 @@ def visit_call(self, node): if not _in_iterating_context(node): checker = '{}-builtin-not-iterating'.format(node.func.name) self.add_message(checker, node=node) - + if node.func.name == 'open' and node.keywords: + kwargs = node.keywords + for kwarg in kwargs or []: + if kwarg.arg == 'encoding': + self._validate_encoding(kwarg.value, node) + break + + def _validate_encoding(self, encoding, node): + if isinstance(encoding, astroid.Const): + value = encoding.value + if value in self._invalid_encodings: + self.add_message('invalid-str-codec', + node=node) @utils.check_messages('indexing-exception') def visit_subscript(self, node): """ Look for indexing exceptions. """ try: - for infered in node.value.infer(): - if not isinstance(infered, astroid.Instance): + for inferred in node.value.infer(): + if not isinstance(inferred, astroid.Instance): continue - if utils.inherit_from_std_ex(infered): + if utils.inherit_from_std_ex(inferred): self.add_message('indexing-exception', node=node) except astroid.InferenceError: return + def visit_assignattr(self, node): + if isinstance(node.assign_type(), astroid.AugAssign): + self.visit_attribute(node) + + def visit_delattr(self, node): + self.visit_attribute(node) + + @utils.check_messages('exception-message-attribute') + def visit_attribute(self, node): + """ Look for accessing message on exceptions. """ + try: + for inferred in node.expr.infer(): + if (isinstance(inferred, astroid.Instance) and + utils.inherit_from_std_ex(inferred)): + if node.attrname == 'message': + self.add_message('exception-message-attribute', node=node) + if isinstance(inferred, astroid.Module): + self._warn_if_deprecated(node, inferred.name, {node.attrname}, + report_on_modules=False) + except astroid.InferenceError: + return + @utils.check_messages('unpacking-in-except') def visit_excepthandler(self, node): """Visit an except handler block and check for exception unpacking.""" @@ -559,7 +838,7 @@ class Python3TokenChecker(checkers.BaseTokenChecker): 'old_names': [('W0331', 'old-ne-operator')]}), 'E1608': ('Use of old octal literal', 'old-octal-literal', - 'Usen when encountering the old octal syntax, ' + 'Used when encountering the old octal syntax, ' 'removed in Python 3. To use the new syntax, ' 'prepend 0o on the number.', {'maxversion': (3, 0)}), diff --git a/pymode/libs/pylint/checkers/raw_metrics.py b/pymode/libs/pylint/checkers/raw_metrics.py index e60ef461..2cceee7e 100644 --- a/pymode/libs/pylint/checkers/raw_metrics.py +++ b/pymode/libs/pylint/checkers/raw_metrics.py @@ -1,5 +1,6 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2007, 2010, 2013, 2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -11,12 +12,8 @@ import tokenize -# pylint now requires pylint >= 2.2, so this is no longer necessary -#if not hasattr(tokenize, 'NL'): -# raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") - from pylint.interfaces import ITokenChecker -from pylint.utils import EmptyReport +from pylint.exceptions import EmptyReportError from pylint.checkers import BaseTokenChecker from pylint.reporters import diff_string from pylint.reporters.ureports.nodes import Table @@ -27,7 +24,7 @@ def report_raw_stats(sect, stats, old_stats): """ total_lines = stats['total_lines'] if not total_lines: - raise EmptyReport() + raise EmptyReportError() sect.description = '%s lines have been analyzed' % total_lines lines = ('type', 'number', '%', 'previous', 'difference') for node_type in ('code', 'docstring', 'comment', 'empty'): diff --git a/pymode/libs/pylint/checkers/refactoring.py b/pymode/libs/pylint/checkers/refactoring.py new file mode 100644 index 00000000..418e63ef --- /dev/null +++ b/pymode/libs/pylint/checkers/refactoring.py @@ -0,0 +1,715 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2016 Moisés López +# Copyright (c) 2016 Claudiu Popa +# Copyright (c) 2016 Alexander Todorov + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +"""Looks for code which can be refactored.""" + +import collections +import itertools +import tokenize + +import astroid +from astroid import decorators +import six + +from pylint import interfaces +from pylint import checkers +from pylint import utils as lint_utils +from pylint.checkers import utils + + +def _all_elements_are_true(gen): + values = list(gen) + return values and all(values) + + +def _if_statement_is_always_returning(if_node): + def _has_return_node(elems, scope): + for node in elems: + if isinstance(node, astroid.If): + yield _if_statement_is_always_returning(node) + elif isinstance(node, astroid.Return): + yield node.scope() is scope + + scope = if_node.scope() + body_returns = _all_elements_are_true( + _has_return_node(if_node.body, scope=scope) + ) + if if_node.orelse: + orelse_returns = _all_elements_are_true( + _has_return_node(if_node.orelse, scope=scope) + ) + else: + orelse_returns = False + + return body_returns and orelse_returns + + +class RefactoringChecker(checkers.BaseTokenChecker): + """Looks for code which can be refactored + + This checker also mixes the astroid and the token approaches + in order to create knowledge about whether a "else if" node + is a true "else if" node, or a "elif" node. + """ + + __implements__ = (interfaces.ITokenChecker, interfaces.IAstroidChecker) + + name = 'refactoring' + + msgs = { + 'R1701': ("Consider merging these isinstance calls to isinstance(%s, (%s))", + "consider-merging-isinstance", + "Used when multiple consecutive isinstance calls can be merged into one."), + 'R1706': ("Consider using ternary (%s if %s else %s)", + "consider-using-ternary", + "Used when one of known pre-python 2.5 ternary syntax is used."), + 'R1702': ('Too many nested blocks (%s/%s)', + 'too-many-nested-blocks', + 'Used when a function or a method has too many nested ' + 'blocks. This makes the code less understandable and ' + 'maintainable.', + {'old_names': [('R0101', 'too-many-nested-blocks')]}), + 'R1703': ('The if statement can be replaced with %s', + 'simplifiable-if-statement', + 'Used when an if statement can be replaced with ' + '\'bool(test)\'. ', + {'old_names': [('R0102', 'simplifiable-if-statement')]}), + 'R1704': ('Redefining argument with the local name %r', + 'redefined-argument-from-local', + 'Used when a local name is redefining an argument, which might ' + 'suggest a potential error. This is taken in account only for ' + 'a handful of name binding operations, such as for iteration, ' + 'with statement assignment and exception handler assignment.' + ), + 'R1705': ('Unnecessary "else" after "return"', + 'no-else-return', + 'Used in order to highlight an unnecessary block of ' + 'code following an if containing a return statement. ' + 'As such, it will warn when it encounters an else ' + 'following a chain of ifs, all of them containing a ' + 'return statement.' + ), + 'R1707': ('Disallow trailing comma tuple', + 'trailing-comma-tuple', + 'In Python, a tuple is actually created by the comma symbol, ' + 'not by the parentheses. Unfortunately, one can actually create a ' + 'tuple by misplacing a trailing comma, which can lead to potential ' + 'weird bugs in your code. You should always use parentheses ' + 'explicitly for creating a tuple.', + {'minversion': (3, 0)}), + } + options = (('max-nested-blocks', + {'default': 5, 'type': 'int', 'metavar': '', + 'help': 'Maximum number of nested blocks for function / ' + 'method body'} + ),) + + priority = 0 + + def __init__(self, linter=None): + checkers.BaseTokenChecker.__init__(self, linter) + self._init() + + def _init(self): + self._nested_blocks = [] + self._elifs = [] + self._if_counter = 0 + self._nested_blocks_msg = None + + @decorators.cachedproperty + def _dummy_rgx(self): + return lint_utils.get_global_option( + self, 'dummy-variables-rgx', default=None) + + @staticmethod + def _is_bool_const(node): + return (isinstance(node.value, astroid.Const) + and isinstance(node.value.value, bool)) + + def _is_actual_elif(self, node): + """Check if the given node is an actual elif + + This is a problem we're having with the builtin ast module, + which splits `elif` branches into a separate if statement. + Unfortunately we need to know the exact type in certain + cases. + """ + + if isinstance(node.parent, astroid.If): + orelse = node.parent.orelse + # current if node must directly follow a "else" + if orelse and orelse == [node]: + if self._elifs[self._if_counter]: + return True + return False + + def _check_simplifiable_if(self, node): + """Check if the given if node can be simplified. + + The if statement can be reduced to a boolean expression + in some cases. For instance, if there are two branches + and both of them return a boolean value that depends on + the result of the statement's test, then this can be reduced + to `bool(test)` without losing any functionality. + """ + + if self._is_actual_elif(node): + # Not interested in if statements with multiple branches. + return + if len(node.orelse) != 1 or len(node.body) != 1: + return + + # Check if both branches can be reduced. + first_branch = node.body[0] + else_branch = node.orelse[0] + if isinstance(first_branch, astroid.Return): + if not isinstance(else_branch, astroid.Return): + return + first_branch_is_bool = self._is_bool_const(first_branch) + else_branch_is_bool = self._is_bool_const(else_branch) + reduced_to = "'return bool(test)'" + elif isinstance(first_branch, astroid.Assign): + if not isinstance(else_branch, astroid.Assign): + return + first_branch_is_bool = self._is_bool_const(first_branch) + else_branch_is_bool = self._is_bool_const(else_branch) + reduced_to = "'var = bool(test)'" + else: + return + + if not first_branch_is_bool or not else_branch_is_bool: + return + if not first_branch.value.value: + # This is a case that can't be easily simplified and + # if it can be simplified, it will usually result in a + # code that's harder to understand and comprehend. + # Let's take for instance `arg and arg <= 3`. This could theoretically be + # reduced to `not arg or arg > 3`, but the net result is that now the + # condition is harder to understand, because it requires understanding of + # an extra clause: + # * first, there is the negation of truthness with `not arg` + # * the second clause is `arg > 3`, which occurs when arg has a + # a truth value, but it implies that `arg > 3` is equivalent + # with `arg and arg > 3`, which means that the user must + # think about this assumption when evaluating `arg > 3`. + # The original form is easier to grasp. + return + + self.add_message('simplifiable-if-statement', node=node, + args=(reduced_to,)) + + def process_tokens(self, tokens): + # Process tokens and look for 'if' or 'elif' + for index, token in enumerate(tokens): + token_string = token[1] + if token_string == 'elif': + self._elifs.append(True) + elif token_string == 'if': + self._elifs.append(False) + elif six.PY3 and token.exact_type == tokenize.COMMA: + self._check_one_element_trailing_comma_tuple(tokens, token, index) + + def _check_one_element_trailing_comma_tuple(self, tokens, token, index): + left_tokens = itertools.islice(tokens, index + 1, None) + same_line_remaining_tokens = list( + other_token for other_token in left_tokens + if other_token.start[0] == token.start[0] + ) + is_last_element = all( + other_token.type in (tokenize.NEWLINE, tokenize.COMMENT) + for other_token in same_line_remaining_tokens + ) + + if not same_line_remaining_tokens or not is_last_element: + return + + assign_token = tokens[index-2:index-1] + if assign_token and '=' in assign_token[0].string: + if self.linter.is_message_enabled('trailing-comma-tuple'): + self.add_message('trailing-comma-tuple', + line=token.start[0]) + + def leave_module(self, _): + self._init() + + @utils.check_messages('too-many-nested-blocks') + def visit_tryexcept(self, node): + self._check_nested_blocks(node) + + visit_tryfinally = visit_tryexcept + visit_while = visit_tryexcept + + def _check_redefined_argument_from_local(self, name_node): + if self._dummy_rgx and self._dummy_rgx.match(name_node.name): + return + if not name_node.lineno: + # Unknown position, maybe it is a manually built AST? + return + + scope = name_node.scope() + if not isinstance(scope, astroid.FunctionDef): + return + + for defined_argument in scope.args.nodes_of_class(astroid.AssignName): + if defined_argument.name == name_node.name: + self.add_message('redefined-argument-from-local', + node=name_node, + args=(name_node.name, )) + + @utils.check_messages('redefined-argument-from-local', + 'too-many-nested-blocks') + def visit_for(self, node): + self._check_nested_blocks(node) + + for name in node.target.nodes_of_class(astroid.AssignName): + self._check_redefined_argument_from_local(name) + + @utils.check_messages('redefined-argument-from-local') + def visit_excepthandler(self, node): + if node.name and isinstance(node.name, astroid.AssignName): + self._check_redefined_argument_from_local(node.name) + + @utils.check_messages('redefined-argument-from-local') + def visit_with(self, node): + for _, names in node.items: + if not names: + continue + for name in names.nodes_of_class(astroid.AssignName): + self._check_redefined_argument_from_local(name) + + def visit_ifexp(self, _): + self._if_counter += 1 + + def visit_comprehension(self, node): + self._if_counter += len(node.ifs) + + def _check_superfluous_else_return(self, node): + if not node.orelse: + # Not interested in if statements without else. + return + + if _if_statement_is_always_returning(node) and not self._is_actual_elif(node): + self.add_message('no-else-return', node=node) + + @utils.check_messages('too-many-nested-blocks', 'simplifiable-if-statement', + 'no-else-return',) + def visit_if(self, node): + self._check_simplifiable_if(node) + self._check_nested_blocks(node) + self._check_superfluous_else_return(node) + self._if_counter += 1 + + @utils.check_messages('too-many-nested-blocks') + def leave_functiondef(self, _): + # check left-over nested blocks stack + self._emit_nested_blocks_message_if_needed(self._nested_blocks) + # new scope = reinitialize the stack of nested blocks + self._nested_blocks = [] + + def _check_nested_blocks(self, node): + """Update and check the number of nested blocks + """ + # only check block levels inside functions or methods + if not isinstance(node.scope(), astroid.FunctionDef): + return + # messages are triggered on leaving the nested block. Here we save the + # stack in case the current node isn't nested in the previous one + nested_blocks = self._nested_blocks[:] + if node.parent == node.scope(): + self._nested_blocks = [node] + else: + # go through ancestors from the most nested to the less + for ancestor_node in reversed(self._nested_blocks): + if ancestor_node == node.parent: + break + self._nested_blocks.pop() + # if the node is a elif, this should not be another nesting level + if isinstance(node, astroid.If) and self._elifs[self._if_counter]: + if self._nested_blocks: + self._nested_blocks.pop() + self._nested_blocks.append(node) + + # send message only once per group of nested blocks + if len(nested_blocks) > len(self._nested_blocks): + self._emit_nested_blocks_message_if_needed(nested_blocks) + + def _emit_nested_blocks_message_if_needed(self, nested_blocks): + if len(nested_blocks) > self.config.max_nested_blocks: + self.add_message('too-many-nested-blocks', node=nested_blocks[0], + args=(len(nested_blocks), self.config.max_nested_blocks)) + + @staticmethod + def _duplicated_isinstance_types(node): + """Get the duplicated types from the underlying isinstance calls. + + :param astroid.BoolOp node: Node which should contain a bunch of isinstance calls. + :returns: Dictionary of the comparison objects from the isinstance calls, + to duplicate values from consecutive calls. + :rtype: dict + """ + duplicated_objects = set() + all_types = collections.defaultdict(set) + + for call in node.values: + if not isinstance(call, astroid.Call) or len(call.args) != 2: + continue + + inferred = utils.safe_infer(call.func) + if not inferred or not utils.is_builtin_object(inferred): + continue + + if inferred.name != 'isinstance': + continue + + isinstance_object = call.args[0].as_string() + isinstance_types = call.args[1] + + if isinstance_object in all_types: + duplicated_objects.add(isinstance_object) + + if isinstance(isinstance_types, astroid.Tuple): + elems = [class_type.as_string() for class_type in isinstance_types.itered()] + else: + elems = [isinstance_types.as_string()] + all_types[isinstance_object].update(elems) + + # Remove all keys which not duplicated + return {key: value for key, value in all_types.items() + if key in duplicated_objects} + + @utils.check_messages('consider-merging-isinstance') + def visit_boolop(self, node): + '''Check isinstance calls which can be merged together.''' + if node.op != 'or': + return + + first_args = self._duplicated_isinstance_types(node) + for duplicated_name, class_names in first_args.items(): + names = sorted(name for name in class_names) + self.add_message('consider-merging-isinstance', + node=node, + args=(duplicated_name, ', '.join(names))) + + @utils.check_messages('consider-using-ternary') + def visit_assign(self, node): + if self._is_and_or_ternary(node.value): + cond, truth_value, false_value = self._and_or_ternary_arguments(node.value) + elif self._is_seq_based_ternary(node.value): + cond, truth_value, false_value = self._seq_based_ternary_params(node.value) + else: + return + + self.add_message( + 'consider-using-ternary', node=node, + args=(truth_value.as_string(), + cond.as_string(), + false_value.as_string()),) + + visit_return = visit_assign + + @staticmethod + def _is_and_or_ternary(node): + """ + Returns true if node is 'condition and true_value else false_value' form. + + All of: condition, true_value and false_value should not be a complex boolean expression + """ + return (isinstance(node, astroid.BoolOp) + and node.op == 'or' and len(node.values) == 2 + and isinstance(node.values[0], astroid.BoolOp) + and not isinstance(node.values[1], astroid.BoolOp) + and node.values[0].op == 'and' + and not isinstance(node.values[0].values[1], astroid.BoolOp) + and len(node.values[0].values) == 2) + + @staticmethod + def _and_or_ternary_arguments(node): + false_value = node.values[1] + condition, true_value = node.values[0].values + return condition, true_value, false_value + + @staticmethod + def _is_seq_based_ternary(node): + """Returns true if node is '[false_value,true_value][condition]' form""" + return (isinstance(node, astroid.Subscript) + and isinstance(node.value, (astroid.Tuple, astroid.List)) + and len(node.value.elts) == 2 and isinstance(node.slice, astroid.Index)) + + @staticmethod + def _seq_based_ternary_params(node): + false_value, true_value = node.value.elts + condition = node.slice.value + return condition, true_value, false_value + + +class RecommandationChecker(checkers.BaseChecker): + __implements__ = (interfaces.IAstroidChecker,) + name = 'refactoring' + msgs = {'C0200': ('Consider using enumerate instead of iterating with range and len', + 'consider-using-enumerate', + 'Emitted when code that iterates with range and len is ' + 'encountered. Such code can be simplified by using the ' + 'enumerate builtin.'), + 'C0201': ('Consider iterating the dictionary directly instead of calling .keys()', + 'consider-iterating-dictionary', + 'Emitted when the keys of a dictionary are iterated through the .keys() ' + 'method. It is enough to just iterate through the dictionary itself, as ' + 'in "for key in dictionary".'), + } + + @staticmethod + def _is_builtin(node, function): + inferred = utils.safe_infer(node) + if not inferred: + return False + return utils.is_builtin_object(inferred) and inferred.name == function + + @utils.check_messages('consider-iterating-dictionary') + def visit_call(self, node): + inferred = utils.safe_infer(node.func) + if not inferred: + return + + if not isinstance(inferred, astroid.BoundMethod): + return + if not isinstance(inferred.bound, astroid.Dict) or inferred.name != 'keys': + return + + if isinstance(node.parent, (astroid.For, astroid.Comprehension)): + self.add_message('consider-iterating-dictionary', node=node) + + @utils.check_messages('consider-using-enumerate') + def visit_for(self, node): + """Emit a convention whenever range and len are used for indexing.""" + # Verify that we have a `range(len(...))` call and that the object + # which is iterated is used as a subscript in the body of the for. + + # Is it a proper range call? + if not isinstance(node.iter, astroid.Call): + return + if not self._is_builtin(node.iter.func, 'range'): + return + if len(node.iter.args) != 1: + return + + # Is it a proper len call? + if not isinstance(node.iter.args[0], astroid.Call): + return + second_func = node.iter.args[0].func + if not self._is_builtin(second_func, 'len'): + return + len_args = node.iter.args[0].args + if not len_args or len(len_args) != 1: + return + iterating_object = len_args[0] + if not isinstance(iterating_object, astroid.Name): + return + + # Verify that the body of the for loop uses a subscript + # with the object that was iterated. This uses some heuristics + # in order to make sure that the same object is used in the + # for body. + for child in node.body: + for subscript in child.nodes_of_class(astroid.Subscript): + if not isinstance(subscript.value, astroid.Name): + continue + if not isinstance(subscript.slice, astroid.Index): + continue + if not isinstance(subscript.slice.value, astroid.Name): + continue + if subscript.slice.value.name != node.target.name: + continue + if iterating_object.name != subscript.value.name: + continue + if subscript.value.scope() != node.scope(): + # Ignore this subscript if it's not in the same + # scope. This means that in the body of the for + # loop, another scope was created, where the same + # name for the iterating object was used. + continue + self.add_message('consider-using-enumerate', node=node) + return + + +class NotChecker(checkers.BaseChecker): + """checks for too many not in comparison expressions + + - "not not" should trigger a warning + - "not" followed by a comparison should trigger a warning + """ + __implements__ = (interfaces.IAstroidChecker,) + msgs = {'C0113': ('Consider changing "%s" to "%s"', + 'unneeded-not', + 'Used when a boolean expression contains an unneeded ' + 'negation.'), + } + name = 'basic' + reverse_op = {'<': '>=', '<=': '>', '>': '<=', '>=': '<', '==': '!=', + '!=': '==', 'in': 'not in', 'is': 'is not'} + # sets are not ordered, so for example "not set(LEFT_VALS) <= set(RIGHT_VALS)" is + # not equivalent to "set(LEFT_VALS) > set(RIGHT_VALS)" + skipped_nodes = (astroid.Set,) + # 'builtins' py3, '__builtin__' py2 + skipped_classnames = ['%s.%s' % (six.moves.builtins.__name__, qname) + for qname in ('set', 'frozenset')] + + @utils.check_messages('unneeded-not') + def visit_unaryop(self, node): + if node.op != 'not': + return + operand = node.operand + + if isinstance(operand, astroid.UnaryOp) and operand.op == 'not': + self.add_message('unneeded-not', node=node, + args=(node.as_string(), + operand.operand.as_string())) + elif isinstance(operand, astroid.Compare): + left = operand.left + # ignore multiple comparisons + if len(operand.ops) > 1: + return + operator, right = operand.ops[0] + if operator not in self.reverse_op: + return + # Ignore __ne__ as function of __eq__ + frame = node.frame() + if frame.name == '__ne__' and operator == '==': + return + for _type in (utils.node_type(left), utils.node_type(right)): + if not _type: + return + if isinstance(_type, self.skipped_nodes): + return + if (isinstance(_type, astroid.Instance) and + _type.qname() in self.skipped_classnames): + return + suggestion = '%s %s %s' % (left.as_string(), + self.reverse_op[operator], + right.as_string()) + self.add_message('unneeded-not', node=node, + args=(node.as_string(), suggestion)) + + +def _is_len_call(node): + """Checks if node is len(SOMETHING).""" + return (isinstance(node, astroid.Call) and isinstance(node.func, astroid.Name) and + node.func.name == 'len') + +def _is_constant_zero(node): + return isinstance(node, astroid.Const) and node.value == 0 + +def _node_is_test_condition(node): + """ Checks if node is an if, while, assert or if expression statement.""" + return isinstance(node, (astroid.If, astroid.While, astroid.Assert, astroid.IfExp)) + + +class LenChecker(checkers.BaseChecker): + """Checks for incorrect usage of len() inside conditions. + Pep8 states: + For sequences, (strings, lists, tuples), use the fact that empty sequences are false. + + Yes: if not seq: + if seq: + + No: if len(seq): + if not len(seq): + + Problems detected: + * if len(sequence): + * if not len(sequence): + * if len(sequence) == 0: + * if len(sequence) != 0: + * if len(sequence) > 0: + """ + + __implements__ = (interfaces.IAstroidChecker,) + + # configuration section name + name = 'len' + msgs = {'C1801': ('Do not use `len(SEQUENCE)` as condition value', + 'len-as-condition', + 'Used when Pylint detects incorrect use of len(sequence) inside ' + 'conditions.'), + } + + priority = -2 + options = () + + @utils.check_messages('len-as-condition') + def visit_call(self, node): + # a len(S) call is used inside a test condition + # could be if, while, assert or if expression statement + # e.g. `if len(S):` + if _is_len_call(node): + # the len() call could also be nested together with other + # boolean operations, e.g. `if z or len(x):` + parent = node.parent + while isinstance(parent, astroid.BoolOp): + parent = parent.parent + + # we're finally out of any nested boolean operations so check if + # this len() call is part of a test condition + if not _node_is_test_condition(parent): + return + if not (node is parent.test or parent.test.parent_of(node)): + return + self.add_message('len-as-condition', node=node) + + @utils.check_messages('len-as-condition') + def visit_unaryop(self, node): + """`not len(S)` must become `not S` regardless if the parent block + is a test condition or something else (boolean expression) + e.g. `if not len(S):`""" + if isinstance(node, astroid.UnaryOp) and node.op == 'not' and _is_len_call(node.operand): + self.add_message('len-as-condition', node=node) + + @utils.check_messages('len-as-condition') + def visit_compare(self, node): + # compare nodes are trickier because the len(S) expression + # may be somewhere in the middle of the node + + # note: astroid.Compare has the left most operand in node.left + # while the rest are a list of tuples in node.ops + # the format of the tuple is ('compare operator sign', node) + # here we squash everything into `ops` to make it easier for processing later + ops = [('', node.left)] + ops.extend(node.ops) + ops = list(itertools.chain(*ops)) + + for ops_idx in range(len(ops) - 2): + op_1 = ops[ops_idx] + op_2 = ops[ops_idx + 1] + op_3 = ops[ops_idx + 2] + error_detected = False + + # 0 ?? len() + if _is_constant_zero(op_1) and op_2 in ['==', '!=', '<'] and _is_len_call(op_3): + error_detected = True + # len() ?? 0 + elif _is_len_call(op_1) and op_2 in ['==', '!=', '>'] and _is_constant_zero(op_3): + error_detected = True + + if error_detected: + parent = node.parent + # traverse the AST to figure out if this comparison was part of + # a test condition + while parent and not _node_is_test_condition(parent): + parent = parent.parent + + # report only if this len() comparison is part of a test condition + # for example: return len() > 0 should not report anything + if _node_is_test_condition(parent): + self.add_message('len-as-condition', node=node) + + +def register(linter): + """Required method to auto register this checker.""" + linter.register_checker(RefactoringChecker(linter)) + linter.register_checker(NotChecker(linter)) + linter.register_checker(RecommandationChecker(linter)) + linter.register_checker(LenChecker(linter)) diff --git a/pymode/libs/pylint/checkers/similar.py b/pymode/libs/pylint/checkers/similar.py index 71897f44..aa59bfd8 100644 --- a/pymode/libs/pylint/checkers/similar.py +++ b/pymode/libs/pylint/checkers/similar.py @@ -1,5 +1,6 @@ -# Copyright (c) 2004-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2008-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/checkers/spelling.py b/pymode/libs/pylint/checkers/spelling.py index 3f748b8b..7b0eb8f2 100644 --- a/pymode/libs/pylint/checkers/spelling.py +++ b/pymode/libs/pylint/checkers/spelling.py @@ -1,5 +1,7 @@ -# Copyright (c) 2014-2016 Michal Nowikowski -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2014 Michal Nowikowski +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Pavel Roskin + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -7,15 +9,20 @@ """ import os -import re +import sys import tokenize import string -import sys +import re try: import enchant + from enchant.tokenize import get_tokenizer, Filter, EmailFilter, URLFilter, WikiWordFilter except ImportError: enchant = None + class Filter: + def _skip(self, word): + raise NotImplementedError + import six from pylint.interfaces import ITokenChecker, IAstroidChecker @@ -42,6 +49,26 @@ table = maketrans("", "") +class WordsWithDigigtsFilter(Filter): + """Skips words with digits. + """ + + def _skip(self, word): + for char in word: + if char.isdigit(): + return True + return False + + +class WordsWithUnderscores(Filter): + """Skips words with underscores. + + They are probably function parameter names. + """ + def _skip(self, word): + return '_' in word + + class SpellingChecker(BaseTokenChecker): """Check spelling in comments and docstrings""" __implements__ = (ITokenChecker, IAstroidChecker) @@ -119,6 +146,11 @@ def open(self): # ' and _ are treated in a special way. puncts = string.punctuation.replace("'", "").replace("_", "") self.punctuation_regex = re.compile('[%s]' % re.escape(puncts)) + self.tokenizer = get_tokenizer(dict_name, filters=[EmailFilter, + URLFilter, + WikiWordFilter, + WordsWithDigigtsFilter, + WordsWithUnderscores]) self.initialized = True def close(self): @@ -126,35 +158,7 @@ def close(self): self.private_dict_file.close() def _check_spelling(self, msgid, line, line_num): - line2 = line.strip() - # Replace ['afadf with afadf (but preserve don't) - line2 = re.sub("'([^a-zA-Z]|$)", " ", line2) - # Replace afadf'] with afadf (but preserve don't) - line2 = re.sub("([^a-zA-Z]|^)'", " ", line2) - # Replace punctuation signs with space e.g. and/or -> and or - line2 = self.punctuation_regex.sub(' ', line2) - - words = [] - for word in line2.split(): - # Skip words with digits. - if len(re.findall(r"\d", word)) > 0: - continue - - # Skip words with mixed big and small letters, - # they are probaly class names. - if (len(re.findall("[A-Z]", word)) > 0 and - len(re.findall("[a-z]", word)) > 0 and - len(word) > 2): - continue - - # Skip words with _ - they are probably function parameter names. - if word.count('_') > 0: - continue - - words.append(word) - - # Go through words and check them. - for word in words: + for word, _ in self.tokenizer(line.strip()): # Skip words from ignore list. if word in self.ignore_list: continue @@ -200,7 +204,7 @@ def _check_spelling(self, msgid, line, line_num): self.add_message(msgid, line=line_num, args=(orig_word, line, indicator, - "' or '".join(suggestions))) + "'{0}'".format("' or '".join(suggestions)))) def process_tokens(self, tokens): if not self.initialized: @@ -209,6 +213,12 @@ def process_tokens(self, tokens): # Process tokens and look for comments. for (tok_type, token, (start_row, _), _, _) in tokens: if tok_type == tokenize.COMMENT: + if start_row == 1 and token.startswith('#!/'): + # Skip shebang lines + continue + if token.startswith('# pylint:'): + # Skip pylint enable/disable comments + continue self._check_spelling('wrong-spelling-in-comment', token, start_row) diff --git a/pymode/libs/pylint/checkers/stdlib.py b/pymode/libs/pylint/checkers/stdlib.py index 5d814282..38282c27 100644 --- a/pymode/libs/pylint/checkers/stdlib.py +++ b/pymode/libs/pylint/checkers/stdlib.py @@ -1,5 +1,9 @@ -# Copyright (c) 2012-2016 Google, Inc. -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Vlad Temian +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Cezar +# Copyright (c) 2015 Chris Rebert + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -166,6 +170,9 @@ class StdlibChecker(BaseChecker): 'inspect.getcallargs', 'platform.linux_distribution', 'platform.dist', ], + (3, 6, 0): [ + 'importlib._bootstrap_external.FileLoader.load_module', + ], }, } diff --git a/pymode/libs/pylint/checkers/strings.py b/pymode/libs/pylint/checkers/strings.py index 3100675f..8135b412 100644 --- a/pymode/libs/pylint/checkers/strings.py +++ b/pymode/libs/pylint/checkers/strings.py @@ -1,17 +1,18 @@ -# Copyright (c) 2009-2010 Arista Networks, Inc. - James Lingard -# Copyright (c) 2004-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2009-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa + + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """Checker for string formatting operations. """ -import numbers +import sys import tokenize import string -import sys +import numbers import six @@ -88,7 +89,7 @@ 'W1305': ("Format string contains both automatic field numbering " "and manual field specification", "format-combined-specification", - "Usen when a PEP 3101 format string contains both automatic " + "Used when a PEP 3101 format string contains both automatic " "field numbering (e.g. '{}') and manual field " "specification (e.g. '{0}').", {'minversion': (2, 7)}), @@ -124,7 +125,10 @@ def _field_iterator_convertor(iterator): yield is_attr, key def split_format_field_names(format_string): - keyname, fielditerator = format_string._formatter_field_name_split() + try: + keyname, fielditerator = format_string._formatter_field_name_split() + except ValueError: + raise utils.IncompleteFormatString # it will return longs, instead of ints, which will complicate # the output return keyname, _field_iterator_convertor(fielditerator) @@ -184,7 +188,10 @@ def parse_format_method_string(format_string): # to different output between 2 and 3 manual_pos_arg.add(str(keyname)) keyname = int(keyname) - keys.append((keyname, list(fielditerator))) + try: + keys.append((keyname, list(fielditerator))) + except ValueError: + raise utils.IncompleteFormatString() else: num_args += 1 return keys, num_args, len(manual_pos_arg) @@ -271,7 +278,7 @@ def visit_binop(self, node): else: # One of the keys was something other than a # constant. Since we can't tell what it is, - # supress checks for missing keys in the + # suppress checks for missing keys in the # dictionary. unknown_keys = True if not unknown_keys: @@ -297,7 +304,10 @@ def visit_binop(self, node): # the % operator matches the number required by the format # string. if isinstance(args, astroid.Tuple): - num_args = len(args.elts) + rhs_tuple = utils.safe_infer(args) + num_args = None + if rhs_tuple not in (None, astroid.Uninferable): + num_args = len(rhs_tuple.elts) elif isinstance(args, OTHER_NODES + (astroid.Dict, astroid.DictComp)): num_args = 1 else: @@ -471,11 +481,15 @@ def _check_new_format_specifiers(self, node, fields, named): warn_error = False if hasattr(previous, 'getitem'): try: - previous = previous.getitem(specifier) - except (IndexError, TypeError): + previous = previous.getitem(astroid.Const(specifier)) + except (astroid.AstroidIndexError, + astroid.AstroidTypeError, + astroid.AttributeInferenceError): warn_error = True except astroid.InferenceError: break + if previous is astroid.Uninferable: + break else: try: # Lookup __getitem__ in the current node, @@ -499,7 +513,6 @@ def _check_new_format_specifiers(self, node, fields, named): break - class StringConstantChecker(BaseTokenChecker): """Check string literals""" __implements__ = (ITokenChecker, IRawChecker) diff --git a/pymode/libs/pylint/checkers/typecheck.py b/pymode/libs/pylint/checkers/typecheck.py index 25b9b71a..8ae8f446 100644 --- a/pymode/libs/pylint/checkers/typecheck.py +++ b/pymode/libs/pylint/checkers/typecheck.py @@ -1,5 +1,15 @@ -# Copyright (c) 2006-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# -*- coding: utf-8 -*- +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014, 2016 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014 Holger Peters +# Copyright (c) 2014 David Shea +# Copyright (c) 2015 Radu Ciorba +# Copyright (c) 2015 Rene Zhang +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2016 Jakub Wilk +# Copyright (c) 2016 Jürgen Hermann + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -8,6 +18,9 @@ import collections import fnmatch +import heapq +import itertools +import operator import re import shlex import sys @@ -17,20 +30,27 @@ import astroid import astroid.context import astroid.arguments +import astroid.nodes from astroid import exceptions +from astroid.interpreter import dunder_lookup from astroid import objects from astroid import bases -from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE +from pylint.interfaces import IAstroidChecker, INFERENCE from pylint.checkers import BaseChecker from pylint.checkers.utils import ( is_super, check_messages, decorated_with_property, decorated_with, node_ignores_exception, is_iterable, is_mapping, supports_membership_test, is_comprehension, is_inside_abstract_class, - supports_subscript, + supports_getitem, + supports_setitem, + supports_delitem, safe_infer, - has_known_bases) + has_known_bases, + is_builtin_object, + singledispatch) + BUILTINS = six.moves.builtins.__name__ STR_FORMAT = "%s.str.format" % BUILTINS @@ -40,8 +60,8 @@ def _unflatten(iterable): for index, elem in enumerate(iterable): if (isinstance(elem, collections.Sequence) and not isinstance(elem, six.string_types)): - for elem in _unflatten(elem): - yield elem + for single_elem in _unflatten(elem): + yield single_elem elif elem and not index: # We're interested only in the first element. yield elem @@ -75,8 +95,90 @@ def _is_owner_ignored(owner, name, ignored_classes, ignored_modules): return any(name == ignore or qname == ignore for ignore in ignored_classes) +@singledispatch +def _node_names(node): + # TODO: maybe we need an ABC for checking if an object is a scoped node + # or not? + if not hasattr(node, 'locals'): + return [] + return node.locals.keys() + + +@_node_names.register(astroid.ClassDef) +@_node_names.register(astroid.Instance) +def _(node): + values = itertools.chain(node.instance_attrs.keys(), node.locals.keys()) + + try: + mro = node.mro()[1:] + except (NotImplementedError, TypeError): + mro = node.ancestors() + + other_values = [value for cls in mro for value in _node_names(cls)] + return itertools.chain(values, other_values) + + +def _string_distance(seq1, seq2): + seq2_length = len(seq2) + + row = list(range(1, seq2_length + 1)) + [0] + for seq1_index, seq1_char in enumerate(seq1): + last_row = row + row = [0] * seq2_length + [seq1_index + 1] + + for seq2_index, seq2_char in enumerate(seq2): + row[seq2_index] = min( + last_row[seq2_index] + 1, + row[seq2_index - 1] + 1, + last_row[seq2_index - 1] + (seq1_char != seq2_char) + + ) + + return row[seq2_length - 1] + + +def _similar_names(owner, attrname, distance_threshold, max_choices): + """Given an owner and a name, try to find similar names + + The similar names are searched given a distance metric and only + a given number of choices will be returned. + """ + possible_names = [] + names = _node_names(owner) + + for name in names: + if name == attrname: + continue + + distance = _string_distance(attrname, name) + if distance <= distance_threshold: + possible_names.append((name, distance)) + + # Now get back the values with a minimum, up to the given + # limit or choices. + picked = [name for (name, _) in + heapq.nsmallest(max_choices, possible_names, + key=operator.itemgetter(1))] + return sorted(picked) + + +def _missing_member_hint(owner, attrname, distance_threshold, max_choices): + names = _similar_names(owner, attrname, distance_threshold, max_choices) + if not names: + # No similar name. + return "" + + names = list(map(repr, names)) + if len(names) == 1: + names = ", ".join(names) + else: + names = "one of {} or {}".format(", ".join(names[:-1]), names[-1]) + + return "; maybe {}?".format(names) + + MSGS = { - 'E1101': ('%s %r has no %r member', + 'E1101': ('%s %r has no %r member%s', 'no-member', 'Used when a variable is accessed for an unexistent member.', {'old_names': [('E1103', 'maybe-no-member')]}), @@ -129,7 +231,7 @@ def _is_owner_ignored(owner, name, ignored_classes, ignored_modules): 'the context manager protocol(__enter__/__exit__).'), 'E1130': ('%s', 'invalid-unary-operand-type', - 'Emitted when an unary operand is used on an object which does not ' + 'Emitted when a unary operand is used on an object which does not ' 'support this type of operation'), 'E1131': ('%s', 'unsupported-binary-operation', @@ -140,12 +242,25 @@ def _is_owner_ignored(owner, name, ignored_classes, ignored_modules): 'Emitted when a function call got multiple values for a keyword.'), 'E1135': ("Value '%s' doesn't support membership test", 'unsupported-membership-test', - 'Emitted when an instance in membership test expression doesn\'t' + 'Emitted when an instance in membership test expression doesn\'t ' 'implement membership protocol (__contains__/__iter__/__getitem__)'), 'E1136': ("Value '%s' is unsubscriptable", 'unsubscriptable-object', "Emitted when a subscripted value doesn't support subscription" "(i.e. doesn't define __getitem__ method)"), + 'E1137': ("%r does not support item assignment", + 'unsupported-assignment-operation', + "Emitted when an object does not support item assignment " + "(i.e. doesn't define __setitem__ method)"), + 'E1138': ("%r does not support item deletion", + 'unsupported-delete-operation', + "Emitted when an object does not support item deletion " + "(i.e. doesn't define __delitem__ method)"), + 'E1139': ('Invalid metaclass %r used', + 'invalid-metaclass', + 'Emitted whenever we can detect that a class is using, ' + 'as a metaclass, something which might be invalid for using as ' + 'a metaclass.'), } # builtin sequence types in Python 2 and 3. @@ -176,7 +291,7 @@ def _emit_no_member(node, owner, owner_name, ignored_mixins): return False if isinstance(owner, astroid.FunctionDef) and owner.decorators: return False - if isinstance(owner, astroid.Instance): + if isinstance(owner, (astroid.Instance, astroid.ClassDef)): if owner.has_dynamic_getattr() or not has_known_bases(owner): return False if isinstance(owner, objects.Super): @@ -237,6 +352,134 @@ def _determine_callable(callable_obj): else: raise ValueError + +def _has_parent_of_type(node, node_type, statement): + """Check if the given node has a parent of the given type.""" + parent = node.parent + while not isinstance(parent, node_type) and statement.parent_of(parent): + parent = parent.parent + return isinstance(parent, node_type) + + +def _is_name_used_as_variadic(name, variadics): + """Check if the given name is used as a variadic argument.""" + return any(variadic.value == name or variadic.value.parent_of(name) + for variadic in variadics) + + +def _no_context_variadic_keywords(node): + statement = node.statement() + scope = node.scope() + variadics = () + + if not isinstance(scope, astroid.FunctionDef): + return False + + if isinstance(statement, astroid.Expr) and isinstance(statement.value, astroid.Call): + call = statement.value + variadics = call.keywords or () + + return _no_context_variadic(node, scope.args.kwarg, astroid.Keyword, variadics) + + +def _no_context_variadic_positional(node): + statement = node.statement() + scope = node.scope() + variadics = () + + if not isinstance(scope, astroid.FunctionDef): + return False + + if isinstance(statement, astroid.Expr) and isinstance(statement.value, astroid.Call): + call = statement.value + variadics = call.starargs + + return _no_context_variadic(node, scope.args.vararg, astroid.Starred, variadics) + + +def _no_context_variadic(node, variadic_name, variadic_type, variadics): + """Verify if the given call node has variadic nodes without context + + This is a workaround for handling cases of nested call functions + which don't have the specific call context at hand. + Variadic arguments (variable positional arguments and variable + keyword arguments) are inferred, inherently wrong, by astroid + as a Tuple, respectively a Dict with empty elements. + This can lead pylint to believe that a function call receives + too few arguments. + """ + statement = node.statement() + for name in statement.nodes_of_class(astroid.Name): + if name.name != variadic_name: + continue + + inferred = safe_infer(name) + if isinstance(inferred, (astroid.List, astroid.Tuple)): + length = len(inferred.elts) + elif isinstance(inferred, astroid.Dict): + length = len(inferred.items) + else: + continue + + inferred_statement = inferred.statement() + if not length and isinstance(inferred_statement, astroid.FunctionDef): + is_in_starred_context = _has_parent_of_type(node, variadic_type, statement) + used_as_starred_argument = _is_name_used_as_variadic(name, variadics) + if is_in_starred_context or used_as_starred_argument: + return True + return False + + +def _is_invalid_metaclass(metaclass): + try: + mro = metaclass.mro() + except NotImplementedError: + # Cannot have a metaclass which is not a newstyle class. + return True + else: + if not any(is_builtin_object(cls) and cls.name == 'type' + for cls in mro): + return True + return False + + +def _infer_from_metaclass_constructor(cls, func): + """Try to infer what the given *func* constructor is building + + :param astroid.FunctionDef func: + A metaclass constructor. Metaclass definitions can be + functions, which should accept three arguments, the name of + the class, the bases of the class and the attributes. + The function could return anything, but usually it should + be a proper metaclass. + :param astroid.ClassDef cls: + The class for which the *func* parameter should generate + a metaclass. + :returns: + The class generated by the function or None, + if we couldn't infer it. + :rtype: astroid.ClassDef + """ + context = astroid.context.InferenceContext() + + class_bases = astroid.List() + class_bases.postinit(elts=cls.bases) + + attrs = astroid.Dict() + local_names = [(name, values[-1]) for name, values in cls.locals.items()] + attrs.postinit(local_names) + + builder_args = astroid.Tuple() + builder_args.postinit([cls.name, class_bases, attrs]) + + context.callcontext = astroid.context.CallContext(builder_args) + try: + inferred = next(func.infer_call_result(func, context), None) + except astroid.InferenceError: + return None + return inferred or None + + class TypeChecker(BaseChecker): """try to find bugs in the code using type inference """ @@ -249,7 +492,17 @@ class TypeChecker(BaseChecker): msgs = MSGS priority = -1 # configuration options - options = (('ignore-mixin-members', + options = (('ignore-on-opaque-inference', + {'default': True, 'type': 'yn', 'metavar': '', + 'help': 'This flag controls whether pylint should warn about ' + 'no-member and similar checks whenever an opaque object ' + 'is returned when inferring. The inference can return ' + 'multiple potential results while evaluating a Python object, ' + 'but some branches might not be evaluated, which results in ' + 'partial inference. In that case, it might be useful to still emit ' + 'no-member and other checks for the rest of the inferred objects.'} + ), + ('ignore-mixin-members', {'default' : True, 'type' : 'yn', 'metavar': '', 'help' : 'Tells whether missing members accessed in mixin \ class should be ignored. A mixin class is detected if its name ends with \ @@ -296,6 +549,30 @@ class should be ignored. A mixin class is detected if its name ends with \ 'to register other decorators that produce valid ' 'context managers.'} ), + ('missing-member-hint-distance', + {'default': 1, + 'type': 'int', + 'metavar': '', + 'help': 'The minimum edit distance a name should have in order ' + 'to be considered a similar match for a missing member name.' + } + ), + ('missing-member-max-choices', + {'default': 1, + 'type': "int", + 'metavar': '', + 'help': 'The total number of similar names that should be taken in ' + 'consideration when showing a hint for a missing member.' + } + ), + ('missing-member-hint', + {'default': True, + 'type': "yn", + 'metavar': '', + 'help': 'Show a hint with possible names when a member name was not ' + 'found. The aspect of finding the hint is based on edit distance.' + } + ), ) def open(self): @@ -307,9 +584,36 @@ def open(self): if isinstance(self.config.generated_members, six.string_types): gen = shlex.shlex(self.config.generated_members) gen.whitespace += ',' - gen.wordchars += '[]-+\.*?' + gen.wordchars += r'[]-+\.*?()|' self.config.generated_members = tuple(tok.strip('"') for tok in gen) + @check_messages('invalid-metaclass') + def visit_classdef(self, node): + + def _metaclass_name(metaclass): + if isinstance(metaclass, (astroid.ClassDef, astroid.FunctionDef)): + return metaclass.name + return metaclass.as_string() + + metaclass = node.declared_metaclass() + if not metaclass: + return + + if isinstance(metaclass, astroid.FunctionDef): + # Try to infer the result. + metaclass = _infer_from_metaclass_constructor(node, metaclass) + if not metaclass: + # Don't do anything if we cannot infer the result. + return + + if isinstance(metaclass, astroid.ClassDef): + if _is_invalid_metaclass(metaclass): + self.add_message('invalid-metaclass', node=node, + args=(_metaclass_name(metaclass), )) + else: + self.add_message('invalid-metaclass', node=node, + args=(_metaclass_name(metaclass), )) + def visit_assignattr(self, node): if isinstance(node.assign_type(), astroid.AugAssign): self.visit_attribute(node) @@ -334,18 +638,26 @@ def visit_attribute(self, node): return try: - infered = list(node.expr.infer()) + inferred = list(node.expr.infer()) except exceptions.InferenceError: return + # list of (node, nodename) which are missing the attribute missingattr = set() - inference_failure = False - for owner in infered: - # skip yes object - if owner is astroid.YES: - inference_failure = True - continue + non_opaque_inference_results = [ + owner for owner in inferred + if owner is not astroid.Uninferable + and not isinstance(owner, astroid.nodes.Unknown) + ] + if (len(non_opaque_inference_results) != len(inferred) + and self.config.ignore_on_opaque_inference): + # There is an ambiguity in the inference. Since we can't + # make sure that we won't emit a false positive, we just stop + # whenever the inference returns an opaque inference object. + return + + for owner in non_opaque_inference_results: name = getattr(owner, 'name', None) if _is_owner_ignored(owner, name, self.config.ignored_classes, self.config.ignored_modules): @@ -386,11 +698,18 @@ def visit_attribute(self, node): if actual in done: continue done.add(actual) - confidence = INFERENCE if not inference_failure else INFERENCE_FAILURE + + if self.config.missing_member_hint: + hint = _missing_member_hint(owner, node.attrname, + self.config.missing_member_hint_distance, + self.config.missing_member_max_choices) + else: + hint = "" + self.add_message('no-member', node=node, args=(owner.display_type(), name, - node.attrname), - confidence=confidence) + node.attrname, hint), + confidence=INFERENCE) @check_messages('assignment-from-no-return', 'assignment-from-none') def visit_assign(self, node): @@ -409,7 +728,7 @@ def visit_assign(self, node): return returns = list(function_node.nodes_of_class(astroid.Return, skip_klass=astroid.FunctionDef)) - if len(returns) == 0: + if not returns: self.add_message('assignment-from-no-return', node=node) else: for rnode in returns: @@ -464,33 +783,6 @@ def _check_uninferable_callfunc(self, node): args=node.func.as_string()) break - @staticmethod - def _no_context_variadic(node): - """Verify if the given call node has variadic nodes without context - - This is a workaround for handling cases of nested call functions - which don't have the specific call context at hand. - Variadic arguments (variable positional arguments and variable - keyword arguments) are inferred, inherently wrong, by astroid - as a Tuple, respectively a Dict with empty elements. - This can lead pylint to believe that a function call receives - too few arguments. - """ - for arg in node.args: - if not isinstance(arg, astroid.Starred): - continue - - inferred = safe_infer(arg.value) - if isinstance(inferred, astroid.Tuple): - length = len(inferred.elts) - elif isinstance(inferred, astroid.Dict): - length = len(inferred.items) - else: - return False - if not length and isinstance(inferred.statement(), astroid.FunctionDef): - return True - return False - @check_messages(*(list(MSGS.keys()))) def visit_call(self, node): """check that called functions/methods are inferred to callable objects, @@ -502,13 +794,23 @@ def visit_call(self, node): call_site = astroid.arguments.CallSite.from_call(node) num_positional_args = len(call_site.positional_arguments) keyword_args = list(call_site.keyword_arguments.keys()) - no_context_variadic = self._no_context_variadic(node) + + # Determine if we don't have a context for our call and we use variadics. + if isinstance(node.scope(), astroid.FunctionDef): + has_no_context_positional_variadic = _no_context_variadic_positional(node) + has_no_context_keywords_variadic = _no_context_variadic_keywords(node) + else: + has_no_context_positional_variadic = has_no_context_keywords_variadic = False called = safe_infer(node.func) # only function, generator and object defining __call__ are allowed - if called is not None and not called.callable(): - self.add_message('not-callable', node=node, - args=node.func.as_string()) + if called and not called.callable(): + if isinstance(called, astroid.Instance) and not has_known_bases(called): + # Don't emit if we can't make sure this object is callable. + pass + else: + self.add_message('not-callable', node=node, + args=node.func.as_string()) self._check_uninferable_callfunc(node) @@ -636,13 +938,13 @@ def visit_call(self, node): else: display_name = repr(name) # TODO(cpopa): this should be removed after PyCQA/astroid/issues/177 - if not no_context_variadic: + if not has_no_context_positional_variadic: self.add_message('no-value-for-parameter', node=node, args=(display_name, callable_name)) for name in kwparams: defval, assigned = kwparams[name] - if defval is None and not assigned: + if defval is None and not assigned and not has_no_context_keywords_variadic: self.add_message('missing-kwoa', node=node, args=(name, callable_name)) @@ -668,10 +970,9 @@ def visit_index(self, node): # Determine what method on the parent this index will use # The parent of this node will be a Subscript, and the parent of that # node determines if the Subscript is a get, set, or delete operation. - operation = node.parent.parent - if isinstance(operation, astroid.Assign): + if node.parent.ctx is astroid.Store: methodname = '__setitem__' - elif isinstance(operation, astroid.Delete): + elif node.parent.ctx is astroid.Del: methodname = '__delitem__' else: methodname = '__getitem__' @@ -681,11 +982,13 @@ def visit_index(self, node): # type. This way we catch subclasses of sequence types but skip classes # that override __getitem__ and which may allow non-integer indices. try: - methods = parent_type.getattr(methodname) + methods = dunder_lookup.lookup(parent_type, methodname) if methods is astroid.YES: return itemmethod = methods[0] - except (exceptions.NotFoundError, IndexError): + except (exceptions.NotFoundError, + exceptions.AttributeInferenceError, + IndexError): return if not isinstance(itemmethod, astroid.FunctionDef): return @@ -810,9 +1113,8 @@ def visit_with(self, node): self.add_message('not-context-manager', node=node, args=(infered.name, )) - # Disabled until we'll have a more capable astroid. @check_messages('invalid-unary-operand-type') - def _visit_unaryop(self, node): + def visit_unaryop(self, node): """Detect TypeErrors for unary operands.""" for error in node.type_errors(): @@ -833,6 +1135,9 @@ def _visit_augassign(self, node): def _check_binop_errors(self, node): for error in node.type_errors(): # Let the error customize its output. + if any(isinstance(obj, astroid.ClassDef) and not has_known_bases(obj) + for obj in (error.left_type, error.right_type)): + continue self.add_message('unsupported-binary-operation', args=str(error), node=node) @@ -853,32 +1158,42 @@ def _check_membership_test(self, node): def visit_compare(self, node): if len(node.ops) != 1: return - operator, right = node.ops[0] - if operator in ['in', 'not in']: + + op, right = node.ops[0] + if op in ['in', 'not in']: self._check_membership_test(right) - @check_messages('unsubscriptable-object') + @check_messages('unsubscriptable-object', 'unsupported-assignment-operation', + 'unsupported-delete-operation') def visit_subscript(self, node): + supported_protocol = None if isinstance(node.value, (astroid.ListComp, astroid.DictComp)): return + + if node.ctx == astroid.Load: + supported_protocol = supports_getitem + msg = 'unsubscriptable-object' + elif node.ctx == astroid.Store: + supported_protocol = supports_setitem + msg = 'unsupported-assignment-operation' + elif node.ctx == astroid.Del: + supported_protocol = supports_delitem + msg = 'unsupported-delete-operation' + if isinstance(node.value, astroid.SetComp): - self.add_message('unsubscriptable-object', - args=node.value.as_string(), + self.add_message(msg, args=node.value.as_string(), node=node.value) return - infered = safe_infer(node.value) - if infered is None or infered is astroid.YES: - return - if is_inside_abstract_class(node): return - if not supports_subscript(infered): - self.add_message('unsubscriptable-object', - args=node.value.as_string(), - node=node.value) + inferred = safe_infer(node.value) + if inferred is None or inferred is astroid.YES: + return + if not supported_protocol(inferred): + self.add_message(msg, args=node.value.as_string(), node=node.value) class IterableChecker(BaseChecker): @@ -898,11 +1213,11 @@ class IterableChecker(BaseChecker): msgs = {'E1133': ('Non-iterable value %s is used in an iterating context', 'not-an-iterable', - 'Used when a non-iterable value is used in place where' + 'Used when a non-iterable value is used in place where ' 'iterable is expected'), 'E1134': ('Non-mapping value %s is used in a mapping context', 'not-a-mapping', - 'Used when a non-mapping value is used in place where' + 'Used when a non-mapping value is used in place where ' 'mapping is expected'), } diff --git a/pymode/libs/pylint/checkers/utils.py b/pymode/libs/pylint/checkers/utils.py index dc9d772f..5ed18865 100644 --- a/pymode/libs/pylint/checkers/utils.py +++ b/pymode/libs/pylint/checkers/utils.py @@ -1,12 +1,27 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2012-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2015 Radu Ciorba +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING # pylint: disable=W0611 """some functions that may be useful for various checkers """ +import collections import functools +try: + from functools import singledispatch as singledispatch +except ImportError: + # pylint: disable=import-error + from singledispatch import singledispatch as singledispatch +try: + from functools import lru_cache +except ImportError: + from backports.functools_lru_cache import lru_cache import itertools import re import sys @@ -17,8 +32,10 @@ from six.moves import map, builtins # pylint: disable=redefined-builtin import astroid +from astroid import bases as _bases from astroid import scoped_nodes + BUILTINS_NAME = builtins.__name__ COMP_NODE_TYPES = (astroid.ListComp, astroid.SetComp, astroid.DictComp, astroid.GeneratorExp) @@ -33,6 +50,8 @@ ITER_METHOD = '__iter__' NEXT_METHOD = 'next' if six.PY2 else '__next__' GETITEM_METHOD = '__getitem__' +SETITEM_METHOD = '__setitem__' +DELITEM_METHOD = '__delitem__' CONTAINS_METHOD = '__contains__' KEYS_METHOD = 'keys' @@ -55,7 +74,8 @@ '__float__', '__neg__', '__pos__', '__abs__', '__complex__', '__int__', '__float__', '__index__', '__enter__', '__aenter__', '__getnewargs_ex__', '__getnewargs__', '__getstate__', '__reduce__', '__copy__', - '__unicode__', '__nonzero__', '__await__', '__aiter__', '__anext__'), + '__unicode__', '__nonzero__', '__await__', '__aiter__', '__anext__', + '__fspath__'), 1: ('__format__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__getattr__', '__getattribute__', '__delattr__', @@ -243,8 +263,8 @@ def is_func_decorator(node): if isinstance(parent, astroid.Decorators): return True if (parent.is_statement or - isinstance(parent, astroid.Lambda) or - isinstance(parent, (scoped_nodes.ComprehensionScope, + isinstance(parent, (astroid.Lambda, + scoped_nodes.ComprehensionScope, scoped_nodes.ListComp))): break parent = parent.parent @@ -400,9 +420,11 @@ def is_attr_private(attrname): def get_argument_from_call(callfunc_node, position=None, keyword=None): """Returns the specified argument from a function call. + :param astroid.Call callfunc_node: Node representing a function call to check. :param int position: position of the argument. :param str keyword: the keyword of the argument. + :returns: The node representing the argument, None if the argument is not found. :rtype: astroid.Name :raises ValueError: if both position and keyword are None. @@ -468,28 +490,36 @@ def decorated_with_property(node): if not isinstance(decorator, astroid.Name): continue try: - for infered in decorator.infer(): - if isinstance(infered, astroid.ClassDef): - if (infered.root().name == BUILTINS_NAME and - infered.name == 'property'): - return True - for ancestor in infered.ancestors(): - if (ancestor.name == 'property' and - ancestor.root().name == BUILTINS_NAME): - return True + if _is_property_decorator(decorator): + return True except astroid.InferenceError: pass + return False + + +def _is_property_decorator(decorator): + for infered in decorator.infer(): + if isinstance(infered, astroid.ClassDef): + if infered.root().name == BUILTINS_NAME and infered.name == 'property': + return True + for ancestor in infered.ancestors(): + if ancestor.name == 'property' and ancestor.root().name == BUILTINS_NAME: + return True def decorated_with(func, qnames): """Determine if the `func` node has a decorator with the qualified name `qname`.""" decorators = func.decorators.nodes if func.decorators else [] for decorator_node in decorators: - dec = safe_infer(decorator_node) - if dec and dec.qname() in qnames: - return True + try: + if any(i is not None and i.qname() in qnames for i in decorator_node.infer()): + return True + except astroid.InferenceError: + continue + return False +@lru_cache(maxsize=1024) def unimplemented_abstract_methods(node, is_abstract_cb=None): """ Get the unimplemented abstract methods for the given *node*. @@ -608,13 +638,18 @@ def class_is_abstract(node): return False -def _hasattr(value, attr): +def _supports_protocol_method(value, attr): try: - value.getattr(attr) - return True + attributes = value.getattr(attr) except astroid.NotFoundError: return False + first = attributes[0] + if isinstance(first, astroid.AssignName): + if isinstance(first.parent.value, astroid.Const): + return False + return True + def is_comprehension(node): comprehensions = (astroid.ListComp, @@ -625,19 +660,33 @@ def is_comprehension(node): def _supports_mapping_protocol(value): - return _hasattr(value, GETITEM_METHOD) and _hasattr(value, KEYS_METHOD) + return ( + _supports_protocol_method(value, GETITEM_METHOD) + and _supports_protocol_method(value, KEYS_METHOD) + ) def _supports_membership_test_protocol(value): - return _hasattr(value, CONTAINS_METHOD) + return _supports_protocol_method(value, CONTAINS_METHOD) def _supports_iteration_protocol(value): - return _hasattr(value, ITER_METHOD) or _hasattr(value, GETITEM_METHOD) + return ( + _supports_protocol_method(value, ITER_METHOD) + or _supports_protocol_method(value, GETITEM_METHOD) + ) + + +def _supports_getitem_protocol(value): + return _supports_protocol_method(value, GETITEM_METHOD) -def _supports_subscript_protocol(value): - return _hasattr(value, GETITEM_METHOD) +def _supports_setitem_protocol(value): + return _supports_protocol_method(value, SETITEM_METHOD) + + +def _supports_delitem_protocol(value): + return _supports_protocol_method(value, DELITEM_METHOD) def _is_abstract_class_name(name): @@ -660,70 +709,59 @@ def is_inside_abstract_class(node): return False -def is_iterable(value): +def _supports_protocol(value, protocol_callback): if isinstance(value, astroid.ClassDef): if not has_known_bases(value): return True # classobj can only be iterable if it has an iterable metaclass meta = value.metaclass() if meta is not None: - if _supports_iteration_protocol(meta): + if protocol_callback(meta): return True - if isinstance(value, astroid.Instance): + if isinstance(value, astroid.BaseInstance): if not has_known_bases(value): return True - if _supports_iteration_protocol(value): + if protocol_callback(value): return True + + # TODO: this is not needed in astroid 2.0, where we can + # check the type using a virtual base class instead. + if (isinstance(value, _bases.Proxy) + and isinstance(value._proxied, astroid.BaseInstance) + and has_known_bases(value._proxied)): + value = value._proxied + return protocol_callback(value) + return False +def is_iterable(value): + return _supports_protocol(value, _supports_iteration_protocol) + + def is_mapping(value): - if isinstance(value, astroid.ClassDef): - if not has_known_bases(value): - return True - # classobj can only be a mapping if it has a metaclass is mapping - meta = value.metaclass() - if meta is not None: - if _supports_mapping_protocol(meta): - return True - if isinstance(value, astroid.Instance): - if not has_known_bases(value): - return True - if _supports_mapping_protocol(value): - return True - return False + return _supports_protocol(value, _supports_mapping_protocol) def supports_membership_test(value): - if isinstance(value, astroid.ClassDef): - if not has_known_bases(value): - return True - meta = value.metaclass() - if meta is not None and _supports_membership_test_protocol(meta): - return True - if isinstance(value, astroid.Instance): - if not has_known_bases(value): - return True - if _supports_membership_test_protocol(value): - return True - return is_iterable(value) + supported = _supports_protocol(value, _supports_membership_test_protocol) + return supported or is_iterable(value) -def supports_subscript(value): - if isinstance(value, astroid.ClassDef): - if not has_known_bases(value): - return True - meta = value.metaclass() - if meta is not None and _supports_subscript_protocol(meta): - return True - if isinstance(value, astroid.Instance): - if not has_known_bases(value): - return True - if _supports_subscript_protocol(value): - return True - return False +def supports_getitem(value): + return _supports_protocol(value, _supports_getitem_protocol) + + +def supports_setitem(value): + return _supports_protocol(value, _supports_setitem_protocol) + + +def supports_delitem(value): + return _supports_protocol(value, _supports_delitem_protocol) + # TODO(cpopa): deprecate these or leave them as aliases? +@lru_cache(maxsize=1024) def safe_infer(node, context=None): """Return the inferred value for the given node. @@ -760,3 +798,63 @@ def has_known_bases(klass, context=None): return False klass._all_bases_known = True return True + + +def is_none(node): + return (node is None or + (isinstance(node, astroid.Const) and node.value is None) or + (isinstance(node, astroid.Name) and node.name == 'None') + ) + + +def node_type(node): + """Return the inferred type for `node` + + If there is more than one possible type, or if inferred type is YES or None, + return None + """ + # check there is only one possible type for the assign node. Else we + # don't handle it for now + types = set() + try: + for var_type in node.infer(): + if var_type == astroid.YES or is_none(var_type): + continue + types.add(var_type) + if len(types) > 1: + return + except astroid.InferenceError: + return + return types.pop() if types else None + + +def is_registered_in_singledispatch_function(node): + """Check if the given function node is a singledispatch function.""" + + singledispatch_qnames = ( + 'functools.singledispatch', + 'singledispatch.singledispatch' + ) + + if not isinstance(node, astroid.FunctionDef): + return False + + decorators = node.decorators.nodes if node.decorators else [] + for decorator in decorators: + # func.register are function calls + if not isinstance(decorator, astroid.Call): + continue + + func = decorator.func + if not isinstance(func, astroid.Attribute) or func.attrname != 'register': + continue + + try: + func_def = next(func.expr.infer()) + except astroid.InferenceError: + continue + + if isinstance(func_def, astroid.FunctionDef): + return decorated_with(func_def, singledispatch_qnames) + + return False diff --git a/pymode/libs/pylint/checkers/variables.py b/pymode/libs/pylint/checkers/variables.py index 354419de..e6becff2 100644 --- a/pymode/libs/pylint/checkers/variables.py +++ b/pymode/libs/pylint/checkers/variables.py @@ -1,15 +1,21 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2011-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa +# Copyright (c) 2014 Michal Nowikowski +# Copyright (c) 2015 Radu Ciorba +# Copyright (c) 2015 Dmitry Pribysh +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """variables checkers for Python code """ +import copy import itertools import os import sys import re -from copy import copy try: from functools import lru_cache except ImportError: @@ -23,16 +29,13 @@ from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE, HIGH from pylint.utils import get_global_option from pylint.checkers import BaseChecker -from pylint.checkers.utils import ( - PYMETHODS, is_ancestor_name, is_builtin, - is_defined_before, is_error, is_func_default, is_func_decorator, - assign_parent, check_messages, is_inside_except, clobber_in_except, - get_all_elements, has_known_bases, node_ignores_exception, - is_inside_abstract_class, is_comprehension, is_iterable, - safe_infer, is_from_fallback_block) +from pylint.checkers import utils + SPECIAL_OBJ = re.compile("^_{2}[a-z]+_{2}$") FUTURE = '__future__' +# regexp for ignored argument name +IGNORED_ARGUMENT_NAMES = re.compile('_.*|^ignored_|^unused_') PY3K = sys.version_info >= (3, 0) @@ -40,7 +43,7 @@ def _is_from_future_import(stmt, name): """Check if the name is a future import from another module.""" try: module = stmt.do_import_module(stmt.modname) - except astroid.InferenceError: + except astroid.AstroidBuildingException: return for local_node in module.locals.get(name, []): @@ -52,7 +55,9 @@ def _is_from_future_import(stmt, name): def in_for_else_branch(parent, stmt): """Returns True if stmt in inside the else branch for a parent For stmt.""" return (isinstance(parent, astroid.For) and - any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse)) + any(else_stmt.parent_of(stmt) or else_stmt == stmt + for else_stmt in parent.orelse)) + @lru_cache(maxsize=1000) def overridden_method(klass, name): @@ -212,6 +217,19 @@ def _import_name_is_global(stmt, global_names): return False +def _flattened_scope_names(iterator): + values = (set(stmt.names) for stmt in iterator) + return set(itertools.chain.from_iterable(values)) + + +def _assigned_locally(name_node): + """ + Checks if name_node has corresponding assign statement in same scope + """ + assign_stmts = name_node.scope().nodes_of_class(astroid.AssignName) + return any(a.name == name_node.name for a in assign_stmts) + + MSGS = { 'E0601': ('Using variable %r before assignment', 'used-before-assignment', @@ -242,7 +260,7 @@ def _import_name_is_global(stmt, global_names): 'global-statement', 'Used when you use the "global" statement to update a global \ variable. Pylint just try to discourage this \ - usage. That doesn\'t mean you can not use it !'), + usage. That doesn\'t mean you cannot use it !'), 'W0604': ('Using the global statement at the module level', # W0103 'global-at-module-level', 'Used when you use the "global" statement at the module level \ @@ -316,18 +334,19 @@ class VariablesChecker(BaseChecker): priority = -1 options = (("init-import", {'default': 0, 'type' : 'yn', 'metavar' : '', - 'help' : 'Tells whether we should check for unused import in \ -__init__ files.'}), + 'help' : 'Tells whether we should check for unused import in ' + '__init__ files.'}), ("dummy-variables-rgx", - {'default': ('(_+[a-zA-Z0-9]*?$)|dummy'), + {'default': '_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_', 'type' :'regexp', 'metavar' : '', - 'help' : 'A regular expression matching the name of dummy \ -variables (i.e. expectedly not used).'}), + 'help' : 'A regular expression matching the name of dummy ' + 'variables (i.e. expectedly not used).'}), ("additional-builtins", {'default': (), 'type' : 'csv', 'metavar' : '', - 'help' : 'List of additional names supposed to be defined in \ -builtins. Remember that you should avoid to define new builtins when possible.' + 'help' : 'List of additional names supposed to be defined in ' + 'builtins. Remember that you should avoid to define new builtins ' + 'when possible.' }), ("callbacks", {'default' : ('cb_', '_cb'), 'type' : 'csv', @@ -342,11 +361,24 @@ class VariablesChecker(BaseChecker): 'help': 'List of qualified module names which can have objects ' 'that can redefine builtins.'} ), + ('ignored-argument-names', + {'default' : IGNORED_ARGUMENT_NAMES, + 'type' :'regexp', 'metavar' : '', + 'help' : 'Argument names that match this expression will be ' + 'ignored. Default to name with leading underscore'} + ), + ('allow-global-unused-variables', + {'default': True, + 'type': 'yn', 'metavar': '', + 'help': 'Tells whether unused global variables should be treated as a violation.'} + ), ) + def __init__(self, linter=None): BaseChecker.__init__(self, linter) self._to_consume = None # list of tuples: (to_consume:dict, consumed:dict, scope_type:str) self._checking_mod_attr = None + self._loop_variables = [] # Relying on other checker's options, which might not have been initialized yet. @decorators.cachedproperty @@ -357,21 +389,49 @@ def _analyse_fallback_blocks(self): def _ignored_modules(self): return get_global_option(self, 'ignored-modules', default=[]) + @decorators.cachedproperty + def _allow_global_unused_variables(self): + return get_global_option(self, 'allow-global-unused-variables', default=True) + + @utils.check_messages('redefined-outer-name') + def visit_for(self, node): + assigned_to = [var.name for var in node.target.nodes_of_class(astroid.AssignName)] + + # Only check variables that are used + dummy_rgx = self.config.dummy_variables_rgx + assigned_to = [var for var in assigned_to if not dummy_rgx.match(var)] + + for variable in assigned_to: + for outer_for, outer_variables in self._loop_variables: + if (variable in outer_variables + and not in_for_else_branch(outer_for, node)): + self.add_message( + 'redefined-outer-name', + args=(variable, outer_for.fromlineno), + node=node + ) + break + + self._loop_variables.append((node, assigned_to)) + + @utils.check_messages('redefined-outer-name') + def leave_for(self, _): + self._loop_variables.pop() def visit_module(self, node): """visit module : update consumption analysis variable checks globals doesn't overrides builtins """ - self._to_consume = [(copy(node.locals), {}, 'module')] + self._to_consume = [(copy.copy(node.locals), {}, 'module')] for name, stmts in six.iteritems(node.locals): - if is_builtin(name) and not is_inside_except(stmts[0]): + if utils.is_builtin(name) and not utils.is_inside_except(stmts[0]): if self._should_ignore_redefined_builtin(stmts[0]): continue self.add_message('redefined-builtin', args=name, node=stmts[0]) - @check_messages('unused-import', 'unused-wildcard-import', - 'redefined-builtin', 'undefined-all-variable', - 'invalid-all-object') + @utils.check_messages('unused-import', 'unused-wildcard-import', + 'redefined-builtin', 'undefined-all-variable', + 'invalid-all-object', 'unused-variable') def leave_module(self, node): """leave module: check globals """ @@ -380,6 +440,10 @@ def leave_module(self, node): # attempt to check for __all__ if defined if '__all__' in node.locals: self._check_all(node, not_consumed) + + # check for unused globals + self._check_globals(not_consumed) + # don't check unused imports in __init__ files if not self.config.init_import and node.package: return @@ -434,6 +498,13 @@ def _check_all(self, node, not_consumed): # when the file will be checked pass + def _check_globals(self, not_consumed): + if self._allow_global_unused_variables: + return + for name, nodes in six.iteritems(not_consumed): + for node in nodes: + self.add_message('unused-variable', args=(name,), node=node) + def _check_imports(self, not_consumed): local_names = _fix_dot_imports(not_consumed) checked = set() @@ -457,6 +528,8 @@ def _check_imports(self, not_consumed): # Filter special objects (__doc__, __all__) etc., # because they can be imported for exporting. continue + if as_name == "_": + continue if as_name is None: msg = "import %s" % imported_name else: @@ -490,7 +563,7 @@ def _check_imports(self, not_consumed): def visit_classdef(self, node): """visit class: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'class')) + self._to_consume.append((copy.copy(node.locals), {}, 'class')) def leave_classdef(self, _): """leave class: update consumption analysis variable @@ -501,7 +574,7 @@ def leave_classdef(self, _): def visit_lambda(self, node): """visit lambda: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'lambda')) + self._to_consume.append((copy.copy(node.locals), {}, 'lambda')) def leave_lambda(self, _): """leave lambda: update consumption analysis variable @@ -512,7 +585,7 @@ def leave_lambda(self, _): def visit_generatorexp(self, node): """visit genexpr: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) + self._to_consume.append((copy.copy(node.locals), {}, 'comprehension')) def leave_generatorexp(self, _): """leave genexpr: update consumption analysis variable @@ -523,7 +596,7 @@ def leave_generatorexp(self, _): def visit_dictcomp(self, node): """visit dictcomp: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) + self._to_consume.append((copy.copy(node.locals), {}, 'comprehension')) def leave_dictcomp(self, _): """leave dictcomp: update consumption analysis variable @@ -534,7 +607,7 @@ def leave_dictcomp(self, _): def visit_setcomp(self, node): """visit setcomp: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) + self._to_consume.append((copy.copy(node.locals), {}, 'comprehension')) def leave_setcomp(self, _): """leave setcomp: update consumption analysis variable @@ -545,13 +618,13 @@ def leave_setcomp(self, _): def visit_functiondef(self, node): """visit function: update consumption analysis variable and check locals """ - self._to_consume.append((copy(node.locals), {}, 'function')) + self._to_consume.append((copy.copy(node.locals), {}, 'function')) if not (self.linter.is_message_enabled('redefined-outer-name') or self.linter.is_message_enabled('redefined-builtin')): return globs = node.root().globals for name, stmt in node.items(): - if is_inside_except(stmt): + if utils.is_inside_except(stmt): continue if name in globs and not isinstance(stmt, astroid.Global): definition = globs[name][0] @@ -566,19 +639,22 @@ def visit_functiondef(self, node): self.add_message('redefined-outer-name', args=(name, line), node=stmt) - elif is_builtin(name) and not self._should_ignore_redefined_builtin(stmt): + elif utils.is_builtin(name) and not self._should_ignore_redefined_builtin(stmt): # do not print Redefining builtin for additional builtins self.add_message('redefined-builtin', args=name, node=stmt) - @staticmethod - def _flattened_scope_names(iterator): - values = (set(stmt.names) for stmt in iterator) - return set(itertools.chain.from_iterable(values)) + def _is_name_ignored(self, stmt, name): + authorized_rgx = self.config.dummy_variables_rgx + if (isinstance(stmt, astroid.AssignName) + and isinstance(stmt.parent, astroid.Arguments)): + regex = self.config.ignored_argument_names + else: + regex = authorized_rgx + return regex and regex.match(name) def _check_is_unused(self, name, node, stmt, global_names, nonlocal_names): # Ignore some special names specified by user configuration. - authorized_rgx = self.config.dummy_variables_rgx - if authorized_rgx.match(name): + if self._is_name_ignored(stmt, name): return # Ignore names imported by the global statement. @@ -590,11 +666,14 @@ def _check_is_unused(self, name, node, stmt, global_names, nonlocal_names): if global_names and _import_name_is_global(stmt, global_names): return - argnames = node.argnames() + argnames = list(itertools.chain( + node.argnames(), + [arg.name for arg in node.args.kwonlyargs] + )) is_method = node.is_method() klass = node.parent.frame() if is_method and isinstance(klass, astroid.ClassDef): - confidence = INFERENCE if has_known_bases(klass) else INFERENCE_FAILURE + confidence = INFERENCE if utils.has_known_bases(klass) else INFERENCE_FAILURE else: confidence = HIGH @@ -608,12 +687,15 @@ def _check_is_unused(self, name, node, stmt, global_names, nonlocal_names): overridden = overridden_method(klass, node.name) if overridden is not None and name in overridden.argnames(): return - if node.name in PYMETHODS and node.name not in ('__init__', '__new__'): + if node.name in utils.PYMETHODS and node.name not in ('__init__', '__new__'): return # Don't check callback arguments if any(node.name.startswith(cb) or node.name.endswith(cb) for cb in self.config.callbacks): return + # Don't check arguments of singledispatch.register function. + if utils.is_registered_in_singledispatch_function(node): + return self.add_message('unused-argument', args=name, node=stmt, confidence=confidence) else: @@ -636,7 +718,7 @@ def leave_functiondef(self, node): return # Don't check arguments of function which are only raising an exception. - if is_error(node): + if utils.is_error(node): return # Don't check arguments of abstract methods or within an interface. @@ -644,24 +726,24 @@ def leave_functiondef(self, node): if is_method and node.is_abstract(): return - global_names = self._flattened_scope_names(node.nodes_of_class(astroid.Global)) - nonlocal_names = self._flattened_scope_names(node.nodes_of_class(astroid.Nonlocal)) - + global_names = _flattened_scope_names(node.nodes_of_class(astroid.Global)) + nonlocal_names = _flattened_scope_names(node.nodes_of_class(astroid.Nonlocal)) for name, stmts in six.iteritems(not_consumed): self._check_is_unused(name, node, stmts[0], global_names, nonlocal_names) visit_asyncfunctiondef = visit_functiondef leave_asyncfunctiondef = leave_functiondef - @check_messages('global-variable-undefined', 'global-variable-not-assigned', - 'global-statement', 'global-at-module-level', - 'redefined-builtin') + @utils.check_messages('global-variable-undefined', 'global-variable-not-assigned', + 'global-statement', 'global-at-module-level', + 'redefined-builtin') def visit_global(self, node): """check names imported exists in the global scope""" frame = node.frame() if isinstance(frame, astroid.Module): self.add_message('global-at-module-level', node=node) return + module = frame.root() default_message = True for name in node.names: @@ -670,23 +752,16 @@ def visit_global(self, node): except astroid.NotFoundError: # unassigned global, skip assign_nodes = [] - for anode in assign_nodes: - if anode.parent is None: - # node returned for builtin attribute such as __file__, - # __doc__, etc... - continue - if anode.frame() is frame: - # same scope level assignment - break - else: - if not _find_frame_imports(name, frame): - self.add_message('global-variable-not-assigned', - args=name, node=node) - default_message = False + if not assign_nodes: + self.add_message('global-variable-not-assigned', + args=name, node=node) + default_message = False continue + for anode in assign_nodes: - if anode.parent is None: + if (isinstance(anode, astroid.AssignName) + and anode.name in module.special_attributes): self.add_message('redefined-builtin', args=name, node=node) break if anode.frame() is module: @@ -696,6 +771,7 @@ def visit_global(self, node): # global undefined at the module scope self.add_message('global-variable-undefined', args=name, node=node) default_message = False + if default_message: self.add_message('global-statement', node=node) @@ -768,10 +844,10 @@ def _should_ignore_redefined_builtin(self, stmt): return False return stmt.modname in self.config.redefining_builtins_modules - @check_messages('redefine-in-handler') + @utils.check_messages('redefine-in-handler') def visit_excepthandler(self, node): - for name in get_all_elements(node.name): - clobbering, args = clobber_in_except(name) + for name in utils.get_all_elements(node.name): + clobbering, args = utils.clobber_in_except(name) if clobbering: self.add_message('redefine-in-handler', args=args, node=name) @@ -790,6 +866,7 @@ def _defined_in_function_definition(node, frame): in_annotation_or_default = ( ( PY3K and (node in frame.args.annotations + or node in frame.args.kwonlyargs_annotations or node is frame.args.varargannotation or node is frame.args.kwargannotation) ) @@ -816,6 +893,7 @@ def _is_variable_violation(node, name, defnode, stmt, defstmt, recursive_klass): maybee0601 = True annotation_return = False + use_outer_definition = False if frame is not defframe: maybee0601 = _detect_global_scope(node, frame, defframe) elif defframe.parent is None: @@ -826,8 +904,14 @@ def _is_variable_violation(node, name, defnode, stmt, defstmt, else: # we are in a local scope, check the name is not # defined in global or builtin scope - if defframe.root().lookup(name)[1]: + # skip this lookup if name is assigned later in function scope + forbid_lookup = isinstance(frame, astroid.FunctionDef) and _assigned_locally(node) + if not forbid_lookup and defframe.root().lookup(name)[1]: maybee0601 = False + use_outer_definition = ( + stmt == defstmt + and not isinstance(defnode, astroid.node_classes.Comprehension) + ) else: # check if we have a nonlocal if name in defframe.locals: @@ -874,7 +958,16 @@ def _is_variable_violation(node, name, defnode, stmt, defstmt, maybee0601 = True else: maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.fromlineno - return maybee0601, annotation_return + if maybee0601 and stmt.fromlineno == defstmt.fromlineno: + if (isinstance(defframe, astroid.FunctionDef) + and frame is defframe + and defframe.parent_of(node) + and stmt is not defstmt): + # Single statement function, with the statement on the + # same line as the function definition + maybee0601 = False + + return maybee0601, annotation_return, use_outer_definition def _ignore_class_scope(self, node, name, frame): # Detect if we are in a local class scope, as an assignment. @@ -903,7 +996,7 @@ def _ignore_class_scope(self, node, name, frame): in_annotation_or_default) and name in frame_locals) - @check_messages(*(MSGS.keys())) + @utils.check_messages(*(MSGS.keys())) def visit_name(self, node): """check that a name is defined if the current scope and doesn't redefine a built-in @@ -918,8 +1011,8 @@ def visit_name(self, node): # if the name node is used as a function default argument's value or as # a decorator, then start from the parent frame of the function instead # of the function frame - and thus open an inner class scope - if (is_func_default(node) or is_func_decorator(node) - or is_ancestor_name(frame, node)): + if (utils.is_func_default(node) or utils.is_func_decorator(node) + or utils.is_ancestor_name(frame, node)): start_index = len(self._to_consume) - 2 else: start_index = len(self._to_consume) - 1 @@ -941,17 +1034,15 @@ def visit_name(self, node): # the name has already been consumed, only check it's not a loop # variable used outside the loop if name in consumed: - defnode = assign_parent(consumed[name][0]) + defnode = utils.assign_parent(consumed[name][0]) self._check_late_binding_closure(node, defnode) self._loopvar_name(node, name) break found_node = self._next_to_consume(node, name, to_consume) - if found_node: - consumed[name] = found_node - else: + if found_node is None: continue # checks for use before assignment - defnode = assign_parent(to_consume[name][0]) + defnode = utils.assign_parent(to_consume[name][0]) if defnode is not None: self._check_late_binding_closure(node, defnode) defstmt = defnode.statement() @@ -962,28 +1053,28 @@ def visit_name(self, node): isinstance(defframe, astroid.ClassDef) and node.name == defframe.name) - maybee0601, annotation_return = self._is_variable_violation( + maybee0601, annotation_return, use_outer_definition = self._is_variable_violation( node, name, defnode, stmt, defstmt, frame, defframe, base_scope_type, recursive_klass) + if use_outer_definition: + continue + if (maybee0601 - and not is_defined_before(node) - and not astroid.are_exclusive(stmt, defstmt, ('NameError', - 'Exception', - 'BaseException'))): + and not utils.is_defined_before(node) + and not astroid.are_exclusive(stmt, defstmt, ('NameError',))): # Used and defined in the same place, e.g `x += 1` and `del x` defined_by_stmt = ( defstmt is stmt and isinstance(node, (astroid.DelName, astroid.AssignName)) ) - if (recursive_klass or defined_by_stmt or annotation_return or isinstance(defstmt, astroid.Delete)): - if not node_ignores_exception(node, NameError): + if not utils.node_ignores_exception(node, NameError): self.add_message('undefined-variable', args=name, node=node) elif base_scope_type != 'lambda': @@ -1011,6 +1102,7 @@ def visit_name(self, node): self.add_message('undefined-variable', node=node, args=name) + consumed[name] = found_node del to_consume[name] # check it's not a loop variable used outside the loop self._loopvar_name(node, name) @@ -1018,15 +1110,15 @@ def visit_name(self, node): else: # we have not found the name, if it isn't a builtin, that's an # undefined name ! - if not (name in astroid.Module.scope_attrs or is_builtin(name) + if not (name in astroid.Module.scope_attrs or utils.is_builtin(name) or name in self.config.additional_builtins): - if not node_ignores_exception(node, NameError): + if not utils.node_ignores_exception(node, NameError): self.add_message('undefined-variable', args=name, node=node) - @check_messages('no-name-in-module') + @utils.check_messages('no-name-in-module') def visit_import(self, node): """check modules attribute accesses""" - if not self._analyse_fallback_blocks and is_from_fallback_block(node): + if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node): # No need to verify this, since ImportError is already # handled by the client code. return @@ -1039,10 +1131,10 @@ def visit_import(self, node): continue self._check_module_attrs(node, module, parts[1:]) - @check_messages('no-name-in-module') + @utils.check_messages('no-name-in-module') def visit_importfrom(self, node): """check modules attribute accesses""" - if not self._analyse_fallback_blocks and is_from_fallback_block(node): + if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node): # No need to verify this, since ImportError is already # handled by the client code. return @@ -1050,7 +1142,7 @@ def visit_importfrom(self, node): name_parts = node.modname.split('.') try: module = node.do_import_module(name_parts[0]) - except Exception: + except astroid.AstroidBuildingException: return module = self._check_module_attrs(node, module, name_parts[1:]) if not module: @@ -1060,7 +1152,7 @@ def visit_importfrom(self, node): continue self._check_module_attrs(node, module, name.split('.')) - @check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence') + @utils.check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence') def visit_assign(self, node): """Check unbalanced tuple unpacking for assignments and unpacking non-sequences. @@ -1070,7 +1162,7 @@ def visit_assign(self, node): targets = node.targets[0].itered() try: - infered = safe_infer(node.value) + infered = utils.safe_infer(node.value) if infered is not None: self._check_unpacking(infered, node, targets) except astroid.InferenceError: @@ -1080,9 +1172,9 @@ def _check_unpacking(self, infered, node, targets): """ Check for unbalanced tuple unpacking and unpacking non sequences. """ - if is_inside_abstract_class(node): + if utils.is_inside_abstract_class(node): return - if is_comprehension(node): + if utils.is_comprehension(node): return if infered is astroid.YES: return @@ -1105,7 +1197,7 @@ def _check_unpacking(self, infered, node, targets): len(values))) # attempt to check unpacking may be possible (ie RHS is iterable) else: - if not is_iterable(infered): + if not utils.is_iterable(infered): self.add_message('unpacking-non-sequence', node=node, args=(_get_unpacking_extra_info(node, infered),)) @@ -1136,7 +1228,7 @@ def _check_module_attrs(self, node, module, module_names): if module_names: # FIXME: other message if name is not the latest part of # module_names ? - modname = module and module.name or '__dict__' + modname = module.name if module else '__dict__' self.add_message('no-name-in-module', node=node, args=('.'.join(module_names), modname)) return None @@ -1152,7 +1244,7 @@ class VariablesChecker3k(VariablesChecker): def visit_listcomp(self, node): """visit dictcomp: update consumption analysis variable """ - self._to_consume.append((copy(node.locals), {}, 'comprehension')) + self._to_consume.append((copy.copy(node.locals), {}, 'comprehension')) def leave_listcomp(self, _): """leave dictcomp: update consumption analysis variable @@ -1160,56 +1252,68 @@ def leave_listcomp(self, _): # do not check for not used locals here self._to_consume.pop() + def leave_functiondef(self, node): + self._check_metaclasses(node) + super(VariablesChecker3k, self).leave_functiondef(node) + def leave_module(self, node): - """ Update consumption analysis variable - for metaclasses. - """ - module_locals = self._to_consume[0][0] - module_imports = self._to_consume[0][1] - consumed = {} - - for klass in node.nodes_of_class(astroid.ClassDef): - found = metaclass = name = None - if not klass._metaclass: - # Skip if this class doesn't use - # explictly a metaclass, but inherits it from ancestors - continue + self._check_metaclasses(node) + super(VariablesChecker3k, self).leave_module(node) - metaclass = klass.metaclass() + def _check_metaclasses(self, node): + """ Update consumption analysis for metaclasses. """ + consumed = [] # [(scope_locals, consumed_key)] + + for child_node in node.get_children(): + if isinstance(child_node, astroid.ClassDef): + consumed.extend(self._check_classdef_metaclasses(child_node, node)) + + # Pop the consumed items, in order to avoid having + # unused-import and unused-variable false positives + for scope_locals, name in consumed: + scope_locals.pop(name, None) + + def _check_classdef_metaclasses(self, klass, parent_node): + if not klass._metaclass: + # Skip if this class doesn't use explicitly a metaclass, but inherits it from ancestors + return [] + + consumed = [] # [(scope_locals, consumed_key)] + metaclass = klass.metaclass() + + name = None + if isinstance(klass._metaclass, astroid.Name): + name = klass._metaclass.name + elif metaclass: + name = metaclass.root().name + + found = None + if name: + # check enclosing scopes starting from most local + for scope_locals, _, _ in self._to_consume[::-1]: + found = scope_locals.get(name) + if found: + consumed.append((scope_locals, name)) + break - # Look the name in the already found locals. - # If it's not found there, look in the module locals - # and in the imported modules. + if found is None and not metaclass: + name = None if isinstance(klass._metaclass, astroid.Name): name = klass._metaclass.name - elif metaclass: - # if it uses a `metaclass=module.Class` - name = metaclass.root().name - - if name: - found = consumed.setdefault( - name, module_locals.get(name, module_imports.get(name))) - - if found is None and not metaclass: - name = None - if isinstance(klass._metaclass, astroid.Name): - name = klass._metaclass.name - elif isinstance(klass._metaclass, astroid.Attribute): - name = klass._metaclass.as_string() - - if name is not None: - if not (name in astroid.Module.scope_attrs or - is_builtin(name) or - name in self.config.additional_builtins or - name in node.locals): - self.add_message('undefined-variable', - node=klass, - args=(name, )) - # Pop the consumed items, in order to - # avoid having unused-import false positives - for name in consumed: - module_locals.pop(name, None) - super(VariablesChecker3k, self).leave_module(node) + elif isinstance(klass._metaclass, astroid.Attribute): + name = klass._metaclass.as_string() + + if name is not None: + if not (name in astroid.Module.scope_attrs or + utils.is_builtin(name) or + name in self.config.additional_builtins or + name in parent_node.locals): + self.add_message('undefined-variable', + node=klass, + args=(name,)) + + return consumed + if sys.version_info >= (3, 0): VariablesChecker = VariablesChecker3k diff --git a/pymode/libs/pylint/config.py b/pymode/libs/pylint/config.py index 10d807da..6922949f 100644 --- a/pymode/libs/pylint/config.py +++ b/pymode/libs/pylint/config.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2010, 2012-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Aru Sahni + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -28,10 +30,7 @@ import sys import time -try: - import configparser -except ImportError: - from six.moves import configparser +import configparser from six.moves import range from pylint import utils @@ -133,10 +132,10 @@ class UnsupportedAction(Exception): def _multiple_choice_validator(choices, name, value): values = utils._check_csv(value) - for value in values: - if value not in choices: + for csv_value in values: + if csv_value not in choices: msg = "option %s: invalid value: %r, should be in %s" - raise optparse.OptionValueError(msg % (name, value, choices)) + raise optparse.OptionValueError(msg % (name, csv_value, choices)) return values @@ -172,6 +171,13 @@ def _yn_validator(opt, _, value): raise optparse.OptionValueError(msg % (opt, value)) +def _non_empty_string_validator(opt, _, value): + if not value: + msg = "indent string can't be empty." + raise optparse.OptionValueError(msg) + return utils._unquote(value) + + VALIDATORS = { 'string': utils._unquote, 'int': int, @@ -182,6 +188,7 @@ def _yn_validator(opt, _, value): 'choice': lambda opt, name, value: _choice_validator(opt['choices'], name, value), 'multiple_choice': lambda opt, name, value: _multiple_choice_validator(opt['choices'], name, value), + 'non_empty_string': _non_empty_string_validator, } def _call_validator(opttype, optdict, option, value): @@ -257,7 +264,6 @@ class Option(optparse.Option): TYPES = optparse.Option.TYPES + ('regexp', 'regexp_csv', 'csv', 'yn', 'multiple_choice', 'non_empty_string') - ATTRS = optparse.Option.ATTRS + ['hide', 'level'] TYPE_CHECKER = copy.copy(optparse.Option.TYPE_CHECKER) TYPE_CHECKER['regexp'] = _regexp_validator @@ -265,6 +271,7 @@ class Option(optparse.Option): TYPE_CHECKER['csv'] = _csv_validator TYPE_CHECKER['yn'] = _yn_validator TYPE_CHECKER['multiple_choice'] = _multiple_choices_validating_option + TYPE_CHECKER['non_empty_string'] = _non_empty_string_validator def __init__(self, *opts, **attrs): optparse.Option.__init__(self, *opts, **attrs) @@ -290,10 +297,10 @@ def process(self, opt, value, values, parser): # value(s) are bogus. value = self.convert_value(opt, value) if self.type == 'named': - existant = getattr(values, self.dest) - if existant: - existant.update(value) - value = existant + existent = getattr(values, self.dest) + if existent: + existent.update(value) + value = existent # And then take whatever action is expected of us. # This is a separate method to make life easier for # subclasses to add new actions. @@ -384,7 +391,7 @@ def format_title(pgm, section): def format_short_description(pgm, short_desc): return '''.SH NAME .B %s -\- %s +\\- %s ''' % (pgm, short_desc.strip()) @staticmethod @@ -452,7 +459,7 @@ def __init__(self, usage, config_file=None, version=None, quiet=0): def reset_parsers(self, usage='', version=None): # configuration file parser - self.cfgfile_parser = configparser.ConfigParser() + self.cfgfile_parser = configparser.ConfigParser(inline_comment_prefixes=('#', ';')) # command line parser self.cmdline_parser = OptionParser(usage=usage, version=version) self.cmdline_parser.options_manager = self @@ -493,7 +500,8 @@ def add_option_group(self, group_name, _, options, provider): group.level = provider.level self._mygroups[group_name] = group # add section to the config file - if group_name != "DEFAULT": + if group_name != "DEFAULT" and \ + group_name not in self.cfgfile_parser._sections: self.cfgfile_parser.add_section(group_name) # add provider's specific options for opt, optdict in options: @@ -579,7 +587,7 @@ def generate_config(self, stream=None, skipsections=(), encoding=None): if printed: print('\n', file=stream) utils.format_section(stream, section.upper(), - options_by_section[section], + sorted(options_by_section[section]), encoding) printed = True @@ -728,36 +736,36 @@ def option_value(self, opt): """get the current value for the given option""" return getattr(self.config, self.option_attrname(opt), None) - def set_option(self, opt, value, action=None, optdict=None): + def set_option(self, optname, value, action=None, optdict=None): """method called to set an option (registered in the options list)""" if optdict is None: - optdict = self.get_option_def(opt) + optdict = self.get_option_def(optname) if value is not None: - value = _validate(value, optdict, opt) + value = _validate(value, optdict, optname) if action is None: action = optdict.get('action', 'store') if action == 'store': - setattr(self.config, self.option_attrname(opt, optdict), value) + setattr(self.config, self.option_attrname(optname, optdict), value) elif action in ('store_true', 'count'): - setattr(self.config, self.option_attrname(opt, optdict), 0) + setattr(self.config, self.option_attrname(optname, optdict), 0) elif action == 'store_false': - setattr(self.config, self.option_attrname(opt, optdict), 1) + setattr(self.config, self.option_attrname(optname, optdict), 1) elif action == 'append': - opt = self.option_attrname(opt, optdict) - _list = getattr(self.config, opt, None) + optname = self.option_attrname(optname, optdict) + _list = getattr(self.config, optname, None) if _list is None: if isinstance(value, (list, tuple)): _list = value elif value is not None: _list = [] _list.append(value) - setattr(self.config, opt, _list) + setattr(self.config, optname, _list) elif isinstance(_list, tuple): - setattr(self.config, opt, _list + (value,)) + setattr(self.config, optname, _list + (value,)) else: _list.append(value) elif action == 'callback': - optdict['callback'](None, opt, value, None) + optdict['callback'](None, optname, value, None) else: raise UnsupportedAction(action) diff --git a/pymode/libs/pylint/epylint.py b/pymode/libs/pylint/epylint.py index 2ac01936..0b714fb4 100644 --- a/pymode/libs/pylint/epylint.py +++ b/pymode/libs/pylint/epylint.py @@ -1,8 +1,11 @@ -# -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 +# -*- coding: utf-8; +# mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 # -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2008-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014 Manuel Vázquez Acosta +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -42,6 +45,7 @@ import os import os.path as osp import sys +import shlex from subprocess import Popen, PIPE import six @@ -83,9 +87,9 @@ def lint(filename, options=None): # Ensure we use the python and pylint associated with the running epylint run_cmd = "import sys; from pylint.lint import Run; Run(sys.argv[1:])" options = options or ['--disable=C,R,I'] - cmd = [sys.executable, "-c", run_cmd] + options + [ + cmd = [sys.executable, "-c", run_cmd] + [ '--msg-template', '{path}:{line}: {category} ({msg_id}, {symbol}, {obj}) {msg}', - '-r', 'n', child_path] + '-r', 'n', child_path] + options process = Popen(cmd, stdout=PIPE, cwd=parent_path, env=_get_env(), universal_newlines=True) @@ -104,8 +108,7 @@ def lint(filename, options=None): return process.returncode -def py_run(command_options='', return_std=False, stdout=None, stderr=None, - script='epylint'): +def py_run(command_options='', return_std=False, stdout=None, stderr=None): """Run pylint from python ``command_options`` is a string containing ``pylint`` command line options; @@ -133,9 +136,10 @@ def py_run(command_options='', return_std=False, stdout=None, stderr=None, >>> (pylint_stdout, pylint_stderr) = py_run( 'module_name.py', True) """ # Create command line to call pylint - if os.name == 'nt': - script += '.bat' - command_line = script + ' ' + command_options + epylint_part = [sys.executable, "-c", "from pylint import epylint;epylint.Run()"] + options = shlex.split(command_options) + cli = epylint_part + options + # Providing standard output and/or error if not set if stdout is None: if return_std: @@ -148,7 +152,7 @@ def py_run(command_options='', return_std=False, stdout=None, stderr=None, else: stderr = sys.stderr # Call pylint in a subprocess - process = Popen(command_line, shell=True, stdout=stdout, stderr=stderr, + process = Popen(cli, shell=False, stdout=stdout, stderr=stderr, env=_get_env(), universal_newlines=True) proc_stdout, proc_stderr = process.communicate() # Return standard output and error diff --git a/pymode/libs/pylint/exceptions.py b/pymode/libs/pylint/exceptions.py new file mode 100644 index 00000000..429379d9 --- /dev/null +++ b/pymode/libs/pylint/exceptions.py @@ -0,0 +1,15 @@ +# Copyright (c) 2016 Glenn Matthews +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +"""Exception classes raised by various operations within pylint.""" + + +class InvalidMessageError(Exception): + """raised when a message creation, registration or addition is rejected""" + +class UnknownMessageError(Exception): + """raised when a unregistered message id is encountered""" + +class EmptyReportError(Exception): + """raised when a report is empty and so should not be displayed""" diff --git a/pymode/libs/pylint/extensions/_check_docs_utils.py b/pymode/libs/pylint/extensions/_check_docs_utils.py index 1262d85e..920e02f3 100644 --- a/pymode/libs/pylint/extensions/_check_docs_utils.py +++ b/pymode/libs/pylint/extensions/_check_docs_utils.py @@ -1,5 +1,9 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# -*- coding: utf-8 -*- +# Copyright (c) 2016 Ashley Whetter +# Copyright (c) 2016 Moisés López +# Copyright (c) 2016 Glenn Matthews +# Copyright (c) 2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -11,7 +15,11 @@ import astroid -from pylint.checkers.utils import node_ignores_exception +from pylint.checkers.utils import ( + inherit_from_std_ex, + node_ignores_exception, + safe_infer, +) def space_indentation(s): @@ -33,7 +41,7 @@ def returns_something(return_node): :rtype: bool :return: True if the return node returns a value other than None, - False otherise. + False otherwise. """ returns = return_node.value @@ -60,10 +68,24 @@ def possible_exc_types(node): """ excs = [] if isinstance(node.exc, astroid.Name): - excs = [node.exc.name] + inferred = safe_infer(node.exc) + if inferred: + excs = [inferred.name] elif (isinstance(node.exc, astroid.Call) and isinstance(node.exc.func, astroid.Name)): - excs = [node.exc.func.name] + target = safe_infer(node.exc.func) + if isinstance(target, astroid.ClassDef): + excs = [target.name] + elif isinstance(target, astroid.FunctionDef): + for ret in target.nodes_of_class(astroid.Return): + if ret.frame() != target: + # return from inner function - ignore it + continue + + val = safe_infer(ret.value) + if (val and isinstance(val, (astroid.Instance, astroid.ClassDef)) + and inherit_from_std_ex(val)): + excs.append(val.name) elif node.exc is None: handler = node.parent while handler and not isinstance(handler, astroid.ExceptHandler): @@ -72,26 +94,36 @@ def possible_exc_types(node): if handler and handler.type: inferred_excs = astroid.unpack_infer(handler.type) excs = (exc.name for exc in inferred_excs - if exc is not astroid.YES) + if exc is not astroid.Uninferable) + try: return set(exc for exc in excs if not node_ignores_exception(node, exc)) except astroid.InferenceError: return () + def docstringify(docstring): - for docstring_type in [SphinxDocstring, GoogleDocstring, NumpyDocstring]: + for docstring_type in [SphinxDocstring, EpytextDocstring, + GoogleDocstring, NumpyDocstring]: instance = docstring_type(docstring) if instance.is_valid(): return instance return Docstring(docstring) + class Docstring(object): re_for_parameters_see = re.compile(r""" For\s+the\s+(other)?\s*parameters\s*,\s+see """, re.X | re.S) + supports_yields = None + """True if the docstring supports a "yield" section. + + False if the docstring uses the returns section to document generators. + """ + # These methods are designed to be overridden # pylint: disable=no-self-use def __init__(self, doc): @@ -110,12 +142,22 @@ def has_params(self): def has_returns(self): return False + def has_rtype(self): + return False + + def has_yields(self): + return False + + def has_yields_type(self): + return False + def match_param_docs(self): return set(), set() def params_documented_elsewhere(self): return self.re_for_parameters_see.search(self.doc) is not None + class SphinxDocstring(Docstring): re_type = r"[\w\.]+" @@ -124,8 +166,13 @@ class SphinxDocstring(Docstring): `{0}` # what to reference """.format(re_type) - re_param_in_docstring = re.compile(r""" - :param # Sphinx keyword + re_param_raw = r""" + : # initial colon + (?: # Sphinx keywords + param|parameter| + arg|argument| + key|keyword + ) \s+ # whitespace (?: # optional type declaration @@ -136,18 +183,24 @@ class SphinxDocstring(Docstring): (\w+) # Parameter name \s* # whitespace : # final colon - """.format(type=re_type), re.X | re.S) + """.format(type=re_type) + re_param_in_docstring = re.compile(re_param_raw, re.X | re.S) - re_type_in_docstring = re.compile(r""" + re_type_raw = r""" :type # Sphinx keyword \s+ # whitespace ({type}) # Parameter name \s* # whitespace : # final colon - """.format(type=re_type), re.X | re.S) - - re_raise_in_docstring = re.compile(r""" - :raises # Sphinx keyword + """.format(type=re_type) + re_type_in_docstring = re.compile(re_type_raw, re.X | re.S) + + re_raise_raw = r""" + : # initial colon + (?: # Sphinx keyword + raises?| + except|exception + ) \s+ # whitespace (?: # type declaration @@ -158,12 +211,15 @@ class SphinxDocstring(Docstring): (\w+) # Parameter name \s* # whitespace : # final colon - """.format(type=re_type), re.X | re.S) + """.format(type=re_type) + re_raise_in_docstring = re.compile(re_raise_raw, re.X | re.S) re_rtype_in_docstring = re.compile(r":rtype:") re_returns_in_docstring = re.compile(r":returns?:") + supports_yields = False + def is_valid(self): return bool(self.re_param_in_docstring.search(self.doc) or self.re_raise_in_docstring.search(self.doc) or @@ -189,8 +245,13 @@ def has_returns(self): if not self.doc: return False - return (self.re_rtype_in_docstring.search(self.doc) and - self.re_returns_in_docstring.search(self.doc)) + return bool(self.re_returns_in_docstring.search(self.doc)) + + def has_rtype(self): + if not self.doc: + return False + + return bool(self.re_rtype_in_docstring.search(self.doc)) def match_param_docs(self): params_with_doc = set() @@ -207,6 +268,39 @@ def match_param_docs(self): return params_with_doc, params_with_type +class EpytextDocstring(SphinxDocstring): + """ + Epytext is similar to Sphinx. See the docs: + http://epydoc.sourceforge.net/epytext.html + http://epydoc.sourceforge.net/fields.html#fields + + It's used in PyCharm: + https://www.jetbrains.com/help/pycharm/2016.1/creating-documentation-comments.html#d848203e314 + https://www.jetbrains.com/help/pycharm/2016.1/using-docstrings-to-specify-types.html + """ + re_param_in_docstring = re.compile( + SphinxDocstring.re_param_raw.replace(':', '@', 1), + re.X | re.S) + + re_type_in_docstring = re.compile( + SphinxDocstring.re_type_raw.replace(':', '@', 1), + re.X | re.S) + + re_raise_in_docstring = re.compile( + SphinxDocstring.re_raise_raw.replace(':', '@', 1), + re.X | re.S) + + re_rtype_in_docstring = re.compile(r""" + @ # initial "at" symbol + (?: # Epytext keyword + rtype|returntype + ) + : # final colon + """, re.X | re.S) + + re_returns_in_docstring = re.compile(r"@returns?:") + + class GoogleDocstring(Docstring): re_type = SphinxDocstring.re_type @@ -217,6 +311,11 @@ class GoogleDocstring(Docstring): [\(\[] [^\n]+ [\)\]] # with the contents of the container """.format(type=re_type, xref=re_xref) + re_multiple_type = r""" + (?:{container_type}|{type}) + (?:\s+or\s+(?:{container_type}|{type}))* + """.format(type=re_type, container_type=re_container_type) + _re_section_template = r""" ^([ ]*) {0} \s*: \s*$ # Google parameter header ( .* ) # section @@ -230,12 +329,11 @@ class GoogleDocstring(Docstring): re_param_line = re.compile(r""" \s* \*{{0,2}}(\w+) # identifier potentially with asterisks \s* ( [(] - (?:{container_type}|{type}) + {type} [)] )? \s* : # optional type declaration \s* (.*) # beginning of optional description """.format( - type=re_type, - container_type=re_container_type + type=re_multiple_type, ), re.X | re.S | re.M) re_raise_section = re.compile( @@ -254,17 +352,26 @@ class GoogleDocstring(Docstring): ) re_returns_line = re.compile(r""" - \s* ({container_type}:|{type}:)? # identifier + \s* ({type}:)? # identifier \s* (.*) # beginning of description """.format( - type=re_type, - container_type=re_container_type + type=re_multiple_type, ), re.X | re.S | re.M) + re_yields_section = re.compile( + _re_section_template.format(r"Yields?"), + re.X | re.S | re.M + ) + + re_yields_line = re_returns_line + + supports_yields = True + def is_valid(self): return bool(self.re_param_section.search(self.doc) or self.re_raise_section.search(self.doc) or - self.re_returns_section.search(self.doc)) + self.re_returns_section.search(self.doc) or + self.re_yields_section.search(self.doc)) def has_params(self): if not self.doc: @@ -282,9 +389,56 @@ def has_returns(self): if not match: continue - return_type = match.group(1) return_desc = match.group(2) - if return_type and return_desc: + if return_desc: + return True + + return False + + def has_rtype(self): + if not self.doc: + return False + + entries = self._parse_section(self.re_returns_section) + for entry in entries: + match = self.re_returns_line.match(entry) + if not match: + continue + + return_type = match.group(1) + if return_type: + return True + + return False + + def has_yields(self): + if not self.doc: + return False + + entries = self._parse_section(self.re_yields_section) + for entry in entries: + match = self.re_yields_line.match(entry) + if not match: + continue + + yield_desc = match.group(2) + if yield_desc: + return True + + return False + + def has_yields_type(self): + if not self.doc: + return False + + entries = self._parse_section(self.re_yields_section) + for entry in entries: + match = self.re_yields_line.match(entry) + if not match: + continue + + yield_type = match.group(1) + if yield_type: return True return False @@ -367,6 +521,7 @@ def _parse_section(self, section_re): return entries + class NumpyDocstring(GoogleDocstring): _re_section_template = r""" ^([ ]*) {0} \s*?$ # Numpy parameters header @@ -382,12 +537,11 @@ class NumpyDocstring(GoogleDocstring): re_param_line = re.compile(r""" \s* (\w+) # identifier \s* : - \s* ({container_type}|{type})? # optional type declaration + \s* (?:({type})(?:,\s+optional)?)? # optional type declaration \n # description starts on a new line \s* (.*) # description """.format( - type=GoogleDocstring.re_type, - container_type=GoogleDocstring.re_container_type + type=GoogleDocstring.re_multiple_type, ), re.X | re.S) re_raise_section = re.compile( @@ -406,13 +560,21 @@ class NumpyDocstring(GoogleDocstring): ) re_returns_line = re.compile(r""" - \s* ({container_type}|{type})$ # type declaration + \s* ({type})$ # type declaration \s* (.*) # optional description """.format( - type=GoogleDocstring.re_type, - container_type=GoogleDocstring.re_container_type + type=GoogleDocstring.re_multiple_type, ), re.X | re.S | re.M) + re_yields_section = re.compile( + _re_section_template.format(r"Yields?"), + re.X | re.S | re.M + ) + + re_yields_line = re_returns_line + + supports_yields = True + @staticmethod def min_section_indent(section_match): return len(section_match.group(1)) diff --git a/pymode/libs/pylint/extensions/bad_builtin.py b/pymode/libs/pylint/extensions/bad_builtin.py index c9cdcbec..9876922e 100644 --- a/pymode/libs/pylint/extensions/bad_builtin.py +++ b/pymode/libs/pylint/extensions/bad_builtin.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/extensions/check_docs.py b/pymode/libs/pylint/extensions/check_docs.py index d6a26e26..a01d6fa4 100644 --- a/pymode/libs/pylint/extensions/check_docs.py +++ b/pymode/libs/pylint/extensions/check_docs.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2014-2015 Bruno Daniel +# Copyright (c) 2015-2016 Claudiu Popa +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/extensions/check_elif.py b/pymode/libs/pylint/extensions/check_elif.py index 99217deb..3fbe1c34 100644 --- a/pymode/libs/pylint/extensions/check_elif.py +++ b/pymode/libs/pylint/extensions/check_elif.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015 LOGILAB S.A. (Paris, FRANCE) + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -14,7 +14,7 @@ class ElseifUsedChecker(BaseTokenChecker): """ __implements__ = (ITokenChecker, IAstroidChecker) - name = 'elseifused' + name = 'else_if_used' msgs = {'R5501': ('Consider using "elif" instead of "else if"', 'else-if-used', 'Used when an else statement is immediately followed by ' diff --git a/pymode/libs/pylint/extensions/comparetozero.py b/pymode/libs/pylint/extensions/comparetozero.py new file mode 100644 index 00000000..00e3eae5 --- /dev/null +++ b/pymode/libs/pylint/extensions/comparetozero.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2016 Alexander Todorov + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +"""Looks for comparisons to empty string.""" + +import itertools + +import astroid + +from pylint import interfaces +from pylint import checkers +from pylint.checkers import utils + + +def _is_constant_zero(node): + return isinstance(node, astroid.Const) and node.value == 0 + + +class CompareToZeroChecker(checkers.BaseChecker): + """Checks for comparisons to zero. + Most of the times you should use the fact that integers with a value of 0 are false. + An exception to this rule is when 0 is allowed in the program and has a + different meaning than None! + """ + + __implements__ = (interfaces.IAstroidChecker,) + + # configuration section name + name = 'compare-to-zero' + msgs = {'C2001': ('Avoid comparisons to zero', + 'compare-to-zero', + 'Used when Pylint detects comparison to a 0 constant.'), + } + + priority = -2 + options = () + + @utils.check_messages('compare-to-zero') + def visit_compare(self, node): + _operators = ['!=', '==', 'is not', 'is'] + # note: astroid.Compare has the left most operand in node.left + # while the rest are a list of tuples in node.ops + # the format of the tuple is ('compare operator sign', node) + # here we squash everything into `ops` to make it easier for processing later + ops = [('', node.left)] + ops.extend(node.ops) + ops = list(itertools.chain(*ops)) + + for ops_idx in range(len(ops) - 2): + op_1 = ops[ops_idx] + op_2 = ops[ops_idx + 1] + op_3 = ops[ops_idx + 2] + error_detected = False + + # 0 ?? X + if _is_constant_zero(op_1) and op_2 in _operators + ['<']: + error_detected = True + # X ?? 0 + elif op_2 in _operators + ['>'] and _is_constant_zero(op_3): + error_detected = True + + if error_detected: + self.add_message('compare-to-zero', node=node) + + +def register(linter): + """Required method to auto register this checker.""" + linter.register_checker(CompareToZeroChecker(linter)) diff --git a/pymode/libs/pylint/extensions/docparams.py b/pymode/libs/pylint/extensions/docparams.py index ffd78f99..43e46351 100644 --- a/pymode/libs/pylint/extensions/docparams.py +++ b/pymode/libs/pylint/extensions/docparams.py @@ -1,5 +1,8 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2014-2015 Bruno Daniel +# Copyright (c) 2015-2016 Claudiu Popa +# Copyright (c) 2016 Ashley Whetter +# Copyright (c) 2016 Glenn Matthews + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -26,12 +29,12 @@ class DocstringParameterChecker(BaseChecker): the documentation, i.e. also report documented parameters that are missing in the signature. This is important to find cases where parameters are renamed only in the code, not in the documentation. - * Check that all explicity raised exceptions in a function are documented + * Check that all explicitly raised exceptions in a function are documented in the function docstring. Caught exceptions are ignored. Activate this checker by adding the line:: - load-plugins=pylint.extensions.check_docs + load-plugins=pylint.extensions.docparams to the ``MASTER`` section of your ``.pylintrc``. @@ -40,46 +43,81 @@ class DocstringParameterChecker(BaseChecker): """ __implements__ = IAstroidChecker - name = 'docstring_params' + name = 'parameter_documentation' msgs = { - 'W9003': ('"%s" missing or differing in parameter documentation', - 'missing-param-doc', - 'Please add parameter declarations for all parameters.'), - 'W9004': ('"%s" missing or differing in parameter type documentation', - 'missing-type-doc', - 'Please add parameter type declarations for all parameters.'), 'W9005': ('"%s" has constructor parameters documented in class and __init__', 'multiple-constructor-doc', 'Please remove parameter declarations in the class or constructor.'), 'W9006': ('"%s" not documented as being raised', 'missing-raises-doc', 'Please document exceptions for all raised exception types.'), - 'W9007': ('Missing return type documentation', - 'missing-returns-doc', - 'Please add documentation about what this method returns.'), 'W9008': ('Redundant returns documentation', 'redundant-returns-doc', - 'Please remove the return documentation from this method.'), + 'Please remove the return/rtype documentation from this method.'), + 'W9010': ('Redundant yields documentation', + 'redundant-yields-doc', + 'Please remove the yields documentation from this method.'), + 'W9011': ('Missing return documentation', + 'missing-return-doc', + 'Please add documentation about what this method returns.', + {'old_names': [('W9007', 'missing-returns-doc')]}), + 'W9012': ('Missing return type documentation', + 'missing-return-type-doc', + 'Please document the type returned by this method.', + # we can't use the same old_name for two different warnings + # {'old_names': [('W9007', 'missing-returns-doc')]}, + ), + 'W9013': ('Missing yield documentation', + 'missing-yield-doc', + 'Please add documentation about what this generator yields.', + {'old_names': [('W9009', 'missing-yields-doc')]}), + 'W9014': ('Missing yield type documentation', + 'missing-yield-type-doc', + 'Please document the type yielded by this method.', + # we can't use the same old_name for two different warnings + # {'old_names': [('W9009', 'missing-yields-doc')]}, + ), + 'W9015': ('"%s" missing in parameter documentation', + 'missing-param-doc', + 'Please add parameter declarations for all parameters.', + {'old_names': [('W9003', 'missing-param-doc')]}), + 'W9016': ('"%s" missing in parameter type documentation', + 'missing-type-doc', + 'Please add parameter type declarations for all parameters.', + {'old_names': [('W9004', 'missing-type-doc')]}), + 'W9017': ('"%s" differing in parameter documentation', + 'differing-param-doc', + 'Please check parameter names in declarations.', + ), + 'W9018': ('"%s" differing in parameter type documentation', + 'differing-type-doc', + 'Please check parameter names in type declarations.', + ), } options = (('accept-no-param-doc', {'default': True, 'type' : 'yn', 'metavar' : '', 'help': 'Whether to accept totally missing parameter ' - 'documentation in a docstring of a function that has ' + 'documentation in the docstring of a function that has ' 'parameters.' }), ('accept-no-raise-doc', {'default': True, 'type' : 'yn', 'metavar' : '', - 'help': 'Whether to accept totally missing raises' - 'documentation in a docstring of a function that' + 'help': 'Whether to accept totally missing raises ' + 'documentation in the docstring of a function that ' 'raises an exception.' }), ('accept-no-return-doc', {'default': True, 'type' : 'yn', 'metavar' : '', - 'help': 'Whether to accept totally missing return' - 'documentation in a docstring of a function that' + 'help': 'Whether to accept totally missing return ' + 'documentation in the docstring of a function that ' 'returns a statement.' }), + ('accept-no-yields-doc', + {'default': True, 'type' : 'yn', 'metavar': '', + 'help': 'Whether to accept totally missing yields ' + 'documentation in the docstring of a generator.' + }), ) priority = -2 @@ -96,6 +134,7 @@ def visit_functiondef(self, node): node_doc = utils.docstringify(node.doc) self.check_functiondef_params(node, node_doc) self.check_functiondef_returns(node, node_doc) + self.check_functiondef_yields(node, node_doc) def check_functiondef_params(self, node, node_doc): node_allow_no_param = None @@ -107,8 +146,16 @@ def check_functiondef_params(self, node, node_doc): # __init__ or class docstrings can have no parameters documented # as long as the other documents them. - node_allow_no_param = class_doc.has_params() or None - class_allow_no_param = node_doc.has_params() or None + node_allow_no_param = ( + class_doc.has_params() or + class_doc.params_documented_elsewhere() or + None + ) + class_allow_no_param = ( + node_doc.has_params() or + node_doc.params_documented_elsewhere() or + None + ) self.check_arguments_in_docstring( class_doc, node.args, class_node, class_allow_no_param) @@ -117,13 +164,26 @@ def check_functiondef_params(self, node, node_doc): node_doc, node.args, node, node_allow_no_param) def check_functiondef_returns(self, node, node_doc): + if not node_doc.supports_yields and node.is_generator(): + return + return_nodes = node.nodes_of_class(astroid.Return) - if (node_doc.has_returns() and + if ((node_doc.has_returns() or node_doc.has_rtype()) and not any(utils.returns_something(ret_node) for ret_node in return_nodes)): self.add_message( 'redundant-returns-doc', node=node) + def check_functiondef_yields(self, node, node_doc): + if not node_doc.supports_yields: + return + + if ((node_doc.has_yields() or node_doc.has_yields_type()) and + not node.is_generator()): + self.add_message( + 'redundant-yields-doc', + node=node) + def visit_raise(self, node): func_node = node.frame() if not isinstance(func_node, astroid.FunctionDef): @@ -157,10 +217,47 @@ def visit_return(self, node): if not doc.has_returns(): self.add_message( - 'missing-returns-doc', + 'missing-return-doc', + node=func_node + ) + + if not doc.has_rtype(): + self.add_message( + 'missing-return-type-doc', node=func_node ) + def visit_yield(self, node): + func_node = node.frame() + if not isinstance(func_node, astroid.FunctionDef): + return + + doc = utils.docstringify(func_node.doc) + if not doc.is_valid() and self.config.accept_no_yields_doc: + return + + if doc.supports_yields: + doc_has_yields = doc.has_yields() + doc_has_yields_type = doc.has_yields_type() + else: + doc_has_yields = doc.has_returns() + doc_has_yields_type = doc.has_rtype() + + if not doc_has_yields: + self.add_message( + 'missing-yield-doc', + node=func_node + ) + + if not doc_has_yields_type: + self.add_message( + 'missing-yield-type-doc', + node=func_node + ) + + def visit_yieldfrom(self, node): + self.visit_yield(node) + def check_arguments_in_docstring(self, doc, arguments_node, warning_node, accept_no_param_doc=None): """Check that all parameters in a function, method or class constructor @@ -224,11 +321,12 @@ class constructor. and accept_no_param_doc): tolerate_missing_params = True - def _compare_args(found_argument_names, message_id, not_needed_names): + def _compare_missing_args(found_argument_names, message_id, + not_needed_names): """Compare the found argument names with the expected ones and - generate a message if there are inconsistencies. + generate a message if there are arguments missing. - :param list found_argument_names: argument names found in the + :param set found_argument_names: argument names found in the docstring :param str message_id: pylint message id @@ -237,25 +335,49 @@ def _compare_args(found_argument_names, message_id, not_needed_names): :type not_needed_names: set of str """ if not tolerate_missing_params: - missing_or_differing_argument_names = ( - (expected_argument_names ^ found_argument_names) - - not_needed_names) - else: - missing_or_differing_argument_names = ( - (found_argument_names - expected_argument_names) + missing_argument_names = ( + (expected_argument_names - found_argument_names) - not_needed_names) + if missing_argument_names: + self.add_message( + message_id, + args=(', '.join( + sorted(missing_argument_names)),), + node=warning_node) + + def _compare_different_args(found_argument_names, message_id, + not_needed_names): + """Compare the found argument names with the expected ones and + generate a message if there are extra arguments found. + + :param set found_argument_names: argument names found in the + docstring + + :param str message_id: pylint message id - if missing_or_differing_argument_names: + :param not_needed_names: names that may be omitted + :type not_needed_names: set of str + """ + differing_argument_names = ( + (expected_argument_names ^ found_argument_names) + - not_needed_names - expected_argument_names) + + if differing_argument_names: self.add_message( message_id, args=(', '.join( - sorted(missing_or_differing_argument_names)),), + sorted(differing_argument_names)),), node=warning_node) - _compare_args(params_with_doc, 'missing-param-doc', - self.not_needed_param_in_docstring) - _compare_args(params_with_type, 'missing-type-doc', - not_needed_type_in_docstring) + _compare_missing_args(params_with_doc, 'missing-param-doc', + self.not_needed_param_in_docstring) + _compare_missing_args(params_with_type, 'missing-type-doc', + not_needed_type_in_docstring) + + _compare_different_args(params_with_doc, 'differing-param-doc', + self.not_needed_param_in_docstring) + _compare_different_args(params_with_type, 'differing-type-doc', + not_needed_type_in_docstring) def check_single_constructor_params(self, class_doc, init_doc, class_node): if class_doc.has_params() and init_doc.has_params(): diff --git a/pymode/libs/pylint/extensions/docstyle.py b/pymode/libs/pylint/extensions/docstyle.py index 2b5a005b..12a58d09 100644 --- a/pymode/libs/pylint/extensions/docstyle.py +++ b/pymode/libs/pylint/extensions/docstyle.py @@ -1,16 +1,17 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2016 Luis Escobar +# Copyright (c) 2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING import linecache -from pylint.checkers.base import BaseChecker +from pylint import checkers from pylint.interfaces import IAstroidChecker, HIGH from pylint.checkers.utils import check_messages -class DocStringStyleChecker(BaseChecker): +class DocStringStyleChecker(checkers.BaseChecker): """Checks format of docstrings based on PEP 0257""" __implements__ = IAstroidChecker @@ -33,7 +34,7 @@ def visit_classdef(self, node): self._check_docstring('class', node) def visit_functiondef(self, node): - ftype = node.is_method() and 'method' or 'function' + ftype = 'method' if node.is_method() else 'function' self._check_docstring(ftype, node) visit_asyncfunctiondef = visit_functiondef diff --git a/pymode/libs/pylint/extensions/emptystring.py b/pymode/libs/pylint/extensions/emptystring.py new file mode 100644 index 00000000..d3e05e9d --- /dev/null +++ b/pymode/libs/pylint/extensions/emptystring.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2016 Alexander Todorov + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +"""Looks for comparisons to empty string.""" + +import itertools + +import astroid + +from pylint import interfaces +from pylint import checkers +from pylint.checkers import utils + + +def _is_constant_empty_str(node): + return isinstance(node, astroid.Const) and node.value == '' + + +class CompareToEmptyStringChecker(checkers.BaseChecker): + """Checks for comparisons to empty string. + Most of the times you should use the fact that empty strings are false. + An exception to this rule is when an empty string value is allowed in the program + and has a different meaning than None! + """ + + __implements__ = (interfaces.IAstroidChecker,) + + # configuration section name + name = 'compare-to-empty-string' + msgs = {'C1901': ('Avoid comparisons to empty string', + 'compare-to-empty-string', + 'Used when Pylint detects comparison to an empty string constant.'), + } + + priority = -2 + options = () + + @utils.check_messages('compare-to-empty-string') + def visit_compare(self, node): + _operators = ['!=', '==', 'is not', 'is'] + # note: astroid.Compare has the left most operand in node.left + # while the rest are a list of tuples in node.ops + # the format of the tuple is ('compare operator sign', node) + # here we squash everything into `ops` to make it easier for processing later + ops = [('', node.left)] + ops.extend(node.ops) + ops = list(itertools.chain(*ops)) + + for ops_idx in range(len(ops) - 2): + op_1 = ops[ops_idx] + op_2 = ops[ops_idx + 1] + op_3 = ops[ops_idx + 2] + error_detected = False + + # x ?? "" + if _is_constant_empty_str(op_1) and op_2 in _operators: + error_detected = True + # '' ?? X + elif op_2 in _operators and _is_constant_empty_str(op_3): + error_detected = True + + if error_detected: + self.add_message('compare-to-empty-string', node=node) + + +def register(linter): + """Required method to auto register this checker.""" + linter.register_checker(CompareToEmptyStringChecker(linter)) diff --git a/pymode/libs/pylint/extensions/mccabe.py b/pymode/libs/pylint/extensions/mccabe.py index 86c9b567..8e231ccd 100644 --- a/pymode/libs/pylint/extensions/mccabe.py +++ b/pymode/libs/pylint/extensions/mccabe.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -9,7 +9,7 @@ from mccabe import PathGraph as Mccabe_PathGraph, \ PathGraphingAstVisitor as Mccabe_PathGraphingAstVisitor -from pylint.checkers.base import BaseChecker +from pylint import checkers from pylint.checkers.utils import check_messages from pylint.interfaces import HIGH, IAstroidChecker @@ -116,7 +116,7 @@ def _subgraph_parse(self, node, pathnode, extra_blocks): # pylint: disable=unus self.tail = bottom -class McCabeMethodChecker(BaseChecker): +class McCabeMethodChecker(checkers.BaseChecker): """Checks McCabe complexity cyclomatic threshold in methods and functions to validate a too complex code. """ diff --git a/pymode/libs/pylint/extensions/overlapping_exceptions.py b/pymode/libs/pylint/extensions/overlapping_exceptions.py new file mode 100644 index 00000000..c231ba35 --- /dev/null +++ b/pymode/libs/pylint/extensions/overlapping_exceptions.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +"""Looks for overlapping exceptions.""" + +import astroid + +from pylint import interfaces +from pylint import checkers +from pylint.checkers import utils + +from pylint.checkers.exceptions import _annotated_unpack_infer + + +class OverlappingExceptionsChecker(checkers.BaseChecker): + """Checks for two or more exceptions in the same exception handler + clause that are identical or parts of the same inheritance hierarchy + (i.e. overlapping).""" + + __implements__ = interfaces.IAstroidChecker + + name = 'overlap-except' + msgs = {'W0714': ('Overlapping exceptions (%s)', + 'overlapping-except', + 'Used when exceptions in handler overlap or are identical')} + priority = -2 + options = () + + @utils.check_messages('overlapping-except') + def visit_tryexcept(self, node): + """check for empty except""" + for handler in node.handlers: + if handler.type is None: + continue + if isinstance(handler.type, astroid.BoolOp): + continue + try: + excs = list(_annotated_unpack_infer(handler.type)) + except astroid.InferenceError: + continue + + handled_in_clause = [] + for part, exc in excs: + if exc is astroid.YES: + continue + if (isinstance(exc, astroid.Instance) and + utils.inherit_from_std_ex(exc)): + # pylint: disable=protected-access + exc = exc._proxied + + if not isinstance(exc, astroid.ClassDef): + continue + + exc_ancestors = [anc for anc in exc.ancestors() + if isinstance(anc, astroid.ClassDef)] + + for prev_part, prev_exc in handled_in_clause: + prev_exc_ancestors = [anc for anc in prev_exc.ancestors() + if isinstance(anc, astroid.ClassDef)] + if exc == prev_exc: + self.add_message('overlapping-except', + node=handler.type, + args='%s and %s are the same' % + (prev_part.as_string(), + part.as_string())) + elif (prev_exc in exc_ancestors or + exc in prev_exc_ancestors): + ancestor = part if exc in prev_exc_ancestors else prev_part + descendant = part if prev_exc in exc_ancestors else prev_part + self.add_message('overlapping-except', + node=handler.type, + args='%s is an ancestor class of %s' % + (ancestor.as_string(), descendant.as_string())) + handled_in_clause += [(part, exc)] + + +def register(linter): + """Required method to auto register this checker.""" + linter.register_checker(OverlappingExceptionsChecker(linter)) diff --git a/pymode/libs/pylint/extensions/redefined_variable_type.py b/pymode/libs/pylint/extensions/redefined_variable_type.py new file mode 100644 index 00000000..6b6abb83 --- /dev/null +++ b/pymode/libs/pylint/extensions/redefined_variable_type.py @@ -0,0 +1,104 @@ +# Copyright (c) 2016 Claudiu Popa + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +import six + +import astroid +from pylint.checkers import BaseChecker +from pylint.checkers.utils import check_messages, is_none, node_type +from pylint.interfaces import IAstroidChecker + + +BUILTINS = six.moves.builtins.__name__ + + +class MultipleTypesChecker(BaseChecker): + """Checks for variable type redefinitions (NoneType excepted) + + At a function, method, class or module scope + + This rule could be improved: + + - Currently, if an attribute is set to different types in 2 methods of a + same class, it won't be detected (see functional test) + - One could improve the support for inference on assignment with tuples, + ifexpr, etc. Also it would be great to have support for inference on + str.split() + """ + __implements__ = IAstroidChecker + + name = 'multiple_types' + msgs = {'R0204': ('Redefinition of %s type from %s to %s', + 'redefined-variable-type', + 'Used when the type of a variable changes inside a ' + 'method or a function.' + ), + } + + def visit_classdef(self, _): + self._assigns.append({}) + + @check_messages('redefined-variable-type') + def leave_classdef(self, _): + self._check_and_add_messages() + + visit_functiondef = visit_classdef + leave_functiondef = leave_module = leave_classdef + + def visit_module(self, _): + self._assigns = [{}] + + def _check_and_add_messages(self): + assigns = self._assigns.pop() + for name, args in assigns.items(): + if len(args) <= 1: + continue + orig_node, orig_type = args[0] + # Check if there is a type in the following nodes that would be + # different from orig_type. + for redef_node, redef_type in args[1:]: + if redef_type == orig_type: + continue + # if a variable is defined to several types in a if node, + # this is not actually redefining. + orig_parent = orig_node.parent + redef_parent = redef_node.parent + if isinstance(orig_parent, astroid.If): + if orig_parent == redef_parent: + if (redef_node in orig_parent.orelse and + orig_node not in orig_parent.orelse): + orig_node, orig_type = redef_node, redef_type + continue + elif (isinstance(redef_parent, astroid.If) and + redef_parent in orig_parent.nodes_of_class(astroid.If)): + orig_node, orig_type = redef_node, redef_type + continue + orig_type = orig_type.replace(BUILTINS + ".", '') + redef_type = redef_type.replace(BUILTINS + ".", '') + self.add_message('redefined-variable-type', node=redef_node, + args=(name, orig_type, redef_type)) + break + + def visit_assign(self, node): + # we don't handle multiple assignment nor slice assignment + target = node.targets[0] + if isinstance(target, (astroid.Tuple, astroid.Subscript)): + return + # ignore NoneType + if is_none(node): + return + _type = node_type(node.value) + if _type: + self._assigns[-1].setdefault(target.as_string(), []).append( + (node, _type.pytype())) + + +def register(linter): + """Required method to auto register this checker. + + :param linter: Main interface object for Pylint plugins + :type linter: Pylint object + """ + linter.register_checker(MultipleTypesChecker(linter)) diff --git a/pymode/libs/pylint/graph.py b/pymode/libs/pylint/graph.py index c3ad3e1f..f2c2c5bb 100644 --- a/pymode/libs/pylint/graph.py +++ b/pymode/libs/pylint/graph.py @@ -1,5 +1,6 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/gui.py b/pymode/libs/pylint/gui.py deleted file mode 100644 index 6761bd95..00000000 --- a/pymode/libs/pylint/gui.py +++ /dev/null @@ -1,521 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tkinker gui for pylint""" -from __future__ import print_function - -import os -import sys -import re -from threading import Thread - -import six - -from six.moves.tkinter import ( - Tk, Frame, Listbox, Entry, Label, Button, Scrollbar, - Checkbutton, Radiobutton, IntVar, StringVar, PanedWindow, - TOP, LEFT, RIGHT, BOTTOM, END, X, Y, BOTH, SUNKEN, W, - HORIZONTAL, DISABLED, NORMAL, -) -from six.moves.tkinter_tkfiledialog import ( - askopenfilename, askdirectory, -) - -import pylint.lint -from pylint.reporters.guireporter import GUIReporter - -HOME = os.path.expanduser('~/') -HISTORY = '.pylint-gui-history' -COLORS = {'(I)':'green', - '(C)':'blue', '(R)':'darkblue', - '(W)':'black', '(E)':'darkred', - '(F)':'red'} - - -def convert_to_string(msg): - """make a string representation of a message""" - module_object = msg.module - if msg.obj: - module_object += ".%s" % msg.obj - return "(%s) %s [%d]: %s" % (msg.C, module_object, msg.line, msg.msg) - -class BasicStream(object): - ''' - used in gui reporter instead of writing to stdout, it is written to - this stream and saved in contents - ''' - def __init__(self, gui): - """init""" - self.curline = "" - self.gui = gui - self.contents = [] - self.outdict = {} - self.currout = None - self.next_title = None - - def write(self, text): - """write text to the stream""" - if re.match('^--+$', text.strip()) or re.match('^==+$', text.strip()): - if self.currout: - self.outdict[self.currout].remove(self.next_title) - self.outdict[self.currout].pop() - self.currout = self.next_title - self.outdict[self.currout] = [''] - - if text.strip(): - self.next_title = text.strip() - - if text.startswith(os.linesep): - self.contents.append('') - if self.currout: - self.outdict[self.currout].append('') - self.contents[-1] += text.strip(os.linesep) - if self.currout: - self.outdict[self.currout][-1] += text.strip(os.linesep) - if text.endswith(os.linesep) and text.strip(): - self.contents.append('') - if self.currout: - self.outdict[self.currout].append('') - - def fix_contents(self): - """finalize what the contents of the dict should look like before output""" - for item in self.outdict: - num_empty = self.outdict[item].count('') - for _ in range(num_empty): - self.outdict[item].remove('') - if self.outdict[item]: - self.outdict[item].pop(0) - - def output_contents(self): - """output contents of dict to the gui, and set the rating""" - self.fix_contents() - self.gui.tabs = self.outdict - try: - self.gui.rating.set(self.outdict['Global evaluation'][0]) - except KeyError: - self.gui.rating.set('Error') - self.gui.refresh_results_window() - - #reset stream variables for next run - self.contents = [] - self.outdict = {} - self.currout = None - self.next_title = None - - -class LintGui(object): - """Build and control a window to interact with pylint""" - - def __init__(self, root=None): - """init""" - self.root = root or Tk() - self.root.title('Pylint') - #reporter - self.reporter = None - #message queue for output from reporter - self.msg_queue = six.moves.queue.Queue() - self.msgs = [] - self.visible_msgs = [] - self.filenames = [] - self.rating = StringVar() - self.tabs = {} - self.report_stream = BasicStream(self) - #gui objects - self.lb_messages = None - self.showhistory = None - self.results = None - self.btnRun = None - self.information_box = None - self.convention_box = None - self.refactor_box = None - self.warning_box = None - self.error_box = None - self.fatal_box = None - self.txtModule = None - self.status = None - self.msg_type_dict = None - self.init_gui() - - def init_gui(self): - """init helper""" - - window = PanedWindow(self.root, orient="vertical") - window.pack(side=TOP, fill=BOTH, expand=True) - - top_pane = Frame(window) - window.add(top_pane) - mid_pane = Frame(window) - window.add(mid_pane) - bottom_pane = Frame(window) - window.add(bottom_pane) - - #setting up frames - top_frame = Frame(top_pane) - mid_frame = Frame(top_pane) - history_frame = Frame(top_pane) - radio_frame = Frame(mid_pane) - rating_frame = Frame(mid_pane) - res_frame = Frame(mid_pane) - check_frame = Frame(bottom_pane) - msg_frame = Frame(bottom_pane) - btn_frame = Frame(bottom_pane) - top_frame.pack(side=TOP, fill=X) - mid_frame.pack(side=TOP, fill=X) - history_frame.pack(side=TOP, fill=BOTH, expand=True) - radio_frame.pack(side=TOP, fill=X) - rating_frame.pack(side=TOP, fill=X) - res_frame.pack(side=TOP, fill=BOTH, expand=True) - check_frame.pack(side=TOP, fill=X) - msg_frame.pack(side=TOP, fill=BOTH, expand=True) - btn_frame.pack(side=TOP, fill=X) - - # Binding F5 application-wide to run lint - self.root.bind('', self.run_lint) - - #Message ListBox - rightscrollbar = Scrollbar(msg_frame) - rightscrollbar.pack(side=RIGHT, fill=Y) - bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) - bottomscrollbar.pack(side=BOTTOM, fill=X) - self.lb_messages = Listbox( - msg_frame, - yscrollcommand=rightscrollbar.set, - xscrollcommand=bottomscrollbar.set, - bg="white") - self.lb_messages.bind("", self.show_sourcefile) - self.lb_messages.pack(expand=True, fill=BOTH) - rightscrollbar.config(command=self.lb_messages.yview) - bottomscrollbar.config(command=self.lb_messages.xview) - - #History ListBoxes - rightscrollbar2 = Scrollbar(history_frame) - rightscrollbar2.pack(side=RIGHT, fill=Y) - bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) - bottomscrollbar2.pack(side=BOTTOM, fill=X) - self.showhistory = Listbox( - history_frame, - yscrollcommand=rightscrollbar2.set, - xscrollcommand=bottomscrollbar2.set, - bg="white") - self.showhistory.pack(expand=True, fill=BOTH) - rightscrollbar2.config(command=self.showhistory.yview) - bottomscrollbar2.config(command=self.showhistory.xview) - self.showhistory.bind('', self.select_recent_file) - self.set_history_window() - - #status bar - self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) - self.status.pack(side=BOTTOM, fill=X) - - #labelbl_ratingls - lbl_rating_label = Label(rating_frame, text='Rating:') - lbl_rating_label.pack(side=LEFT) - lbl_rating = Label(rating_frame, textvariable=self.rating) - lbl_rating.pack(side=LEFT) - Label(mid_frame, text='Recently Used:').pack(side=LEFT) - Label(top_frame, text='Module or package').pack(side=LEFT) - - #file textbox - self.txt_module = Entry(top_frame, background='white') - self.txt_module.bind('', self.run_lint) - self.txt_module.pack(side=LEFT, expand=True, fill=X) - - #results box - rightscrollbar = Scrollbar(res_frame) - rightscrollbar.pack(side=RIGHT, fill=Y) - bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) - bottomscrollbar.pack(side=BOTTOM, fill=X) - self.results = Listbox( - res_frame, - yscrollcommand=rightscrollbar.set, - xscrollcommand=bottomscrollbar.set, - bg="white", font="Courier") - self.results.pack(expand=True, fill=BOTH, side=BOTTOM) - rightscrollbar.config(command=self.results.yview) - bottomscrollbar.config(command=self.results.xview) - - #buttons - Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT) - Button(top_frame, text='Open Package', - command=(lambda: self.file_open(package=True))).pack(side=LEFT) - - self.btnRun = Button(top_frame, text='Run', command=self.run_lint) - self.btnRun.pack(side=LEFT) - Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM) - - #radio buttons - self.information_box = IntVar() - self.convention_box = IntVar() - self.refactor_box = IntVar() - self.warning_box = IntVar() - self.error_box = IntVar() - self.fatal_box = IntVar() - i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'], - variable=self.information_box, command=self.refresh_msg_window) - c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'], - variable=self.convention_box, command=self.refresh_msg_window) - r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'], - variable=self.refactor_box, command=self.refresh_msg_window) - w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'], - variable=self.warning_box, command=self.refresh_msg_window) - e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'], - variable=self.error_box, command=self.refresh_msg_window) - f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'], - variable=self.fatal_box, command=self.refresh_msg_window) - i.select() - c.select() - r.select() - w.select() - e.select() - f.select() - i.pack(side=LEFT) - c.pack(side=LEFT) - r.pack(side=LEFT) - w.pack(side=LEFT) - e.pack(side=LEFT) - f.pack(side=LEFT) - - #check boxes - self.box = StringVar() - # XXX should be generated - report = Radiobutton( - radio_frame, text="Report", variable=self.box, - value="Report", command=self.refresh_results_window) - raw_met = Radiobutton( - radio_frame, text="Raw metrics", variable=self.box, - value="Raw metrics", command=self.refresh_results_window) - dup = Radiobutton( - radio_frame, text="Duplication", variable=self.box, - value="Duplication", command=self.refresh_results_window) - ext = Radiobutton( - radio_frame, text="External dependencies", - variable=self.box, value="External dependencies", - command=self.refresh_results_window) - stat = Radiobutton( - radio_frame, text="Statistics by type", - variable=self.box, value="Statistics by type", - command=self.refresh_results_window) - msg_cat = Radiobutton( - radio_frame, text="Messages by category", - variable=self.box, value="Messages by category", - command=self.refresh_results_window) - msg = Radiobutton( - radio_frame, text="Messages", variable=self.box, - value="Messages", command=self.refresh_results_window) - source_file = Radiobutton( - radio_frame, text="Source File", variable=self.box, - value="Source File", command=self.refresh_results_window) - report.select() - report.grid(column=0, row=0, sticky=W) - raw_met.grid(column=1, row=0, sticky=W) - dup.grid(column=2, row=0, sticky=W) - msg.grid(column=3, row=0, sticky=W) - stat.grid(column=0, row=1, sticky=W) - msg_cat.grid(column=1, row=1, sticky=W) - ext.grid(column=2, row=1, sticky=W) - source_file.grid(column=3, row=1, sticky=W) - - #dictionary for check boxes and associated error term - self.msg_type_dict = { - 'I': lambda: self.information_box.get() == 1, - 'C': lambda: self.convention_box.get() == 1, - 'R': lambda: self.refactor_box.get() == 1, - 'E': lambda: self.error_box.get() == 1, - 'W': lambda: self.warning_box.get() == 1, - 'F': lambda: self.fatal_box.get() == 1 - } - self.txt_module.focus_set() - - - def select_recent_file(self, event): # pylint: disable=unused-argument - """adds the selected file in the history listbox to the Module box""" - if not self.showhistory.size(): - return - - selected = self.showhistory.curselection() - item = self.showhistory.get(selected) - #update module - self.txt_module.delete(0, END) - self.txt_module.insert(0, item) - - def refresh_msg_window(self): - """refresh the message window with current output""" - #clear the window - self.lb_messages.delete(0, END) - self.visible_msgs = [] - for msg in self.msgs: - if self.msg_type_dict.get(msg.C)(): - self.visible_msgs.append(msg) - msg_str = convert_to_string(msg) - self.lb_messages.insert(END, msg_str) - fg_color = COLORS.get(msg_str[:3], 'black') - self.lb_messages.itemconfigure(END, fg=fg_color) - - def refresh_results_window(self): - """refresh the results window with current output""" - #clear the window - self.results.delete(0, END) - try: - for res in self.tabs[self.box.get()]: - self.results.insert(END, res) - except KeyError: - pass - - def process_incoming(self): - """process the incoming messages from running pylint""" - while self.msg_queue.qsize(): - try: - msg = self.msg_queue.get(0) - if msg == "DONE": - self.report_stream.output_contents() - return False - - #adding message to list of msgs - self.msgs.append(msg) - - #displaying msg if message type is selected in check box - if self.msg_type_dict.get(msg.C)(): - self.visible_msgs.append(msg) - msg_str = convert_to_string(msg) - self.lb_messages.insert(END, msg_str) - fg_color = COLORS.get(msg_str[:3], 'black') - self.lb_messages.itemconfigure(END, fg=fg_color) - - except six.moves.queue.Empty: - pass - return True - - def periodic_call(self): - """determine when to unlock the run button""" - if self.process_incoming(): - self.root.after(100, self.periodic_call) - else: - #enabling button so it can be run again - self.btnRun.config(state=NORMAL) - - def mainloop(self): - """launch the mainloop of the application""" - self.root.mainloop() - - def quit(self, _=None): - """quit the application""" - self.root.quit() - - def halt(self): # pylint: disable=no-self-use - """program halt placeholder""" - return - - def file_open(self, package=False, _=None): - """launch a file browser""" - if not package: - filename = askopenfilename(parent=self.root, - filetypes=[('pythonfiles', '*.py'), - ('allfiles', '*')], - title='Select Module') - else: - filename = askdirectory(title="Select A Folder", mustexist=1) - - if filename == (): - return - - self.txt_module.delete(0, END) - self.txt_module.insert(0, filename) - - def update_filenames(self): - """update the list of recent filenames""" - filename = self.txt_module.get() - if not filename: - filename = os.getcwd() - if filename+'\n' in self.filenames: - index = self.filenames.index(filename+'\n') - self.filenames.pop(index) - - #ensure only 10 most recent are stored - if len(self.filenames) == 10: - self.filenames.pop() - self.filenames.insert(0, filename+'\n') - - def set_history_window(self): - """update the history window with info from the history file""" - #clear the window - self.showhistory.delete(0, END) - # keep the last 10 most recent files - try: - view_history = open(HOME+HISTORY, 'r') - for hist in view_history.readlines(): - if hist not in self.filenames: - self.filenames.append(hist) - self.showhistory.insert(END, hist.split('\n')[0]) - view_history.close() - except IOError: - # do nothing since history file will be created later - return - - def run_lint(self, _=None): - """launches pylint""" - self.update_filenames() - self.root.configure(cursor='watch') - self.reporter = GUIReporter(self, output=self.report_stream) - module = self.txt_module.get() - if not module: - module = os.getcwd() - - #cleaning up msgs and windows - self.msgs = [] - self.visible_msgs = [] - self.lb_messages.delete(0, END) - self.tabs = {} - self.results.delete(0, END) - self.btnRun.config(state=DISABLED) - - #setting up a worker thread to run pylint - worker = Thread(target=lint_thread, args=(module, self.reporter, self,)) - self.periodic_call() - worker.start() - - # Overwrite the .pylint-gui-history file with all the new recently added files - # in order from filenames but only save last 10 files - write_history = open(HOME+HISTORY, 'w') - write_history.writelines(self.filenames) - write_history.close() - self.set_history_window() - - self.root.configure(cursor='') - - def show_sourcefile(self, event=None): # pylint: disable=unused-argument - selected = self.lb_messages.curselection() - if not selected: - return - - msg = self.visible_msgs[int(selected[0])] - scroll = msg.line - 3 - if scroll < 0: - scroll = 0 - - self.tabs["Source File"] = open(msg.path, "r").readlines() - self.box.set("Source File") - self.refresh_results_window() - self.results.yview(scroll) - self.results.select_set(msg.line - 1) - - -def lint_thread(module, reporter, gui): - """thread for pylint""" - gui.status.text = "processing module(s)" - pylint.lint.Run(args=[module], reporter=reporter, exit=False) - gui.msg_queue.put("DONE") - - -def Run(args): - """launch pylint gui from args""" - if args: - print('USAGE: pylint-gui\n launch a simple pylint gui using Tk') - sys.exit(1) - gui = LintGui() - gui.mainloop() - sys.exit(0) - -if __name__ == '__main__': - Run(sys.argv[1:]) diff --git a/pymode/libs/pylint/interfaces.py b/pymode/libs/pylint/interfaces.py index ac383ce7..5403818a 100644 --- a/pymode/libs/pylint/interfaces.py +++ b/pymode/libs/pylint/interfaces.py @@ -1,5 +1,8 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2009-2010, 2012-2013 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/lint.py b/pymode/libs/pylint/lint.py index 69bef2b8..537d6f25 100644 --- a/pymode/libs/pylint/lint.py +++ b/pymode/libs/pylint/lint.py @@ -1,5 +1,14 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2011-2014 Google, Inc. +# Copyright (c) 2012 FELD Boris +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2014-2015 Michal Nowikowski +# Copyright (c) 2015 Mihai Balint +# Copyright (c) 2015 Simu Toni +# Copyright (c) 2015 Aru Sahni +# Copyright (c) 2015-2016 Florian Bruhin +# Copyright (c) 2016 Glenn Matthews + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -26,8 +35,8 @@ except ImportError: multiprocessing = None import sys -import warnings import tokenize +import warnings import six @@ -37,6 +46,7 @@ from pylint import checkers from pylint import interfaces from pylint import reporters +from pylint import exceptions from pylint import utils from pylint import config from pylint.__pkginfo__ import version @@ -44,10 +54,7 @@ MANAGER = astroid.MANAGER -INCLUDE_IDS_HELP = ("Deprecated. It was used to include message\'s " - "id in output. Use --msg-template instead.") -SYMBOLS_HELP = ("Deprecated. It was used to include symbolic ids of " - "messages in output. Use --msg-template instead.") + def _get_new_args(message): location = ( @@ -131,7 +138,7 @@ def _patch_sysmodules(): 'traceback. Please report such errors !'), 'F0010': ('error while code parsing: %s', 'parse-error', - 'Used when an exception occured while building the Astroid ' + 'Used when an exception occurred while building the Astroid ' 'representation which could be handled by astroid.'), 'I0001': ('Unable to run raw checkers on built-in module %s', @@ -246,8 +253,8 @@ class PyLinter(config.OptionsManagerMixIn, * handle message activation / deactivation at the module level * handle some basic but necessary stats'data (number of classes, methods...) - IDE plugins developpers: you may have to call - `astroid.builder.MANAGER.astroid_cache.clear()` accross run if you want + IDE plugin developers: you may have to call + `astroid.builder.MANAGER.astroid_cache.clear()` across runs if you want to ensure the latest code version is actually checked. """ @@ -289,21 +296,12 @@ def make_options(): 'short': 'f', 'group': 'Reports', 'help' : 'Set the output format. Available formats are text,' - ' parseable, colorized, msvs (visual studio) and html. You ' - 'can also give a reporter class, eg mypackage.mymodule.' + ' parseable, colorized, json and msvs (visual studio).' + 'You can also give a reporter class, eg mypackage.mymodule.' 'MyReporterClass.'}), - ('files-output', - {'default': 0, 'type' : 'yn', 'metavar' : '', - 'group': 'Reports', 'level': 1, - 'help' : 'Put messages in a separate file for each module / ' - 'package specified on the command line instead of printing ' - 'them on stdout. Reports (if any) will be written in a file ' - 'name "pylint_global.[txt|html]". This option is deprecated and ' - 'it will be removed in Pylint 2.0.'}), - ('reports', - {'default': 1, 'type' : 'yn', 'metavar' : '', + {'default': False, 'type' : 'yn', 'metavar' : '', 'short': 'r', 'group': 'Reports', 'help' : 'Tells whether to display a full report or only the ' @@ -321,8 +319,11 @@ def make_options(): 'warnings messages and the total number of ' 'statements analyzed. This is used by the global ' 'evaluation report (RP0004).'}), - - ('comment', utils.deprecated_option(opt_type='yn')), + ('score', + {'default': True, 'type': 'yn', 'metavar': '', + 'short': 's', + 'group': 'Reports', + 'help': 'Activate the evaluation score.'}), ('confidence', {'type' : 'multiple_choice', 'metavar': '', @@ -390,25 +391,11 @@ def make_options(): ' loading into the active Python interpreter and may run' ' arbitrary code')} ), - - ('optimize-ast', - {'type': 'yn', 'metavar': '', 'default': False, - 'help': ('Allow optimization of some AST trees. This will ' - 'activate a peephole AST optimizer, which will ' - 'apply various small optimizations. For instance, ' - 'it can be used to obtain the result of joining ' - 'multiple strings with the addition operator. ' - 'Joining a lot of strings can lead to a maximum ' - 'recursion error in Pylint and this flag can prevent ' - 'that. It has one side effect, the resulting AST ' - 'will be different than the one from reality. ' - 'This option is deprecated and it will be removed in Pylint 2.0.')} - ), ) option_groups = ( - ('Messages control', 'Options controling analysis messages'), - ('Reports', 'Options related to output formating and reporting'), + ('Messages control', 'Options controlling analysis messages'), + ('Reports', 'Options related to output formatting and reporting'), ) def __init__(self, options=(), reporter=None, option_groups=(), @@ -453,8 +440,6 @@ def __init__(self, options=(), reporter=None, option_groups=(), report_messages_by_module_stats), ('RP0003', 'Messages', report_messages_stats), - ('RP0004', 'Global evaluation', - self.report_evaluation), ) self.register_checker(self) self._dynamic_plugins = set() @@ -601,6 +586,7 @@ def error_mode(self): self.disable('python3') self.set_option('reports', False) self.set_option('persistent', False) + self.set_option('score', False) def python3_porting_mode(self): """Disable all other checkers and enable Python 3 warnings.""" @@ -652,7 +638,7 @@ def process_tokens(self, tokens): meth = self._options_methods[opt] except KeyError: meth = self._bw_options_methods[opt] - # found a "(dis|en)able-msg" pragma deprecated suppresssion + # found a "(dis|en)able-msg" pragma deprecated suppression self.add_message('deprecated-pragma', line=start[0], args=(opt, opt.replace('-msg', ''))) for msgid in utils._splitstrip(value): @@ -668,7 +654,7 @@ def process_tokens(self, tokens): self._ignore_file = True return meth(msgid, 'module', start[0]) - except utils.UnknownMessage: + except exceptions.UnknownMessageError: self.add_message('bad-option-value', args=msgid, line=start[0]) else: self.add_message('unrecognized-inline-option', args=opt, line=start[0]) @@ -699,7 +685,9 @@ def prepare_checkers(self): reverse=True) return neededcheckers - def should_analyze_file(self, modname, path): # pylint: disable=unused-argument, no-self-use + # pylint: disable=unused-argument + @staticmethod + def should_analyze_file(modname, path, is_argument=False): """Returns whether or not a module should be checked. This implementation returns True for all python source file, indicating @@ -710,10 +698,16 @@ def should_analyze_file(self, modname, path): # pylint: disable=unused-argument, :param str modname: The name of the module to be checked. :param str path: The full path to the source code of the module. + :param bool is_argument: Whetter the file is an argument to pylint or not. + Files which respect this property are always + checked, since the user requested it explicitly. :returns: True if the module should be checked. :rtype: bool """ + if is_argument: + return True return path.endswith('.py') + # pylint: enable=unused-argument def check(self, files_or_modules): """main checking entry: check a list of files or modules from their @@ -791,7 +785,7 @@ def _parallel_task(self, files_or_modules): child.join() if failed: - print("Error occured, stopping the linter.", file=sys.stderr) + print("Error occurred, stopping the linter.", file=sys.stderr) sys.exit(32) def _parallel_check(self, files_or_modules): @@ -841,12 +835,10 @@ def _do_check(self, files_or_modules): walker.add_checker(checker) # build ast and check modules or packages for descr in self.expand_files(files_or_modules): - modname, filepath = descr['name'], descr['path'] - if not descr['isarg'] and not self.should_analyze_file(modname, filepath): + modname, filepath, is_arg = descr['name'], descr['path'], descr['isarg'] + if not self.should_analyze_file(modname, filepath, is_argument=is_arg): continue - if self.config.files_output: - reportfile = 'pylint_%s.%s' % (modname, self.reporter.extension) - self.reporter.set_output(open(reportfile, 'w')) + self.set_current_module(modname, filepath) # get the module representation ast_node = self.get_ast(filepath, modname) @@ -902,14 +894,12 @@ def get_ast(self, filepath, modname): """return a ast(roid) representation for a module""" try: return MANAGER.ast_from_file(filepath, modname, source=True) + except astroid.AstroidSyntaxError as ex: + self.add_message('syntax-error', + line=getattr(ex.error, 'lineno', 0), + args=str(ex.error)) except astroid.AstroidBuildingException as ex: - if isinstance(ex.args[0], SyntaxError): - ex = ex.args[0] - self.add_message('syntax-error', - line=ex.lineno or 0, - args=ex.msg) - else: - self.add_message('parse-error', args=ex) + self.add_message('parse-error', args=ex) except Exception as ex: # pylint: disable=broad-except import traceback traceback.print_exc() @@ -951,7 +941,6 @@ def open(self): self.stats = {'by_module' : {}, 'by_msg' : {}, } - MANAGER.optimize_ast = self.config.optimize_ast MANAGER.always_load_extensions = self.config.unsafe_load_any_extension MANAGER.extension_package_whitelist.update( self.config.extension_pkg_whitelist) @@ -973,27 +962,26 @@ def generate_reports(self): self.reporter.on_close(self.stats, previous_stats) if self.config.reports: sect = self.make_reports(self.stats, previous_stats) - if self.config.files_output: - filename = 'pylint_global.' + self.reporter.extension - self.reporter.set_output(open(filename, 'w')) else: sect = report_nodes.Section() + if self.config.reports: self.reporter.display_reports(sect) + self._report_evaluation() # save results if persistent run if self.config.persistent: config.save_results(self.stats, self.file_state.base_name) else: self.reporter.on_close(self.stats, {}) - # specific reports ######################################################## - - def report_evaluation(self, sect, stats, previous_stats): + def _report_evaluation(self): """make the global evaluation report""" # check with at least check 1 statements (usually 0 when there is a # syntax error preventing pylint from further processing) - if stats['statement'] == 0: - raise utils.EmptyReport() + previous_stats = config.load_results(self.file_state.base_name) + if self.stats['statement'] == 0: + return + # get a global note for the code evaluation = self.config.evaluation try: @@ -1001,12 +989,15 @@ def report_evaluation(self, sect, stats, previous_stats): except Exception as ex: # pylint: disable=broad-except msg = 'An exception occurred while rating: %s' % ex else: - stats['global_note'] = note + self.stats['global_note'] = note msg = 'Your code has been rated at %.2f/10' % note pnote = previous_stats.get('global_note') if pnote is not None: msg += ' (previous run: %.2f/10, %+.2f)' % (pnote, note - pnote) - sect.append(report_nodes.Text(msg)) + + if self.config.score: + sect = report_nodes.EvaluationSection(msg) + self.reporter.display_reports(sect) # some reporting functions #################################################### @@ -1022,7 +1013,7 @@ def report_messages_stats(sect, stats, _): """make messages type report""" if not stats['by_msg']: # don't print this report when we didn't detected any errors - raise utils.EmptyReport() + raise exceptions.EmptyReportError() in_order = sorted([(value, msg_id) for msg_id, value in six.iteritems(stats['by_msg']) if not msg_id.startswith('I')]) @@ -1036,7 +1027,7 @@ def report_messages_by_module_stats(sect, stats, _): """make errors / warnings by modules report""" if len(stats['by_module']) == 1: # don't print this report when we are analysing a single module - raise utils.EmptyReport() + raise exceptions.EmptyReportError() by_mod = collections.defaultdict(dict) for m_type in ('fatal', 'error', 'warning', 'refactor', 'convention'): total = stats[m_type] @@ -1065,7 +1056,7 @@ def report_messages_by_module_stats(sect, stats, _): for val in line[:-1]: lines.append('%.2f' % val) if len(lines) == 5: - raise utils.EmptyReport() + raise exceptions.EmptyReportError() sect.append(report_nodes.Table(children=lines, cols=5, rheaders=1)) @@ -1118,7 +1109,7 @@ def fix_import_path(args): Within this context, each of the given arguments is importable. Paths are added to sys.path in corresponding order to the arguments. We avoid adding duplicate directories to sys.path. - `sys.path` is reset to its original value upon exitign this context. + `sys.path` is reset to its original value upon exiting this context. """ orig = list(sys.path) changes = [] @@ -1128,7 +1119,7 @@ def fix_import_path(args): continue else: changes.append(path) - sys.path[:] = changes + sys.path + sys.path[:] = changes + ["."] + sys.path try: yield finally: @@ -1259,8 +1250,7 @@ def __init__(self, args, reporter=None, exit=True): 'been issued by analysing pylint output status code\n', level=1) # read configuration - linter.disable('suppressed-message') - linter.disable('useless-suppression') + linter.disable('I') linter.read_config_file() config_parser = linter.cfgfile_parser # run init hook, if present, before loading plugins diff --git a/pymode/libs/pylint/pyreverse/__init__.py b/pymode/libs/pylint/pyreverse/__init__.py index 496f0fb7..8a12c4fe 100644 --- a/pymode/libs/pylint/pyreverse/__init__.py +++ b/pymode/libs/pylint/pyreverse/__init__.py @@ -1,5 +1,4 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/diadefslib.py b/pymode/libs/pylint/pyreverse/diadefslib.py index 2f958ac8..16831ccc 100644 --- a/pymode/libs/pylint/pyreverse/diadefslib.py +++ b/pymode/libs/pylint/pyreverse/diadefslib.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2008-2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2015-2016 Claudiu Popa +# Copyright (c) 2016 Ashley Whetter + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/diagrams.py b/pymode/libs/pylint/pyreverse/diagrams.py index e5c3439d..e6ac9fd9 100644 --- a/pymode/libs/pylint/pyreverse/diagrams.py +++ b/pymode/libs/pylint/pyreverse/diagrams.py @@ -1,5 +1,6 @@ -# Copyright (c) 2004-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2008-2010, 2012-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/inspector.py b/pymode/libs/pylint/pyreverse/inspector.py index d45dd642..a6b8704d 100644 --- a/pymode/libs/pylint/pyreverse/inspector.py +++ b/pymode/libs/pylint/pyreverse/inspector.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/main.py b/pymode/libs/pylint/pyreverse/main.py index d37dede4..f3372ea5 100644 --- a/pymode/libs/pylint/pyreverse/main.py +++ b/pymode/libs/pylint/pyreverse/main.py @@ -1,5 +1,6 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2008-2010, 2012-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -70,12 +71,11 @@ ("output", dict(short="o", dest="output_format", action="store", default="dot", metavar="", help="create a *. output file if format available.")), - ("ignore", {'type' : "csv", 'metavar' : "", + ("ignore", {'type' : "csv", 'metavar' : "", 'dest' : "black_list", "default" : ('CVS',), - 'help' : "add (may be a directory) to the black list. " - "It should be a base name, not a path. You may set " - "this option multiple times."}), - ("project", {'default': "No Name", 'type' : 'string', 'short': 'p', + 'help' : "Add files or directories to the blacklist. They " + "should be base names, not paths."}), + ("project", {'default': "", 'type' : 'string', 'short': 'p', 'metavar': '', 'help': 'set the project name.'}), ) # FIXME : quiet mode diff --git a/pymode/libs/pylint/pyreverse/utils.py b/pymode/libs/pylint/pyreverse/utils.py index 09fc0626..5ab38416 100644 --- a/pymode/libs/pylint/pyreverse/utils.py +++ b/pymode/libs/pylint/pyreverse/utils.py @@ -1,5 +1,6 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2008, 2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/vcgutils.py b/pymode/libs/pylint/pyreverse/vcgutils.py index 2240ec57..7fe930f3 100644 --- a/pymode/libs/pylint/pyreverse/vcgutils.py +++ b/pymode/libs/pylint/pyreverse/vcgutils.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2008-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/pyreverse/writer.py b/pymode/libs/pylint/pyreverse/writer.py index acd0f370..312d14ef 100644 --- a/pymode/libs/pylint/pyreverse/writer.py +++ b/pymode/libs/pylint/pyreverse/writer.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2008-2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/reporters/__init__.py b/pymode/libs/pylint/reporters/__init__.py index 2aac9b4c..327ef644 100644 --- a/pymode/libs/pylint/reporters/__init__.py +++ b/pymode/libs/pylint/reporters/__init__.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006, 2010, 2012-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -59,8 +61,9 @@ def set_output(self, output=None): def encode(self, string): if not isinstance(string, six.text_type): return string + encoding = (getattr(self.out, 'encoding', None) or - locale.getdefaultlocale()[1] or + locale.getpreferredencoding(do_setlocale=False) or sys.getdefaultencoding()) # errors=replace, we don't want to crash when attempting to show # source code line that can't be encoded with the current locale @@ -78,12 +81,6 @@ def display_reports(self, layout): layout.children[0].children[0].data += ' (%s)' % layout.report_id self._display(layout) - def display_results(self, layout): - warnings.warn("display_results is deprecated, use display_reports instead. " - "The former will be removed in Pylint 2.0.", - DeprecationWarning) - self.display_reports(layout) - def _display(self, layout): """display the layout""" raise NotImplementedError() diff --git a/pymode/libs/pylint/reporters/guireporter.py b/pymode/libs/pylint/reporters/guireporter.py deleted file mode 100644 index 5e145860..00000000 --- a/pymode/libs/pylint/reporters/guireporter.py +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -""" reporter used by gui.py """ - -import sys - -from pylint.interfaces import IReporter -from pylint.reporters import BaseReporter -from pylint.reporters.ureports.text_writer import TextWriter - - -class GUIReporter(BaseReporter): - """saves messages""" - - __implements__ = IReporter - extension = '' - - def __init__(self, gui, output=sys.stdout): - """init""" - BaseReporter.__init__(self, output) - self.gui = gui - - def handle_message(self, msg): - """manage message of different type and in the context of path""" - self.gui.msg_queue.put(msg) - - def _display(self, layout): - """launch layouts display""" - TextWriter().format(layout, self.out) diff --git a/pymode/libs/pylint/reporters/html.py b/pymode/libs/pylint/reporters/html.py deleted file mode 100644 index 594d5c48..00000000 --- a/pymode/libs/pylint/reporters/html.py +++ /dev/null @@ -1,102 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""HTML reporter""" - -import itertools -import string -import sys -import warnings - -import six - -from pylint.interfaces import IReporter -from pylint.reporters import BaseReporter -from pylint.reporters.ureports.html_writer import HTMLWriter -from pylint.reporters.ureports.nodes import Section, Table - - -class HTMLReporter(BaseReporter): - """report messages and layouts in HTML""" - - __implements__ = IReporter - name = 'html' - extension = 'html' - - def __init__(self, output=sys.stdout): - BaseReporter.__init__(self, output) - self.msgs = [] - # Add placeholders for title and parsed messages - self.header = None - self.msgargs = [] - - warnings.warn("This reporter will be removed in Pylint 2.0.", - DeprecationWarning) - - @staticmethod - def _parse_msg_template(msg_template): - formatter = string.Formatter() - parsed = formatter.parse(msg_template) - for item in parsed: - if item[1]: - yield item[1] - - def _parse_template(self): - """Helper function to parse the message template""" - self.header = [] - if self.linter.config.msg_template: - msg_template = self.linter.config.msg_template - else: - msg_template = '{category}{module}{obj}{line}{column}{msg}' - - _header, _msgs = itertools.tee(self._parse_msg_template(msg_template)) - self.header = list(_header) - self.msgargs = list(_msgs) - - def handle_message(self, msg): - """manage message of different type and in the context of path""" - - # It would be better to do this in init, but currently we do not - # have access to the linter (as it is setup in lint.set_reporter() - # Therefore we try to parse just the once. - if self.header is None: - self._parse_template() - - # We want to add the lines given by the template - values = [getattr(msg, field) for field in self.msgargs] - self.msgs += [value if isinstance(value, six.text_type) else str(value) - for value in values] - - def set_output(self, output=None): - """set output stream - - messages buffered for old output is processed first""" - if self.out and self.msgs: - self._display(Section()) - BaseReporter.set_output(self, output) - - def _display(self, layout): - """launch layouts display - - overridden from BaseReporter to add insert the messages section - (in add_message, message is not displayed, just collected so it - can be displayed in an html table) - """ - HTMLWriter().format(layout, self.out) - - def display_messages(self, layout): - if self.msgs: - # add stored messages to the layout - msgs = self.header - cols = len(self.header) - msgs += self.msgs - sect = Section('Messages') - layout.append(sect) - sect.append(Table(cols=cols, children=msgs, rheaders=1)) - self.msgs = [] - self._display(layout) - - -def register(linter): - """Register the reporter classes with the linter.""" - linter.register_reporter(HTMLReporter) diff --git a/pymode/libs/pylint/reporters/json.py b/pymode/libs/pylint/reporters/json.py index 8633120e..be37b211 100644 --- a/pymode/libs/pylint/reporters/json.py +++ b/pymode/libs/pylint/reporters/json.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -25,18 +25,18 @@ def __init__(self, output=sys.stdout): BaseReporter.__init__(self, output) self.messages = [] - def handle_message(self, message): + def handle_message(self, msg): """Manage message of different type and in the context of path.""" self.messages.append({ - 'type': message.category, - 'module': message.module, - 'obj': message.obj, - 'line': message.line, - 'column': message.column, - 'path': message.path, - 'symbol': message.symbol, + 'type': msg.category, + 'module': msg.module, + 'obj': msg.obj, + 'line': msg.line, + 'column': msg.column, + 'path': msg.path, + 'symbol': msg.symbol, # pylint: disable=deprecated-method; deprecated since 3.2. - 'message': cgi.escape(message.msg or ''), + 'message': cgi.escape(msg.msg or ''), }) def display_messages(self, layout): @@ -44,7 +44,7 @@ def display_messages(self, layout): if self.messages: print(json.dumps(self.messages, indent=4), file=self.out) - def display_reports(self, _): + def display_reports(self, layout): # pylint: disable=arguments-differ """Don't do nothing in this reporter.""" def _display(self, layout): diff --git a/pymode/libs/pylint/reporters/text.py b/pymode/libs/pylint/reporters/text.py index 5cba1cb1..a47d7f8a 100644 --- a/pymode/libs/pylint/reporters/text.py +++ b/pymode/libs/pylint/reporters/text.py @@ -1,5 +1,8 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2007, 2010-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -10,6 +13,7 @@ """ from __future__ import print_function +import os import warnings import sys @@ -186,9 +190,11 @@ def __init__(self, output=None, color_mapping=None): TextReporter.__init__(self, output) self.color_mapping = color_mapping or \ dict(ColorizedTextReporter.COLOR_MAPPING) - if sys.platform == 'win32': - import colorama - self.out = colorama.AnsiToWin32(self.out) + ansi_terms = ['xterm-16color', 'xterm-256color'] + if os.environ.get('TERM') not in ansi_terms: + if sys.platform == 'win32': + import colorama + self.out = colorama.AnsiToWin32(self.out) def _get_decoration(self, msg_id): """Returns the tuple color, style associated with msg_id as defined diff --git a/pymode/libs/pylint/reporters/ureports/__init__.py b/pymode/libs/pylint/reporters/ureports/__init__.py index 6fdbd938..e294df83 100644 --- a/pymode/libs/pylint/reporters/ureports/__init__.py +++ b/pymode/libs/pylint/reporters/ureports/__init__.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING diff --git a/pymode/libs/pylint/reporters/ureports/html_writer.py b/pymode/libs/pylint/reporters/ureports/html_writer.py deleted file mode 100644 index 5c7fe8a9..00000000 --- a/pymode/libs/pylint/reporters/ureports/html_writer.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""HTML formatting drivers for ureports""" - -from pylint.reporters.ureports import BaseWriter - - -class HTMLWriter(BaseWriter): - """format layouts as HTML""" - - def __init__(self, snippet=None): - super(HTMLWriter, self).__init__() - self.snippet = snippet - - def begin_format(self): - """begin to format a layout""" - super(HTMLWriter, self).begin_format() - if self.snippet is None: - self.writeln(u'') - self.writeln(u'') - - def end_format(self): - """finished to format a layout""" - if self.snippet is None: - self.writeln(u'') - self.writeln(u'') - - def visit_section(self, layout): - """display a section as html, using div + h[section level]""" - self.section += 1 - self.writeln(u'
') - self.format_children(layout) - self.writeln(u'
') - self.section -= 1 - - def visit_title(self, layout): - """display a title using """ - self.write(u'' % self.section) - self.format_children(layout) - self.writeln(u'' % self.section) - - def visit_table(self, layout): - """display a table as html""" - self.writeln(u'') - table_content = self.get_table_content(layout) - for i, row in enumerate(table_content): - if i == 0 and layout.rheaders: - self.writeln(u'') - else: - self.writeln(u'' % (u'even' if i % 2 else u'odd')) - for j, cell in enumerate(row): - cell = cell or u' ' - if (layout.rheaders and i == 0) or \ - (layout.cheaders and j == 0): - self.writeln(u'' % cell) - else: - self.writeln(u'' % cell) - self.writeln(u'') - self.writeln(u'
%s%s
') - - def visit_paragraph(self, layout): - """display links (using

)""" - self.write(u'

') - self.format_children(layout) - self.write(u'

') - - def visit_verbatimtext(self, layout): - """display verbatim text (using
)"""
-        self.write(u'
')
-        self.write(layout.data.replace(u'&', u'&').replace(u'<', u'<'))
-        self.write(u'
') - - def visit_text(self, layout): - """add some text""" - data = layout.data - if layout.escaped: - data = data.replace(u'&', u'&').replace(u'<', u'<') - self.write(data) diff --git a/pymode/libs/pylint/reporters/ureports/nodes.py b/pymode/libs/pylint/reporters/ureports/nodes.py index 0d56b35a..24f87ca8 100644 --- a/pymode/libs/pylint/reporters/ureports/nodes.py +++ b/pymode/libs/pylint/reporters/ureports/nodes.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -128,6 +128,19 @@ def __init__(self, title=None, description=None, **kwargs): self.insert(0, Title(children=(title,))) +class EvaluationSection(Section): + + def __init__(self, message, **kwargs): + super(EvaluationSection, self).__init__(**kwargs) + title = Paragraph() + title.append(Text("-" * len(message))) + self.append(title) + + message_body = Paragraph() + message_body.append(Text(message)) + self.append(message_body) + + class Title(BaseLayout): """a title diff --git a/pymode/libs/pylint/reporters/ureports/text_writer.py b/pymode/libs/pylint/reporters/ureports/text_writer.py index d86d3f6c..a04ad8a8 100644 --- a/pymode/libs/pylint/reporters/ureports/text_writer.py +++ b/pymode/libs/pylint/reporters/ureports/text_writer.py @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2015-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -30,6 +30,13 @@ def visit_section(self, layout): self.section -= 1 self.writeln() + def visit_evaluationsection(self, layout): + """Display an evaluation section as a text.""" + self.section += 1 + self.format_children(layout) + self.section -= 1 + self.writeln() + def visit_title(self, layout): title = u''.join(list(self.compute_content(layout))) self.writeln(title) diff --git a/pymode/libs/pylint/test/data/__init__.py b/pymode/libs/pylint/test/data/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/data/ascript b/pymode/libs/pylint/test/data/ascript deleted file mode 100644 index f401ebc4..00000000 --- a/pymode/libs/pylint/test/data/ascript +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/python -"""ttttttttttttttttttttoooooooooooooooooooooooooooooooooooooooooooooooooooooo lllllllllllooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnngggggggggggggggggg""" diff --git a/pymode/libs/pylint/test/data/classes_No_Name.dot b/pymode/libs/pylint/test/data/classes_No_Name.dot deleted file mode 100644 index 3a9df796..00000000 --- a/pymode/libs/pylint/test/data/classes_No_Name.dot +++ /dev/null @@ -1,12 +0,0 @@ -digraph "classes_No_Name" { -charset="utf-8" -rankdir=BT -"0" [label="{Ancestor|attr : str\lcls_member\l|get_value()\lset_value()\l}", shape="record"]; -"1" [label="{DoNothing|\l|}", shape="record"]; -"2" [label="{Interface|\l|get_value()\lset_value()\l}", shape="record"]; -"3" [label="{Specialization|TYPE : str\lrelation\ltop : str\l|}", shape="record"]; -"3" -> "0" [arrowhead="empty", arrowtail="none"]; -"0" -> "2" [arrowhead="empty", arrowtail="node", style="dashed"]; -"1" -> "0" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="cls_member", style="solid"]; -"1" -> "3" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="relation", style="solid"]; -} diff --git a/pymode/libs/pylint/test/data/clientmodule_test.py b/pymode/libs/pylint/test/data/clientmodule_test.py deleted file mode 100644 index e520e88e..00000000 --- a/pymode/libs/pylint/test/data/clientmodule_test.py +++ /dev/null @@ -1,29 +0,0 @@ -""" docstring for file clientmodule.py """ -from data.suppliermodule_test import Interface, DoNothing - -class Ancestor(object): - """ Ancestor method """ - __implements__ = (Interface,) - cls_member = DoNothing() - - def __init__(self, value): - local_variable = 0 - self.attr = 'this method shouldn\'t have a docstring' - self.__value = value - - def get_value(self): - """ nice docstring ;-) """ - return self.__value - - def set_value(self, value): - self.__value = value - return 'this method shouldn\'t have a docstring' - -class Specialization(Ancestor): - TYPE = 'final class' - top = 'class' - - def __init__(self, value, _id): - Ancestor.__init__(self, value) - self._id = _id - self.relation = DoNothing() diff --git a/pymode/libs/pylint/test/data/packages_No_Name.dot b/pymode/libs/pylint/test/data/packages_No_Name.dot deleted file mode 100644 index 1ceeb724..00000000 --- a/pymode/libs/pylint/test/data/packages_No_Name.dot +++ /dev/null @@ -1,8 +0,0 @@ -digraph "packages_No_Name" { -charset="utf-8" -rankdir=BT -"0" [label="data", shape="box"]; -"1" [label="data.clientmodule_test", shape="box"]; -"2" [label="data.suppliermodule_test", shape="box"]; -"1" -> "2" [arrowhead="open", arrowtail="none"]; -} diff --git a/pymode/libs/pylint/test/data/suppliermodule_test.py b/pymode/libs/pylint/test/data/suppliermodule_test.py deleted file mode 100644 index 24dc9a02..00000000 --- a/pymode/libs/pylint/test/data/suppliermodule_test.py +++ /dev/null @@ -1,10 +0,0 @@ -""" file suppliermodule.py """ - -class Interface: - def get_value(self): - raise NotImplementedError - - def set_value(self, value): - raise NotImplementedError - -class DoNothing: pass diff --git a/pymode/libs/pylint/test/extensions/__init__.py b/pymode/libs/pylint/test/extensions/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/extensions/data/bad_builtin.py b/pymode/libs/pylint/test/extensions/data/bad_builtin.py deleted file mode 100644 index fd3e5c05..00000000 --- a/pymode/libs/pylint/test/extensions/data/bad_builtin.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=missing-docstring - -TEST = map(str, (1, 2, 3)) # [bad-builtin] -TEST1 = filter(str, (1, 2, 3)) # [bad-builtin] diff --git a/pymode/libs/pylint/test/extensions/data/docstring.py b/pymode/libs/pylint/test/extensions/data/docstring.py deleted file mode 100644 index b278c943..00000000 --- a/pymode/libs/pylint/test/extensions/data/docstring.py +++ /dev/null @@ -1,48 +0,0 @@ -"""Checks of Dosctrings 'docstring-first-line-empty' 'bad-docstring-quotes'""" - - -def check_messages(*messages): - """ - docstring""" - return messages - -def function2(): - """Test Ok""" - pass - -class FFFF(object): - """ - Test Docstring First Line Empty - """ - - def method1(self): - ''' - Test Triple Single Quotes docstring - ''' - pass - - def method2(self): - "bad docstring 1" - pass - - def method3(self): - 'bad docstring 2' - pass - - def method4(self): - ' """bad docstring 3 ' - pass - - @check_messages('bad-open-mode', 'redundant-unittest-assert', - 'deprecated-module') - def method5(self): - """Test OK 1 with decorators""" - pass - - def method6(self): - r"""Test OK 2 with raw string""" - pass - - def method7(self): - u"""Test OK 3 with unicode string""" - pass diff --git a/pymode/libs/pylint/test/extensions/data/elif.py b/pymode/libs/pylint/test/extensions/data/elif.py deleted file mode 100644 index 22e79c1d..00000000 --- a/pymode/libs/pylint/test/extensions/data/elif.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Checks use of "else if" triggers a refactor message""" - -def my_function(): - """docstring""" - myint = 2 - if myint > 5: - pass - else: - if myint <= 5: - pass - else: - myint = 3 - if myint > 2: - if myint > 3: - pass - elif myint == 3: - pass - elif myint < 3: - pass - else: - if myint: - pass - else: - if myint: - pass - myint = 4 diff --git a/pymode/libs/pylint/test/extensions/data/mccabe.py b/pymode/libs/pylint/test/extensions/data/mccabe.py deleted file mode 100644 index fdbdb5f0..00000000 --- a/pymode/libs/pylint/test/extensions/data/mccabe.py +++ /dev/null @@ -1,205 +0,0 @@ -"""Checks use of "too-complex" check""" - - -def f1(): - """McCabe rating: 1""" - pass - - -def f2(n): - """McCabe rating: 1""" - k = n + 4 - s = k + n - return s - - -def f3(n): - """McCabe rating: 3""" - if n > 3: - return "bigger than three" - elif n > 4: - return "is never executed" - else: - return "smaller than or equal to three" - - -def f4(): - """McCabe rating: 2""" - for i in range(10): - print(i) - - -def f5(mylist): - """McCabe rating: 2""" - for i in mylist: - print(i) - else: - print(None) - - -def f6(n): - """McCabe rating: 2""" - if n > 4: - return f(n - 1) - else: - return n - - -def f7(): - """McCabe rating: 3""" - def b(): - """McCabe rating: 2""" - def c(): - """McCabe rating: 1""" - pass - c() - b() - - -def f8(): - """McCabe rating: 4""" - try: - print(1) - except TypeA: - print(2) - except TypeB: - print(3) - else: - print(4) - - -def f9(): - """McCabe rating: 9""" - myint = 2 - if myint > 5: - pass - else: - if myint <= 5: - pass - else: - myint = 3 - if myint > 2: - if myint > 3: - pass - elif myint == 3: - pass - elif myint < 3: - pass - else: - if myint: - pass - else: - if myint: - pass - myint = 4 - - -def f10(): - """McCabe rating: 11""" - myint = 2 - if myint == 5: - return myint - elif myint == 6: - return myint - elif myint == 7: - return myint - elif myint == 8: - return myint - elif myint == 9: - return myint - elif myint == 10: - if myint == 8: - while True: - return True - elif myint == 8: - with myint: - return 8 - else: - if myint == 2: - return myint - return myint - return myint - - -class MyClass1(object): - """Class of example to test mccabe""" - _name = 'MyClass' # To force a tail.node=None - - def method1(): - """McCabe rating: 1""" - pass - - def method2(self, param1): - """McCabe rating: 18""" - if not param1: - pass - pass - if param1: - pass - else: - pass - - pass - - if param1: - pass - if param1: - pass - if param1: - pass - if param1: - pass - if param1: - pass - if param1: - pass - if param1: - for value in range(5): - pass - - pass - for count in range(6): - with open('myfile') as fp: - count += 1 - pass - pass - try: - pass - if not param1: - pass - else: - pass - if param1: - raise BaseException('Error') - with open('myfile2') as fp2: - pass - pass - finally: - if param1 is not None: - pass - for count2 in range(8): - try: - pass - except BaseException('Error2'): - pass - return param1 - - -for count in range(10): - if count == 1: - exit(0) - elif count == 2: - exit(1) - else: - exit(2) - - -def method3(self): - try: - if True: - pass - else: - pass - finally: - pass - return True diff --git a/pymode/libs/pylint/test/extensions/test_bad_builtin.py b/pymode/libs/pylint/test/extensions/test_bad_builtin.py deleted file mode 100644 index 22f1dd9b..00000000 --- a/pymode/libs/pylint/test/extensions/test_bad_builtin.py +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for the pylint checker in :mod:`pylint.extensions.bad_builtin -""" - -import os -import os.path as osp -import unittest - -from pylint import checkers -from pylint.extensions.bad_builtin import BadBuiltinChecker -from pylint.lint import PyLinter, fix_import_path -from pylint.reporters import BaseReporter - - -class TestReporter(BaseReporter): - - def handle_message(self, msg): - self.messages.append(msg) - - def on_set_current_module(self, module, filepath): - self.messages = [] - - -class BadBuiltinTestCase(unittest.TestCase): - - expected = [ - ] - - - @classmethod - def setUpClass(cls): - cls._linter = PyLinter() - cls._linter.set_reporter(TestReporter()) - checkers.initialize(cls._linter) - cls._linter.register_checker(BadBuiltinChecker(cls._linter)) - cls._linter.disable('I') - - def test_types_redefined(self): - elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data', - 'bad_builtin.py') - with fix_import_path([elif_test]): - self._linter.check([elif_test]) - msgs = sorted(self._linter.reporter.messages, key=lambda item: item.line) - self.assertEqual(len(msgs), 2) - for msg, expected in zip(msgs, self.expected): - self.assertEqual(msg.symbol, 'bad-builtin') - self.assertEqual(msg.msg, expected) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_check_docs.py b/pymode/libs/pylint/test/extensions/test_check_docs.py deleted file mode 100644 index 9d12a851..00000000 --- a/pymode/libs/pylint/test/extensions/test_check_docs.py +++ /dev/null @@ -1,1174 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the pylint checkers in :mod:`pylint.extensions.check_docs`, -in particular the parameter documentation checker `DocstringChecker` -""" -from __future__ import division, print_function, absolute_import - -import unittest -import sys - -import astroid -from astroid import test_utils -from pylint.testutils import CheckerTestCase, Message, set_config - -from pylint.extensions.docparams import DocstringParameterChecker - - -class ParamDocCheckerTest(CheckerTestCase): - """Tests for pylint_plugin.ParamDocChecker""" - CHECKER_CLASS = DocstringParameterChecker - - def test_missing_func_params_in_sphinx_docstring(self): - """Example of a function with missing Sphinx parameter documentation in - the docstring - """ - node = test_utils.extract_node(""" - def function_foo(x, y, z): - '''docstring ... - - :param x: bla - - :param int z: bar - ''' - pass - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self.checker.visit_functiondef(node) - - def test_missing_func_params_in_google_docstring(self): - """Example of a function with missing Google style parameter - documentation in the docstring - """ - node = test_utils.extract_node(""" - def function_foo(x, y, z): - '''docstring ... - - Args: - x: bla - z (int): bar - - some other stuff - ''' - pass - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self.checker.visit_functiondef(node) - - def test_missing_func_params_in_numpy_docstring(self): - """Example of a function with missing NumPy style parameter - documentation in the docstring - """ - node = test_utils.extract_node(""" - def function_foo(x, y, z): - '''docstring ... - - Parameters - ---------- - x: - bla - z: int - bar - - some other stuff - ''' - pass - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self.checker.visit_functiondef(node) - - def test_tolerate_no_param_documentation_at_all(self): - """Example of a function with no parameter documentation at all - - No error message is emitted. - """ - node = test_utils.extract_node(""" - def function_foo(x, y): - '''docstring ... - - missing parameter documentation''' - pass - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - @set_config(accept_no_param_doc=False) - def test_don_t_tolerate_no_param_documentation_at_all(self): - """Example of a function with no parameter documentation at all - - No error message is emitted. - """ - node = test_utils.extract_node(""" - def function_foo(x, y): - '''docstring ... - - missing parameter documentation''' - pass - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('x, y',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self.checker.visit_functiondef(node) - - def _visit_methods_of_class(self, node): - """Visit all methods of a class node - - :param node: class node - :type node: :class:`astroid.scoped_nodes.Class` - """ - for body_item in node.body: - if (isinstance(body_item, astroid.FunctionDef) - and hasattr(body_item, 'name')): - self.checker.visit_functiondef(body_item) - - def test_missing_method_params_in_sphinx_docstring(self): - """Example of a class method with missing parameter documentation in - the Sphinx style docstring - """ - node = test_utils.extract_node(""" - class Foo(object): - def method_foo(self, x, y): - '''docstring ... - - missing parameter documentation - - :param x: bla - ''' - pass - """) - method_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=method_node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=method_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_missing_method_params_in_google_docstring(self): - """Example of a class method with missing parameter documentation in - the Google style docstring - """ - node = test_utils.extract_node(""" - class Foo(object): - def method_foo(self, x, y): - '''docstring ... - - missing parameter documentation - - Args: - x: bla - ''' - pass - """) - method_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=method_node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=method_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_missing_method_params_in_numpy_docstring(self): - """Example of a class method with missing parameter documentation in - the Numpy style docstring - """ - node = test_utils.extract_node(""" - class Foo(object): - def method_foo(self, x, y): - '''docstring ... - - missing parameter documentation - - Parameters - ---------- - x: - bla - ''' - pass - """) - method_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=method_node, - args=('y',)), - Message( - msg_id='missing-type-doc', - node=method_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_existing_func_params_in_sphinx_docstring(self): - """Example of a function with correctly documented parameters and - return values (Sphinx style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg, warg): - '''function foo ... - - :param xarg: bla xarg - :type xarg: int - - :param yarg: bla yarg - :type yarg: my.qualified.type - - :param int zarg: bla zarg - - :param my.qualified.type warg: bla warg - - :return: sum - :rtype: float - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_existing_func_params_in_google_docstring(self): - """Example of a function with correctly documented parameters and - return values (Google style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg, warg): - '''function foo ... - - Args: - xarg (int): bla xarg - yarg (my.qualified.type): bla - bla yarg - - zarg (int): bla zarg - warg (my.qualified.type): bla warg - - Returns: - float: sum - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_existing_func_params_in_numpy_docstring(self): - """Example of a function with correctly documented parameters and - return values (Numpy style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg, warg): - '''function foo ... - - Parameters - ---------- - xarg: int - bla xarg - yarg: my.qualified.type - bla yarg - - zarg: int - bla zarg - warg: my.qualified.type - bla warg - - Returns - ------- - float - sum - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_wrong_name_of_func_params_in_sphinx_docstring(self): - """Example of functions with inconsistent parameter names in the - signature and in the Sphinx style documentation - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg): - '''function foo ... - - :param xarg1: bla xarg - :type xarg: int - - :param yarg: bla yarg - :type yarg1: float - - :param str zarg1: bla zarg - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('xarg, xarg1, zarg, zarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('yarg, yarg1, zarg, zarg1',)), - ): - self.checker.visit_functiondef(node) - - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - :param yarg1: bla yarg - :type yarg1: float - - For the other parameters, see bla. - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('yarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('yarg1',)) - ): - self.checker.visit_functiondef(node) - - def test_wrong_name_of_func_params_in_google_docstring(self): - """Example of functions with inconsistent parameter names in the - signature and in the Google style documentation - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg): - '''function foo ... - - Args: - xarg1 (int): bla xarg - yarg (float): bla yarg - - zarg1 (str): bla zarg - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('xarg, xarg1, zarg, zarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('xarg, xarg1, zarg, zarg1',)), - ): - self.checker.visit_functiondef(node) - - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - Args: - yarg1 (float): bla yarg - - For the other parameters, see bla. - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('yarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('yarg1',)) - ): - self.checker.visit_functiondef(node) - - def test_wrong_name_of_func_params_in_numpy_docstring(self): - """Example of functions with inconsistent parameter names in the - signature and in the Numpy style documentation - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg, zarg): - '''function foo ... - - Parameters - ---------- - xarg1: int - bla xarg - yarg: float - bla yarg - - zarg1: str - bla zarg - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('xarg, xarg1, zarg, zarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('xarg, xarg1, zarg, zarg1',)), - ): - self.checker.visit_functiondef(node) - - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - Parameters - ---------- - yarg1: float - bla yarg - - For the other parameters, see bla. - ''' - return xarg + yarg - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('yarg1',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('yarg1',)) - ): - self.checker.visit_functiondef(node) - - def test_see_sentence_for_func_params_in_sphinx_docstring(self): - """Example for the usage of "For the other parameters, see" to avoid - too many repetitions, e.g. in functions or methods adhering to a - given interface (Sphinx style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - :param yarg: bla yarg - :type yarg: float - - For the other parameters, see :func:`bla` - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_see_sentence_for_func_params_in_google_docstring(self): - """Example for the usage of "For the other parameters, see" to avoid - too many repetitions, e.g. in functions or methods adhering to a - given interface (Google style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - Args: - yarg (float): bla yarg - - For the other parameters, see :func:`bla` - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_see_sentence_for_func_params_in_numpy_docstring(self): - """Example for the usage of "For the other parameters, see" to avoid - too many repetitions, e.g. in functions or methods adhering to a - given interface (Numpy style) - """ - node = test_utils.extract_node(""" - def function_foo(xarg, yarg): - '''function foo ... - - Parameters - ---------- - yarg: float - bla yarg - - For the other parameters, see :func:`bla` - ''' - return xarg + yarg - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_constr_params_in_class_sphinx(self): - """Example of a class with missing constructor parameter documentation - (Sphinx style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - :param y: bla - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - pass - - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_class_google(self): - """Example of a class with missing constructor parameter documentation - (Google style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - Args: - y: bla - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - pass - - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_class_numpy(self): - """Example of a class with missing constructor parameter documentation - (Numpy style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - Parameters - ---------- - y: - bla - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - pass - - """) - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_init_sphinx(self): - """Example of a class with missing constructor parameter documentation - (Sphinx style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - def __init__(self, x, y): - '''docstring foo constructor - - :param y: bla - - missing constructor parameter documentation - ''' - - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_init_google(self): - """Example of a class with missing constructor parameter documentation - (Google style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - def __init__(self, x, y): - '''docstring foo constructor - - Args: - y: bla - - missing constructor parameter documentation - ''' - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_init_numpy(self): - """Example of a class with missing constructor parameter documentation - (Numpy style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - def __init__(self, x, y): - '''docstring foo constructor - - Parameters - ---------- - y: - bla - - missing constructor parameter documentation - ''' - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)) - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_class_and_init_sphinx(self): - """Example of a class with missing constructor parameter documentation - in both the init docstring and the class docstring - (Sphinx style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - :param y: None - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - '''docstring foo - - :param y: bla - - missing constructor parameter documentation - ''' - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='multiple-constructor-doc', - node=node, - args=(node.name,)), - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)), - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)), - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_class_and_init_google(self): - """Example of a class with missing constructor parameter documentation - in both the init docstring and the class docstring - (Google style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - Args: - y: bla - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - '''docstring foo - - Args: - y: bla - - missing constructor parameter documentation - ''' - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='multiple-constructor-doc', - node=node, - args=(node.name,)), - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)), - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)), - ): - self._visit_methods_of_class(node) - - def test_constr_params_in_class_and_init_numpy(self): - """Example of a class with missing constructor parameter documentation - in both the init docstring and the class docstring - (Numpy style) - - Everything is completely analogous to functions. - """ - node = test_utils.extract_node(""" - class ClassFoo(object): - '''docstring foo - - Parameters - ---------- - y: - bla - - missing constructor parameter documentation - ''' - - def __init__(self, x, y): - '''docstring foo - - Parameters - ---------- - y: - bla - - missing constructor parameter documentation - ''' - pass - - """) - constructor_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='multiple-constructor-doc', - node=node, - args=(node.name,)), - Message( - msg_id='missing-param-doc', - node=node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=node, - args=('x, y',)), - Message( - msg_id='missing-param-doc', - node=constructor_node, - args=('x',)), - Message( - msg_id='missing-type-doc', - node=constructor_node, - args=('x, y',)), - ): - self._visit_methods_of_class(node) - - @unittest.skipIf(sys.version_info[0] != 3, "Enabled on Python 3") - def test_kwonlyargs_are_taken_in_account(self): - node = test_utils.extract_node(''' - def my_func(arg, *, kwonly, missing_kwonly): - """The docstring - - :param int arg: The argument. - :param bool kwonly: A keyword-arg. - """ - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('missing_kwonly', )), - Message( - msg_id='missing-type-doc', - node=node, - args=('missing_kwonly', ))): - self.checker.visit_functiondef(node) - - def test_warns_missing_args_sphinx(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - :param named_arg: Returned - :type named_arg: object - :returns: Maybe named_arg - :rtype: object or None - """ - if args: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('args',))): - self.checker.visit_functiondef(node) - - def test_warns_missing_kwargs_sphinx(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - :param named_arg: Returned - :type named_arg: object - :returns: Maybe named_arg - :rtype: object or None - """ - if kwargs: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('kwargs',))): - self.checker.visit_functiondef(node) - - def test_warns_missing_args_google(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - Args: - named_arg (object): Returned - - Returns: - object or None: Maybe named_arg - """ - if args: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('args',))): - self.checker.visit_functiondef(node) - - def test_warns_missing_kwargs_google(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - Args: - named_arg (object): Returned - - Returns: - object or None: Maybe named_arg - """ - if kwargs: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('kwargs',))): - self.checker.visit_functiondef(node) - - def test_warns_missing_args_numpy(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - Args - ---- - named_arg : object - Returned - - Returns - ------- - object or None - Maybe named_arg - """ - if args: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('args',))): - self.checker.visit_functiondef(node) - - def test_warns_missing_kwargs_numpy(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - Args - ---- - named_arg : object - Returned - - Returns - ------- - object or None - Maybe named_arg - """ - if kwargs: - return named_arg - ''') - with self.assertAddsMessages( - Message( - msg_id='missing-param-doc', - node=node, - args=('kwargs',))): - self.checker.visit_functiondef(node) - - def test_finds_args_without_type_sphinx(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - :param named_arg: Returned - :type named_arg: object - :param args: Optional arguments - :returns: Maybe named_arg - :rtype: object or None - """ - if args: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_finds_kwargs_without_type_sphinx(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - :param named_arg: Returned - :type named_arg: object - :param kwargs: Keyword arguments - :returns: Maybe named_arg - :rtype: object or None - """ - if kwargs: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_finds_args_without_type_google(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - Args: - named_arg (object): Returned - *args: Optional arguments - - Returns: - object or None: Maybe named_arg - """ - if args: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_finds_kwargs_without_type_google(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - Args: - named_arg (object): Returned - **kwargs: Keyword arguments - - Returns: - object or None: Maybe named_arg - """ - if kwargs: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_finds_args_without_type_numpy(self): - node = test_utils.extract_node(''' - def my_func(named_arg, *args): - """The docstring - - Args - ---- - named_arg : object - Returned - args : - Optional Arguments - - Returns - ------- - object or None - Maybe named_arg - """ - if args: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_finds_kwargs_without_type_numpy(self): - node = test_utils.extract_node(''' - def my_func(named_arg, **kwargs): - """The docstring - - Args - ---- - named_arg : object - Returned - kwargs : - Keyword arguments - - Returns - ------- - object or None - Maybe named_arg - """ - if kwargs: - return named_arg - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_check_docs_utils.py b/pymode/libs/pylint/test/extensions/test_check_docs_utils.py deleted file mode 100644 index fdc31353..00000000 --- a/pymode/libs/pylint/test/extensions/test_check_docs_utils.py +++ /dev/null @@ -1,142 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the pylint checkers in :mod:`pylint.extensions.check_docs`, -in particular the parameter documentation checker `DocstringChecker` -""" -from __future__ import division, print_function, absolute_import - -import unittest -import sys - -import astroid -from astroid import test_utils -from pylint.testutils import CheckerTestCase, Message, set_config - -import pylint.extensions._check_docs_utils as utils - - -class SpaceIndentationTest(unittest.TestCase): - """Tests for pylint_plugin.ParamDocChecker""" - - def test_space_indentation(self): - self.assertEqual(utils.space_indentation('abc'), 0) - self.assertEqual(utils.space_indentation(''), 0) - self.assertEqual(utils.space_indentation(' abc'), 2) - self.assertEqual(utils.space_indentation('\n abc'), 0) - self.assertEqual(utils.space_indentation(' \n abc'), 3) - -class PossibleExcTypesText(unittest.TestCase): - def test_exception_class(self): - raise_node = test_utils.extract_node(''' - def my_func(): - raise NotImplementedError #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["NotImplementedError"]) - self.assertEqual(found, expected) - - def test_exception_instance(self): - raise_node = test_utils.extract_node(''' - def my_func(): - raise NotImplementedError("Not implemented!") #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["NotImplementedError"]) - self.assertEqual(found, expected) - - def test_rethrow(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except RuntimeError: - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["RuntimeError"]) - self.assertEqual(found, expected) - - def test_nested_in_if_rethrow(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except RuntimeError: - if another_func(): - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["RuntimeError"]) - self.assertEqual(found, expected) - - def test_nested_in_try(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except RuntimeError: - try: - another_func() - raise #@ - except NameError: - pass - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["RuntimeError"]) - self.assertEqual(found, expected) - - def test_nested_in_try_except(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except RuntimeError: - try: - another_func() - except NameError: - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["NameError"]) - self.assertEqual(found, expected) - - def test_no_rethrow_types(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except: - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set() - self.assertEqual(found, expected) - - def test_multiple_rethrow_types(self): - raise_node = test_utils.extract_node(''' - def my_func(): - try: - fake_func() - except (RuntimeError, ValueError): - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set(["RuntimeError", "ValueError"]) - self.assertEqual(found, expected) - - def test_ignores_uninferable_type(self): - raise_node = test_utils.extract_node(''' - import not_a_module - def my_func(): - try: - fake_func() - except not_a_module.Error: - raise #@ - ''') - found = utils.possible_exc_types(raise_node) - expected = set() - self.assertEqual(found, expected) - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_check_mccabe.py b/pymode/libs/pylint/test/extensions/test_check_mccabe.py deleted file mode 100644 index 9d995891..00000000 --- a/pymode/libs/pylint/test/extensions/test_check_mccabe.py +++ /dev/null @@ -1,72 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for the pylint checker in :mod:`pylint.extensions.check_mccabe -""" - -import os.path as osp -import unittest - -from pylint import checkers -from pylint.extensions.mccabe import register -from pylint.lint import PyLinter -from pylint.reporters import BaseReporter - - -class TestReporter(BaseReporter): - - def handle_message(self, msg): - self.messages.append(msg) - - def on_set_current_module(self, module, filepath): - self.messages = [] - - -class TestMcCabeMethodChecker(unittest.TestCase): - """Test McCabe Method Checker""" - - expected_msgs = [ - "'f1' is too complex. The McCabe rating is 1", - "'f2' is too complex. The McCabe rating is 1", - "'f3' is too complex. The McCabe rating is 3", - "'f4' is too complex. The McCabe rating is 2", - "'f5' is too complex. The McCabe rating is 2", - "'f6' is too complex. The McCabe rating is 2", - "'f7' is too complex. The McCabe rating is 3", - "'f8' is too complex. The McCabe rating is 4", - "'f9' is too complex. The McCabe rating is 9", - "'method1' is too complex. The McCabe rating is 1", - "This 'for' is too complex. The McCabe rating is 4", - "'method3' is too complex. The McCabe rating is 2", - "'f10' is too complex. The McCabe rating is 11", - "'method2' is too complex. The McCabe rating is 18", - ] - - @classmethod - def setUpClass(cls): - cls._linter = PyLinter() - cls._linter.set_reporter(TestReporter()) - checkers.initialize(cls._linter) - register(cls._linter) - cls._linter.disable('all') - cls._linter.enable('too-complex') - - def setUp(self): - self.fname_mccabe_example = osp.join( - osp.dirname(osp.abspath(__file__)), 'data', 'mccabe.py') - - def test_too_complex_message(self): - self._linter.global_set_option('max-complexity', 0) - self._linter.check([self.fname_mccabe_example]) - real_msgs = [message.msg for message in self._linter.reporter.messages] - self.assertEqual(sorted(self.expected_msgs), sorted(real_msgs)) - - def test_max_mccabe_rate(self): - self._linter.global_set_option('max-complexity', 9) - self._linter.check([self.fname_mccabe_example]) - real_msgs = [message.msg for message in self._linter.reporter.messages] - self.assertEqual(sorted(self.expected_msgs[-2:]), sorted(real_msgs)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_check_raise_docs.py b/pymode/libs/pylint/test/extensions/test_check_raise_docs.py deleted file mode 100644 index 633d19b2..00000000 --- a/pymode/libs/pylint/test/extensions/test_check_raise_docs.py +++ /dev/null @@ -1,391 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the raised exception documentation checking in the -`DocstringChecker` in :mod:`pylint.extensions.check_docs` -""" -from __future__ import division, print_function, absolute_import - -import unittest - -import astroid -from astroid import test_utils -from pylint.testutils import CheckerTestCase, Message, set_config - -from pylint.extensions.docparams import DocstringParameterChecker - - -class DocstringCheckerRaiseTest(CheckerTestCase): - """Tests for pylint_plugin.RaiseDocChecker""" - CHECKER_CLASS = DocstringParameterChecker - - def test_ignores_no_docstring(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - raise RuntimeError('hi') #@ - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_ignores_unknown_style(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring.""" - raise RuntimeError('hi') - ''') - raise_node = node.body[0] - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - @set_config(accept_no_raise_doc=False) - def test_warns_unknown_style(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring.""" - raise RuntimeError('hi') - ''') - raise_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_missing_sphinx_raises(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :raises NameError: Never - """ - raise RuntimeError('hi') - raise NameError('hi') - ''') - raise_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_missing_google_raises(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises: - NameError: Never - """ - raise RuntimeError('hi') - raise NameError('hi') - ''') - raise_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_missing_numpy_raises(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises - ------ - NameError - Never - """ - raise RuntimeError('hi') - raise NameError('hi') - ''') - raise_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_all_sphinx_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :raises RuntimeError: Always - :raises NameError: Never - """ - raise RuntimeError('hi') #@ - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_find_all_google_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises: - RuntimeError: Always - NameError: Never - """ - raise RuntimeError('hi') #@ - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_find_all_numpy_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises - ------ - RuntimeError - Always - NameError - Never - """ - raise RuntimeError('hi') #@ - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_finds_rethrown_sphinx_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :raises NameError: Sometimes - """ - try: - fake_func() - except RuntimeError: - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_rethrown_google_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises: - NameError: Sometimes - """ - try: - fake_func() - except RuntimeError: - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_find_rethrown_numpy_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises - ------ - NameError - Sometimes - """ - try: - fake_func() - except RuntimeError: - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError', ))): - self.checker.visit_raise(raise_node) - - def test_finds_rethrown_sphinx_mutiple_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :raises NameError: Sometimes - """ - try: - fake_func() - except (RuntimeError, ValueError): - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError, ValueError', ))): - self.checker.visit_raise(raise_node) - - def test_find_rethrown_google_multiple_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises: - NameError: Sometimes - """ - try: - fake_func() - except (RuntimeError, ValueError): - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError, ValueError', ))): - self.checker.visit_raise(raise_node) - - def test_find_rethrown_numpy_multiple_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises - ------ - NameError - Sometimes - """ - try: - fake_func() - except (RuntimeError, ValueError): - raise #@ - - raise NameError('hi') - ''') - node = raise_node.frame() - with self.assertAddsMessages( - Message( - msg_id='missing-raises-doc', - node=node, - args=('RuntimeError, ValueError', ))): - self.checker.visit_raise(raise_node) - - def test_ignores_caught_sphinx_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :raises NameError: Sometimes - """ - try: - raise RuntimeError('hi') #@ - except RuntimeError: - pass - - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_ignores_caught_google_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises: - NameError: Sometimes - """ - try: - raise RuntimeError('hi') #@ - except RuntimeError: - pass - - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_ignores_caught_numpy_raises(self): - raise_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Raises - ------ - NameError - Sometimes - """ - try: - raise RuntimeError('hi') #@ - except RuntimeError: - pass - - raise NameError('hi') - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_no_crash_when_inferring_handlers(self): - raise_node = test_utils.extract_node(''' - import collections - - def test(): - """raises - - :raise U: pass - """ - try: - pass - except collections.U as exc: - raise #@ - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - def test_no_crash_when_cant_find_exception(self): - raise_node = test_utils.extract_node(''' - import collections - - def test(): - """raises - - :raise U: pass - """ - try: - pass - except U as exc: - raise #@ - ''') - with self.assertNoMessages(): - self.checker.visit_raise(raise_node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_check_return_docs.py b/pymode/libs/pylint/test/extensions/test_check_return_docs.py deleted file mode 100644 index bfdf3ed4..00000000 --- a/pymode/libs/pylint/test/extensions/test_check_return_docs.py +++ /dev/null @@ -1,473 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the return documentation checking in the -`DocstringChecker` in :mod:`pylint.extensions.check_docs` -""" -from __future__ import division, print_function, absolute_import - -import unittest - -import astroid -from astroid import test_utils -from pylint.testutils import CheckerTestCase, Message, set_config - -from pylint.extensions.docparams import DocstringParameterChecker - - -class DocstringCheckerReturnTest(CheckerTestCase): - """Tests for pylint_plugin.RaiseDocChecker""" - CHECKER_CLASS = DocstringParameterChecker - - def test_ignores_no_docstring(self): - return_node = test_utils.extract_node(''' - def my_func(self): - return False #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - @set_config(accept_no_return_doc=False) - def test_warns_no_docstring(self): - node = test_utils.extract_node(''' - def my_func(self): - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_ignores_unknown_style(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring.""" - return False #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_warn_partial_sphinx_returns(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :returns: Always False - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warn_partial_sphinx_returns_type(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :rtype: bool - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warn_missing_sphinx_returns(self): - node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - :param doc_type: Sphinx - :type doc_type: str - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warn_partial_google_returns(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - Always False - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warn_missing_google_returns(self): - node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - Parameters: - doc_type (str): Google - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warn_missing_numpy_returns(self): - node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - Arguments - --------- - doc_type : str - Numpy - """ - return False - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_find_sphinx_returns(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :return: Always False - :rtype: bool - """ - return False #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_find_google_returns(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - bool: Always False - """ - return False #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_find_numpy_returns(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - bool - Always False - """ - return False #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_ignores_sphinx_return_none(self): - return_node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - :param doc_type: Sphinx - :type doc_type: str - """ - return #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_ignores_google_return_none(self): - return_node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - Args: - doc_type (str): Google - """ - return #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_ignores_numpy_return_none(self): - return_node = test_utils.extract_node(''' - def my_func(self, doc_type): - """This is a docstring. - - Arguments - --------- - doc_type : str - Numpy - """ - return #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_sphinx_return_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :returns: An object - :rtype: :class:`mymodule.Class` - """ - return mymodule.Class() #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_google_return_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - mymodule.Class: An object - """ - return mymodule.Class() #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_numpy_return_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - mymodule.Class - An object - """ - return mymodule.Class() #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_sphinx_return_list_of_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :returns: An object - :rtype: list(:class:`mymodule.Class`) - """ - return [mymodule.Class()] #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_google_return_list_of_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - list(:class:`mymodule.Class`): An object - """ - return [mymodule.Class()] #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_finds_numpy_return_list_of_custom_class(self): - return_node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - list(:class:`mymodule.Class`) - An object - """ - return [mymodule.Class()] #@ - ''') - with self.assertNoMessages(): - self.checker.visit_return(return_node) - - def test_warns_sphinx_return_list_of_custom_class_without_description(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :rtype: list(:class:`mymodule.Class`) - """ - return [mymodule.Class()] - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warns_google_return_list_of_custom_class_without_description(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - list(:class:`mymodule.Class`) - """ - return [mymodule.Class()] - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warns_numpy_return_list_of_custom_class_without_description(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - list(:class:`mymodule.Class`) - """ - return [mymodule.Class()] - ''') - return_node = node.body[0] - with self.assertAddsMessages( - Message( - msg_id='missing-returns-doc', - node=node)): - self.checker.visit_return(return_node) - - def test_warns_sphinx_redundant_return_doc(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :returns: One - :rtype: int - """ - return None - ''') - with self.assertAddsMessages( - Message( - msg_id='redundant-returns-doc', - node=node)): - self.checker.visit_functiondef(node) - - def test_warns_google_redundant_return_doc(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - int: One - """ - return None - ''') - with self.assertAddsMessages( - Message( - msg_id='redundant-returns-doc', - node=node)): - self.checker.visit_functiondef(node) - - def test_warns_numpy_redundant_return_doc(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - int - One - """ - return None - ''') - with self.assertAddsMessages( - Message( - msg_id='redundant-returns-doc', - node=node)): - self.checker.visit_functiondef(node) - - def test_ignores_sphinx_redundant_return_doc_multiple_returns(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - :returns: One - :rtype: int - - :returns: None sometimes - :rtype: None - """ - if a_func(): - return None - return 1 - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_ignores_google_redundant_return_doc_multiple_returns(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns: - int or None: One, or sometimes None. - """ - if a_func(): - return None - return 1 - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_ignores_numpy_redundant_return_doc_multiple_returns(self): - node = test_utils.extract_node(''' - def my_func(self): - """This is a docstring. - - Returns - ------- - int - One - None - Sometimes - """ - if a_func(): - return None - return 1 - ''') - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_docstyle.py b/pymode/libs/pylint/test/extensions/test_docstyle.py deleted file mode 100644 index 384616b6..00000000 --- a/pymode/libs/pylint/test/extensions/test_docstyle.py +++ /dev/null @@ -1,67 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for the pylint checker in :mod:`pylint.extensions.check_docstring -""" - -import os.path as osp -import unittest - -from pylint import checkers -from pylint.extensions.docstyle import DocStringStyleChecker -from pylint.lint import PyLinter -from pylint.reporters import BaseReporter - - -class TestReporter(BaseReporter): - - def handle_message(self, msg): - self.messages.append(msg) - - def on_set_current_module(self, module, filepath): - self.messages = [] - - -class CheckDocStringStyleTest(unittest.TestCase): - - expected_msg = [ - 'First line empty in function docstring', - 'First line empty in class docstring', - 'First line empty in method docstring', - 'Bad docstring quotes in method, expected """, given \'\'\'', - 'Bad docstring quotes in method, expected """, given "', - 'Bad docstring quotes in method, expected """, given \'', - 'Bad docstring quotes in method, expected """, given \'', - ] - expected_symbol = [ - 'docstring-first-line-empty', - 'docstring-first-line-empty', - 'docstring-first-line-empty', - 'bad-docstring-quotes', - 'bad-docstring-quotes', - 'bad-docstring-quotes', - 'bad-docstring-quotes', - ] - - @classmethod - def setUpClass(cls): - cls._linter = PyLinter() - cls._linter.set_reporter(TestReporter()) - checkers.initialize(cls._linter) - cls._linter.register_checker(DocStringStyleChecker(cls._linter)) - - def test_docstring_message(self): - docstring_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data', - 'docstring.py') - self._linter.check([docstring_test]) - msgs = self._linter.reporter.messages - self.assertEqual(len(msgs), 7) - for msg, expected_symbol, expected_msg in zip(msgs, - self.expected_symbol, - self.expected_msg): - self.assertEqual(msg.symbol, expected_symbol) - self.assertEqual(msg.msg, expected_msg) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/extensions/test_elseif_used.py b/pymode/libs/pylint/test/extensions/test_elseif_used.py deleted file mode 100644 index f49049f1..00000000 --- a/pymode/libs/pylint/test/extensions/test_elseif_used.py +++ /dev/null @@ -1,50 +0,0 @@ -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for the pylint checker in :mod:`pylint.extensions.check_elif -""" - -import os -import os.path as osp -import unittest - -from pylint import checkers -from pylint.extensions.check_elif import ElseifUsedChecker -from pylint.lint import PyLinter -from pylint.reporters import BaseReporter - - -class TestReporter(BaseReporter): - - def handle_message(self, msg): - self.messages.append(msg) - - def on_set_current_module(self, module, filepath): - self.messages = [] - - -class CheckElseIfUsedTC(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls._linter = PyLinter() - cls._linter.set_reporter(TestReporter()) - checkers.initialize(cls._linter) - cls._linter.register_checker(ElseifUsedChecker(cls._linter)) - - def test_elseif_message(self): - elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data', - 'elif.py') - self._linter.check([elif_test]) - msgs = self._linter.reporter.messages - self.assertEqual(len(msgs), 2) - for msg in msgs: - self.assertEqual(msg.symbol, 'else-if-used') - self.assertEqual(msg.msg, - 'Consider using "elif" instead of "else if"') - self.assertEqual(msgs[0].line, 9) - self.assertEqual(msgs[1].line, 21) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/functional/__init__.py b/pymode/libs/pylint/test/functional/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/functional/abstract_abc_methods.py b/pymode/libs/pylint/test/functional/abstract_abc_methods.py deleted file mode 100644 index 0ba52950..00000000 --- a/pymode/libs/pylint/test/functional/abstract_abc_methods.py +++ /dev/null @@ -1,17 +0,0 @@ -""" This should not warn about `prop` being abstract in Child """ -# pylint: disable=too-few-public-methods, no-absolute-import,metaclass-assignment - -import abc - -class Parent(object): - """Abstract Base Class """ - __metaclass__ = abc.ABCMeta - - @property - @abc.abstractmethod - def prop(self): - """ Abstract """ - -class Child(Parent): - """ No warning for the following. """ - prop = property(lambda self: 1) diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_in_class.py b/pymode/libs/pylint/test/functional/abstract_class_instantiated_in_class.py deleted file mode 100644 index 02604451..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_in_class.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Don't warn if the class is instantiated in its own body.""" -# pylint: disable=missing-docstring - - -import abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class Ala(object): - - @abc.abstractmethod - def bala(self): - pass - - @classmethod - def portocala(cls): - instance = cls() - return instance diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.py b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.py deleted file mode 100644 index 58c74e16..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.py +++ /dev/null @@ -1,82 +0,0 @@ -"""Check that instantiating a class with -`abc.ABCMeta` as metaclass fails if it defines -abstract methods. -""" - -# pylint: disable=too-few-public-methods, missing-docstring -# pylint: disable=no-absolute-import, metaclass-assignment -# pylint: disable=abstract-method, import-error, wildcard-import - -import abc -from abc import ABCMeta -from lala import Bala - - -class GoodClass(object): - __metaclass__ = abc.ABCMeta - -class SecondGoodClass(object): - __metaclass__ = abc.ABCMeta - - def test(self): - """ do nothing. """ - -class ThirdGoodClass(object): - __metaclass__ = abc.ABCMeta - - def test(self): - raise NotImplementedError() - -class FourthGoodClass(object): - __metaclass__ = ABCMeta - -class BadClass(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def test(self): - """ do nothing. """ - -class SecondBadClass(object): - __metaclass__ = abc.ABCMeta - - @property - @abc.abstractmethod - def test(self): - """ do nothing. """ - -class ThirdBadClass(object): - __metaclass__ = ABCMeta - - @abc.abstractmethod - def test(self): - pass - -class FourthBadClass(ThirdBadClass): - pass - - -class SomeMetaclass(object): - __metaclass__ = ABCMeta - - @abc.abstractmethod - def prop(self): - pass - -class FifthGoodClass(SomeMetaclass): - """Don't consider this abstract if some attributes are - there, but can't be inferred. - """ - prop = Bala # missing - - -def main(): - """ do nothing """ - GoodClass() - SecondGoodClass() - ThirdGoodClass() - FourthGoodClass() - BadClass() # [abstract-class-instantiated] - SecondBadClass() # [abstract-class-instantiated] - ThirdBadClass() # [abstract-class-instantiated] - FourthBadClass() # [abstract-class-instantiated] diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.rc b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.rc deleted file mode 100644 index b11e16d5..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.txt b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.txt deleted file mode 100644 index 8ab4b55b..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py2.txt +++ /dev/null @@ -1,4 +0,0 @@ -abstract-class-instantiated:79:main:Abstract class 'BadClass' with abstract methods instantiated -abstract-class-instantiated:80:main:Abstract class 'SecondBadClass' with abstract methods instantiated -abstract-class-instantiated:81:main:Abstract class 'ThirdBadClass' with abstract methods instantiated -abstract-class-instantiated:82:main:Abstract class 'FourthBadClass' with abstract methods instantiated diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.py b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.py deleted file mode 100644 index f3731899..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Check that instantiating a class with -`abc.ABCMeta` as metaclass fails if it defines -abstract methods. -""" - -# pylint: disable=too-few-public-methods, missing-docstring -# pylint: disable=abstract-method, import-error - -import abc -import weakref -from lala import Bala - - -class GoodClass(object, metaclass=abc.ABCMeta): - pass - -class SecondGoodClass(object, metaclass=abc.ABCMeta): - def test(self): - """ do nothing. """ - -class ThirdGoodClass(object, metaclass=abc.ABCMeta): - """ This should not raise the warning. """ - def test(self): - raise NotImplementedError() - -class BadClass(object, metaclass=abc.ABCMeta): - @abc.abstractmethod - def test(self): - """ do nothing. """ - -class SecondBadClass(object, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def test(self): - """ do nothing. """ - -class ThirdBadClass(SecondBadClass): - pass - - -class Structure(object, metaclass=abc.ABCMeta): - @abc.abstractmethod - def __iter__(self): - pass - @abc.abstractmethod - def __len__(self): - pass - @abc.abstractmethod - def __contains__(self, _): - pass - @abc.abstractmethod - def __hash__(self): - pass - -class Container(Structure): - def __contains__(self, _): - pass - -class Sizable(Structure): - def __len__(self): - pass - -class Hashable(Structure): - __hash__ = 42 - - -class Iterator(Structure): - def keys(self): # pylint: disable=no-self-use - return iter([1, 2, 3]) - - __iter__ = keys - -class AbstractSizable(Structure): - @abc.abstractmethod - def length(self): - pass - __len__ = length - -class NoMroAbstractMethods(Container, Iterator, Sizable, Hashable): - pass - -class BadMroAbstractMethods(Container, Iterator, AbstractSizable): - pass - -class SomeMetaclass(metaclass=abc.ABCMeta): - - @abc.abstractmethod - def prop(self): - pass - -class FourthGoodClass(SomeMetaclass): - """Don't consider this abstract if some attributes are - there, but can't be inferred. - """ - prop = Bala # missing - - -def main(): - """ do nothing """ - GoodClass() - SecondGoodClass() - ThirdGoodClass() - FourthGoodClass() - weakref.WeakKeyDictionary() - weakref.WeakValueDictionary() - NoMroAbstractMethods() - - BadMroAbstractMethods() # [abstract-class-instantiated] - BadClass() # [abstract-class-instantiated] - SecondBadClass() # [abstract-class-instantiated] - ThirdBadClass() # [abstract-class-instantiated] diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.rc b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.txt b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.txt deleted file mode 100644 index 4cae7d98..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py3.txt +++ /dev/null @@ -1,4 +0,0 @@ -abstract-class-instantiated:108:main:Abstract class 'BadMroAbstractMethods' with abstract methods instantiated -abstract-class-instantiated:109:main:Abstract class 'BadClass' with abstract methods instantiated -abstract-class-instantiated:110:main:Abstract class 'SecondBadClass' with abstract methods instantiated -abstract-class-instantiated:111:main:Abstract class 'ThirdBadClass' with abstract methods instantiated diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.py b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.py deleted file mode 100644 index c22be369..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Check that instantiating a class with `abc.ABCMeta` as ancestor fails if it -defines abstract methods. -""" - -# pylint: disable=too-few-public-methods, missing-docstring, no-init - -import abc - - - -class BadClass(abc.ABC): - @abc.abstractmethod - def test(self): - pass - -def main(): - """ do nothing """ - BadClass() # [abstract-class-instantiated] diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.rc b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.rc deleted file mode 100644 index 1fb7b871..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.4 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.txt b/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.txt deleted file mode 100644 index 14ffda4a..00000000 --- a/pymode/libs/pylint/test/functional/abstract_class_instantiated_py34.txt +++ /dev/null @@ -1 +0,0 @@ -abstract-class-instantiated:19:main:Abstract class 'BadClass' with abstract methods instantiated diff --git a/pymode/libs/pylint/test/functional/abstract_method_py2.py b/pymode/libs/pylint/test/functional/abstract_method_py2.py deleted file mode 100644 index 7238d442..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py2.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Test abstract-method warning.""" -from __future__ import print_function - -# pylint: disable=missing-docstring, no-init, no-self-use -# pylint: disable=too-few-public-methods -import abc - -class Abstract(object): - def aaaa(self): - """should be overridden in concrete class""" - raise NotImplementedError() - - def bbbb(self): - """should be overridden in concrete class""" - raise NotImplementedError() - - -class AbstractB(Abstract): - """Abstract class. - - this class is checking that it does not output an error msg for - unimplemeted methods in abstract classes - """ - def cccc(self): - """should be overridden in concrete class""" - raise NotImplementedError() - -class Concret(Abstract): # [abstract-method] - """Concrete class""" - - def aaaa(self): - """overidden form Abstract""" - - -class Structure(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def __iter__(self): - pass - @abc.abstractmethod - def __len__(self): - pass - @abc.abstractmethod - def __contains__(self, _): - pass - @abc.abstractmethod - def __hash__(self): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Container(Structure): - def __contains__(self, _): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Sizable(Structure): - def __len__(self): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Hashable(Structure): - __hash__ = 42 - - -# +1: [abstract-method, abstract-method, abstract-method] -class Iterator(Structure): - def keys(self): - return iter([1, 2, 3]) - - __iter__ = keys - - -class AbstractSizable(Structure): - @abc.abstractmethod - def length(self): - pass - __len__ = length - - -class GoodComplexMRO(Container, Iterator, Sizable, Hashable): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class BadComplexMro(Container, Iterator, AbstractSizable): - pass diff --git a/pymode/libs/pylint/test/functional/abstract_method_py2.rc b/pymode/libs/pylint/test/functional/abstract_method_py2.rc deleted file mode 100644 index b11e16d5..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py2.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/abstract_method_py2.txt b/pymode/libs/pylint/test/functional/abstract_method_py2.txt deleted file mode 100644 index 73300124..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py2.txt +++ /dev/null @@ -1,16 +0,0 @@ -abstract-method:28:Concret:"Method 'bbbb' is abstract in class 'Abstract' but is not overridden" -abstract-method:53:Container:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:53:Container:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:53:Container:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:59:Sizable:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:59:Sizable:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:59:Sizable:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:65:Hashable:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:65:Hashable:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:65:Hashable:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:70:Iterator:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:70:Iterator:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:70:Iterator:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:89:BadComplexMro:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:89:BadComplexMro:"Method '__len__' is abstract in class 'AbstractSizable' but is not overridden" -abstract-method:89:BadComplexMro:"Method 'length' is abstract in class 'AbstractSizable' but is not overridden" diff --git a/pymode/libs/pylint/test/functional/abstract_method_py3.py b/pymode/libs/pylint/test/functional/abstract_method_py3.py deleted file mode 100644 index daacf65c..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py3.py +++ /dev/null @@ -1,88 +0,0 @@ -"""Test abstract-method warning.""" -from __future__ import print_function - -# pylint: disable=missing-docstring, no-init, no-self-use -# pylint: disable=too-few-public-methods -import abc - -class Abstract(object): - def aaaa(self): - """should be overridden in concrete class""" - raise NotImplementedError() - - def bbbb(self): - """should be overridden in concrete class""" - raise NotImplementedError() - - -class AbstractB(Abstract): - """Abstract class. - - this class is checking that it does not output an error msg for - unimplemeted methods in abstract classes - """ - def cccc(self): - """should be overridden in concrete class""" - raise NotImplementedError() - -class Concret(Abstract): # [abstract-method] - """Concrete class""" - - def aaaa(self): - """overidden form Abstract""" - - -class Structure(object, metaclass=abc.ABCMeta): - @abc.abstractmethod - def __iter__(self): - pass - @abc.abstractmethod - def __len__(self): - pass - @abc.abstractmethod - def __contains__(self, _): - pass - @abc.abstractmethod - def __hash__(self): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Container(Structure): - def __contains__(self, _): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Sizable(Structure): - def __len__(self): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class Hashable(Structure): - __hash__ = 42 - - -# +1: [abstract-method, abstract-method, abstract-method] -class Iterator(Structure): - def keys(self): - return iter([1, 2, 3]) - - __iter__ = keys - - -class AbstractSizable(Structure): - @abc.abstractmethod - def length(self): - pass - __len__ = length - - -class GoodComplexMRO(Container, Iterator, Sizable, Hashable): - pass - - -# +1: [abstract-method, abstract-method, abstract-method] -class BadComplexMro(Container, Iterator, AbstractSizable): - pass diff --git a/pymode/libs/pylint/test/functional/abstract_method_py3.rc b/pymode/libs/pylint/test/functional/abstract_method_py3.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/abstract_method_py3.txt b/pymode/libs/pylint/test/functional/abstract_method_py3.txt deleted file mode 100644 index 7ef8c942..00000000 --- a/pymode/libs/pylint/test/functional/abstract_method_py3.txt +++ /dev/null @@ -1,16 +0,0 @@ -abstract-method:28:Concret:"Method 'bbbb' is abstract in class 'Abstract' but is not overridden" -abstract-method:51:Container:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:51:Container:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:51:Container:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:57:Sizable:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:57:Sizable:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:57:Sizable:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:63:Hashable:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:63:Hashable:"Method '__iter__' is abstract in class 'Structure' but is not overridden" -abstract-method:63:Hashable:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:68:Iterator:"Method '__contains__' is abstract in class 'Structure' but is not overridden" -abstract-method:68:Iterator:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:68:Iterator:"Method '__len__' is abstract in class 'Structure' but is not overridden" -abstract-method:87:BadComplexMro:"Method '__hash__' is abstract in class 'Structure' but is not overridden" -abstract-method:87:BadComplexMro:"Method '__len__' is abstract in class 'AbstractSizable' but is not overridden" -abstract-method:87:BadComplexMro:"Method 'length' is abstract in class 'AbstractSizable' but is not overridden" diff --git a/pymode/libs/pylint/test/functional/access_member_before_definition.py b/pymode/libs/pylint/test/functional/access_member_before_definition.py deleted file mode 100644 index 53294fbc..00000000 --- a/pymode/libs/pylint/test/functional/access_member_before_definition.py +++ /dev/null @@ -1,40 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods,invalid-name -# pylint: disable=attribute-defined-outside-init - -class Aaaa(object): - """class with attributes defined in wrong order""" - - def __init__(self): - var1 = self._var2 # [access-member-before-definition] - self._var2 = 3 - self._var3 = var1 - - -class Bbbb(object): - A = 23 - B = A - - def __getattr__(self, attr): - try: - return self.__repo - except AttributeError: - self.__repo = attr - return attr - - - def catchme(self, attr): - """no AttributeError catched""" - try: - return self._repo # [access-member-before-definition] - except ValueError: - self._repo = attr - return attr - - -class Mixin(object): - - def test_mixin(self): - """Don't emit access-member-before-definition for mixin classes.""" - if self.already_defined: - # pylint: disable=attribute-defined-outside-init - self.already_defined = None diff --git a/pymode/libs/pylint/test/functional/access_member_before_definition.txt b/pymode/libs/pylint/test/functional/access_member_before_definition.txt deleted file mode 100644 index 81860445..00000000 --- a/pymode/libs/pylint/test/functional/access_member_before_definition.txt +++ /dev/null @@ -1,2 +0,0 @@ -access-member-before-definition:8:Aaaa.__init__:Access to member '_var2' before its definition line 9 -access-member-before-definition:28:Bbbb.catchme:Access to member '_repo' before its definition line 30 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/access_to__name__.py b/pymode/libs/pylint/test/functional/access_to__name__.py deleted file mode 100644 index 6f5a39ec..00000000 --- a/pymode/libs/pylint/test/functional/access_to__name__.py +++ /dev/null @@ -1,21 +0,0 @@ -# pylint: disable=too-few-public-methods, print-statement -"""test access to __name__ gives undefined member on new/old class instances -but not on new/old class object -""" -from __future__ import print_function - -class Aaaa: # <3.0:[old-style-class] - """old class""" - def __init__(self): - print(self.__name__) # [no-member] - print(self.__class__.__name__) - -class NewClass(object): - """new class""" - - def __new__(cls, *args, **kwargs): - print('new', cls.__name__) - return object.__new__(cls, *args, **kwargs) - - def __init__(self): - print('init', self.__name__) # [no-member] diff --git a/pymode/libs/pylint/test/functional/access_to__name__.txt b/pymode/libs/pylint/test/functional/access_to__name__.txt deleted file mode 100644 index ecf5ffd6..00000000 --- a/pymode/libs/pylint/test/functional/access_to__name__.txt +++ /dev/null @@ -1,3 +0,0 @@ -old-style-class:7:Aaaa:Old-style class defined. -no-member:10:Aaaa.__init__:Instance of 'Aaaa' has no '__name__' member:INFERENCE -no-member:21:NewClass.__init__:Instance of 'NewClass' has no '__name__' member:INFERENCE diff --git a/pymode/libs/pylint/test/functional/access_to_protected_members.py b/pymode/libs/pylint/test/functional/access_to_protected_members.py deleted file mode 100644 index fd96bafe..00000000 --- a/pymode/libs/pylint/test/functional/access_to_protected_members.py +++ /dev/null @@ -1,44 +0,0 @@ -# pylint: disable=too-few-public-methods, W0231, print-statement -# pylint: disable=no-classmethod-decorator -"""Test external access to protected class members.""" -from __future__ import print_function - -class MyClass(object): - """Class with protected members.""" - _cls_protected = 5 - - def __init__(self, other): - MyClass._cls_protected = 6 - self._protected = 1 - self.public = other - self.attr = 0 - - def test(self): - """Docstring.""" - self._protected += self._cls_protected - print(self.public._haha) # [protected-access] - - def clsmeth(cls): - """Docstring.""" - cls._cls_protected += 1 - print(cls._cls_protected) - clsmeth = classmethod(clsmeth) - - def _private_method(self): - """Doing nothing.""" - - -class Subclass(MyClass): - """Subclass with protected members.""" - - def __init__(self): - MyClass._protected = 5 - super(Subclass, self)._private_method() - -INST = Subclass() -INST.attr = 1 -print(INST.attr) -INST._protected = 2 # [protected-access] -print(INST._protected) # [protected-access] -INST._cls_protected = 3 # [protected-access] -print(INST._cls_protected) # [protected-access] diff --git a/pymode/libs/pylint/test/functional/access_to_protected_members.txt b/pymode/libs/pylint/test/functional/access_to_protected_members.txt deleted file mode 100644 index 7ba601b7..00000000 --- a/pymode/libs/pylint/test/functional/access_to_protected_members.txt +++ /dev/null @@ -1,5 +0,0 @@ -protected-access:19:MyClass.test:Access to a protected member _haha of a client class -protected-access:41::Access to a protected member _protected of a client class -protected-access:42::Access to a protected member _protected of a client class -protected-access:43::Access to a protected member _cls_protected of a client class -protected-access:44::Access to a protected member _cls_protected of a client class diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.py b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.py deleted file mode 100644 index 8f304fa4..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.py +++ /dev/null @@ -1,20 +0,0 @@ -# pylint:disable=W0105, W0511 -"""Test for backslash escapes in byte vs unicode strings""" - -# Would be valid in Unicode, but probably not what you want otherwise -BAD_UNICODE = b'\u0042' # [anomalous-unicode-escape-in-string] -BAD_LONG_UNICODE = b'\U00000042' # [anomalous-unicode-escape-in-string] -# +1:[anomalous-unicode-escape-in-string] -BAD_NAMED_UNICODE = b'\N{GREEK SMALL LETTER ALPHA}' - -GOOD_UNICODE = u'\u0042' -GOOD_LONG_UNICODE = u'\U00000042' -GOOD_NAMED_UNICODE = u'\N{GREEK SMALL LETTER ALPHA}' - - -# Valid raw strings -RAW_BACKSLASHES = r'raw' -RAW_UNICODE = ur"\u0062\n" - -# In a comment you can have whatever you want: \ \\ \n \m -# even things that look like bad strings: "C:\Program Files" diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.rc b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.rc deleted file mode 100644 index b11e16d5..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.txt b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.txt deleted file mode 100644 index c242cb98..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py2.txt +++ /dev/null @@ -1,3 +0,0 @@ -anomalous-unicode-escape-in-string:5::"Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix." -anomalous-unicode-escape-in-string:6::"Anomalous Unicode escape in byte string: '\U'. String constant might be missing an r or u prefix." -anomalous-unicode-escape-in-string:8::"Anomalous Unicode escape in byte string: '\N'. String constant might be missing an r or u prefix." diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.py b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.py deleted file mode 100644 index b8bfd0a9..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint:disable=W0105, W0511 -"""Test for backslash escapes in byte vs unicode strings""" - -# Would be valid in Unicode, but probably not what you want otherwise -BAD_UNICODE = b'\u0042' # [anomalous-unicode-escape-in-string] -BAD_LONG_UNICODE = b'\U00000042' # [anomalous-unicode-escape-in-string] -# +1:[anomalous-unicode-escape-in-string] -BAD_NAMED_UNICODE = b'\N{GREEK SMALL LETTER ALPHA}' - -GOOD_UNICODE = u'\u0042' -GOOD_LONG_UNICODE = u'\U00000042' -GOOD_NAMED_UNICODE = u'\N{GREEK SMALL LETTER ALPHA}' - - -# Valid raw strings -RAW_BACKSLASHES = r'raw' - -# In a comment you can have whatever you want: \ \\ \n \m -# even things that look like bad strings: "C:\Program Files" diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.rc b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.txt b/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.txt deleted file mode 100644 index d2c5d10e..00000000 --- a/pymode/libs/pylint/test/functional/anomalous_unicode_escape_py3.txt +++ /dev/null @@ -1,3 +0,0 @@ -anomalous-unicode-escape-in-string:5::"Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix." -anomalous-unicode-escape-in-string:6::"Anomalous Unicode escape in byte string: '\U'. String constant might be missing an r or u prefix." -anomalous-unicode-escape-in-string:8::"Anomalous Unicode escape in byte string: '\N'. String constant might be missing an r or u prefix." \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/arguments.py b/pymode/libs/pylint/test/functional/arguments.py deleted file mode 100644 index 037a3f93..00000000 --- a/pymode/libs/pylint/test/functional/arguments.py +++ /dev/null @@ -1,167 +0,0 @@ -# pylint: disable=too-few-public-methods, no-absolute-import,missing-docstring,import-error,wrong-import-position -"""Test function argument checker""" - -def decorator(fun): - """Decorator""" - return fun - - -class DemoClass(object): - """Test class for method invocations.""" - - @staticmethod - def static_method(arg): - """static method.""" - return arg + arg - - @classmethod - def class_method(cls, arg): - """class method""" - return arg + arg - - def method(self, arg): - """method.""" - return (self, arg) - - @decorator - def decorated_method(self, arg): - """decorated method.""" - return (self, arg) - - -def function_1_arg(first_argument): - """one argument function""" - return first_argument - -def function_3_args(first_argument, second_argument, third_argument): - """three arguments function""" - return first_argument, second_argument, third_argument - -def function_default_arg(one=1, two=2): - """fonction with default value""" - return two, one - - -function_1_arg(420) -function_1_arg() # [no-value-for-parameter] -function_1_arg(1337, 347) # [too-many-function-args] - -function_3_args(420, 789) # [no-value-for-parameter] -# +1:[no-value-for-parameter,no-value-for-parameter,no-value-for-parameter] -function_3_args() -function_3_args(1337, 347, 456) -function_3_args('bab', 'bebe', None, 5.6) # [too-many-function-args] - -function_default_arg(1, two=5) -function_default_arg(two=5) - -function_1_arg(bob=4) # [unexpected-keyword-arg,no-value-for-parameter] -function_default_arg(1, 4, coin="hello") # [unexpected-keyword-arg] - -function_default_arg(1, one=5) # [redundant-keyword-arg] - -# Remaining tests are for coverage of correct names in messages. -LAMBDA = lambda arg: 1 - -LAMBDA() # [no-value-for-parameter] - -def method_tests(): - """Method invocations.""" - demo = DemoClass() - demo.static_method() # [no-value-for-parameter] - DemoClass.static_method() # [no-value-for-parameter] - - demo.class_method() # [no-value-for-parameter] - DemoClass.class_method() # [no-value-for-parameter] - - demo.method() # [no-value-for-parameter] - DemoClass.method(demo) # [no-value-for-parameter] - - demo.decorated_method() # [no-value-for-parameter] - DemoClass.decorated_method(demo) # [no-value-for-parameter] - -# Test a regression (issue #234) -import sys - -class Text(object): - """ Regression """ - - if sys.version_info > (3,): - def __new__(cls): - """ empty """ - return object.__new__(cls) - else: - def __new__(cls): - """ empty """ - return object.__new__(cls) - -Text() - -class TestStaticMethod(object): - - @staticmethod - def test(first, second=None, **kwargs): - return first, second, kwargs - - def func(self): - self.test(42) - self.test(42, second=34) - self.test(42, 42) - self.test() # [no-value-for-parameter] - self.test(42, 42, 42) # [too-many-function-args] - -# Should be enabled on a more capable astroid (> 1.4.0) -# class TypeCheckConstructor(object): -# def __init__(self, first, second): -# self.first = first -# self.second = second -# def test(self): -# type(self)(1, 2, 3) -# # -# type(self)() -# type(self)(1, lala=2) -# type(self)(1, 2) -# type(self)(first=1, second=2) - - -class Test(object): - """ lambda needs Test instance as first argument """ - lam = lambda self, icon: (self, icon) - - def test(self): - self.lam(42) - self.lam() # [no-value-for-parameter] - self.lam(1, 2, 3) # [too-many-function-args] - -Test().lam() # [no-value-for-parameter] - -# Don't emit a redundant-keyword-arg for this example, -# it's perfectly valid - -class Issue642(object): - attr = 0 - def __str__(self): - return "{self.attr}".format(self=self) - -# These should not emit anything regarding the number of arguments, -# since they have something invalid. -from ala_bala_portocola import unknown - -# pylint: disable=not-a-mapping,not-an-iterable - -function_1_arg(*unknown) -function_1_arg(1, *2) -function_1_arg(1, 2, 3, **unknown) -function_1_arg(4, 5, **1) -function_1_arg(5, 6, **{unknown: 1}) -function_1_arg(**{object: 1}) -function_1_arg(**{1: 2}) - -# Don't emit no-value-for-parameter for this, since we -# don't have the context at our disposal. -def expect_three(one, two, three): - return one + two + three - - -def no_context(*args): - expect_three(*args) diff --git a/pymode/libs/pylint/test/functional/arguments.txt b/pymode/libs/pylint/test/functional/arguments.txt deleted file mode 100644 index c34f2051..00000000 --- a/pymode/libs/pylint/test/functional/arguments.txt +++ /dev/null @@ -1,26 +0,0 @@ -no-value-for-parameter:46::No value for argument 'first_argument' in function call -too-many-function-args:47::Too many positional arguments for function call -no-value-for-parameter:49::No value for argument 'third_argument' in function call -no-value-for-parameter:51::No value for argument 'first_argument' in function call -no-value-for-parameter:51::No value for argument 'second_argument' in function call -no-value-for-parameter:51::No value for argument 'third_argument' in function call -too-many-function-args:53::Too many positional arguments for function call -no-value-for-parameter:58::No value for argument 'first_argument' in function call -unexpected-keyword-arg:58::Unexpected keyword argument 'bob' in function call -unexpected-keyword-arg:59::Unexpected keyword argument 'coin' in function call -redundant-keyword-arg:61::Argument 'one' passed by position and keyword in function call -no-value-for-parameter:66::No value for argument 'arg' in lambda call -no-value-for-parameter:71:method_tests:No value for argument 'arg' in staticmethod call -no-value-for-parameter:72:method_tests:No value for argument 'arg' in staticmethod call -no-value-for-parameter:74:method_tests:No value for argument 'arg' in classmethod call -no-value-for-parameter:75:method_tests:No value for argument 'arg' in classmethod call -no-value-for-parameter:77:method_tests:No value for argument 'arg' in method call -no-value-for-parameter:78:method_tests:No value for argument 'arg' in unbound method call -no-value-for-parameter:80:method_tests:No value for argument 'arg' in method call -no-value-for-parameter:81:method_tests:No value for argument 'arg' in unbound method call -no-value-for-parameter:110:TestStaticMethod.func:No value for argument 'first' in staticmethod call -too-many-function-args:111:TestStaticMethod.func:Too many positional arguments for staticmethod call -unexpected-keyword-arg:122:TypeCheckConstructor.test:Unexpected keyword argument 'lala' in constructor call -no-value-for-parameter:133:Test.test:No value for argument 'icon' in function call -too-many-function-args:134:Test.test:Too many positional arguments for function call -no-value-for-parameter:136::No value for argument 'icon' in function call \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/arguments_differ.py b/pymode/libs/pylint/test/functional/arguments_differ.py deleted file mode 100644 index 2ddd0838..00000000 --- a/pymode/libs/pylint/test/functional/arguments_differ.py +++ /dev/null @@ -1,138 +0,0 @@ -"""Test that we are emitting arguments-differ when the arguments are different.""" -# pylint: disable=missing-docstring, too-few-public-methods - -class Parent(object): - - def test(self): - pass - - -class Child(Parent): - - def test(self, arg): # [arguments-differ] - pass - - -class ParentDefaults(object): - - def test(self, arg=None, barg=None): - pass - -class ChildDefaults(ParentDefaults): - - def test(self, arg=None): # [arguments-differ] - pass - - -class Classmethod(object): - - @classmethod - def func(cls, data): - return data - - @classmethod - def func1(cls): - return cls - - -class ClassmethodChild(Classmethod): - - @staticmethod - def func(): # [arguments-differ] - pass - - @classmethod - def func1(cls): - return cls() - - -class Builtins(dict): - """Ignore for builtins, for which we don't know the number of required args.""" - - @classmethod - def fromkeys(cls, arg, arg1): - pass - - -class Varargs(object): - - def test(self, arg, **kwargs): - pass - -class VarargsChild(Varargs): - - def test(self, arg): - pass - - -class Super(object): - def __init__(self): - pass - - def __private(self): - pass - - def __private2_(self): - pass - - def ___private3(self): - pass - - def method(self, param): - raise NotImplementedError - - -class Sub(Super): - - # pylint: disable=unused-argument - def __init__(self, arg): - super(Sub, self).__init__() - - def __private(self, arg): - pass - - def __private2_(self, arg): - pass - - def ___private3(self, arg): - pass - - def method(self, param='abc'): - pass - - -class Staticmethod(object): - - @staticmethod - def func(data): - return data - - -class StaticmethodChild(Staticmethod): - - @classmethod - def func(cls, data): - return data - - -class Property(object): - - @property - def close(self): - pass - -class PropertySetter(Property): - - @property - def close(self): - pass - - @close.setter - def close(self, attr): - return attr - - -class StaticmethodChild2(Staticmethod): - - def func(self, arg): - super(StaticmethodChild2, self).func(arg) diff --git a/pymode/libs/pylint/test/functional/arguments_differ.txt b/pymode/libs/pylint/test/functional/arguments_differ.txt deleted file mode 100644 index 51996e46..00000000 --- a/pymode/libs/pylint/test/functional/arguments_differ.txt +++ /dev/null @@ -1,3 +0,0 @@ -arguments-differ:12:Child.test:Arguments number differs from overridden 'test' method -arguments-differ:23:ChildDefaults.test:Arguments number differs from overridden 'test' method -arguments-differ:41:ClassmethodChild.func:Arguments number differs from overridden 'func' method \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/assert_on_tuple.py b/pymode/libs/pylint/test/functional/assert_on_tuple.py deleted file mode 100644 index a612aa47..00000000 --- a/pymode/libs/pylint/test/functional/assert_on_tuple.py +++ /dev/null @@ -1,11 +0,0 @@ -'''Assert check example''' - -# pylint: disable=misplaced-comparison-constant -assert (1 == 1, 2 == 2), "no error" -assert (1 == 1, 2 == 2) # [assert-on-tuple] -assert 1 == 1, "no error" -assert (1 == 1, ), "no error" -assert (1 == 1, ) -assert (1 == 1, 2 == 2, 3 == 5), "no error" -assert () -assert (True, 'error msg') # [assert-on-tuple] diff --git a/pymode/libs/pylint/test/functional/assert_on_tuple.txt b/pymode/libs/pylint/test/functional/assert_on_tuple.txt deleted file mode 100644 index 52d1ca5d..00000000 --- a/pymode/libs/pylint/test/functional/assert_on_tuple.txt +++ /dev/null @@ -1,2 +0,0 @@ -assert-on-tuple:5::Assert called on a 2-uple. Did you mean 'assert x,y'? -assert-on-tuple:11::Assert called on a 2-uple. Did you mean 'assert x,y'? diff --git a/pymode/libs/pylint/test/functional/assigning_non_slot.py b/pymode/libs/pylint/test/functional/assigning_non_slot.py deleted file mode 100644 index 7163ac9a..00000000 --- a/pymode/libs/pylint/test/functional/assigning_non_slot.py +++ /dev/null @@ -1,133 +0,0 @@ -""" Checks assigning attributes not found in class slots -will trigger assigning-non-slot warning. -""" -# pylint: disable=too-few-public-methods, no-init, missing-docstring, no-absolute-import, import-error -from collections import deque - -from missing import Unknown - -class Empty(object): - """ empty """ - -class Bad(object): - """ missing not in slots. """ - - __slots__ = ['member'] - - def __init__(self): - self.missing = 42 # [assigning-non-slot] - -class Bad2(object): - """ missing not in slots """ - __slots__ = [deque.__name__, 'member'] - - def __init__(self): - self.deque = 42 - self.missing = 42 # [assigning-non-slot] - -class Bad3(Bad): - """ missing not found in slots """ - - __slots__ = ['component'] - - def __init__(self): - self.component = 42 - self.member = 24 - self.missing = 42 # [assigning-non-slot] - super(Bad3, self).__init__() - -class Good(Empty): - """ missing not in slots, but Empty doesn't - specify __slots__. - """ - __slots__ = ['a'] - - def __init__(self): - self.missing = 42 - -class Good2(object): - """ Using __dict__ in slots will be safe. """ - - __slots__ = ['__dict__', 'comp'] - - def __init__(self): - self.comp = 4 - self.missing = 5 - -class PropertyGood(object): - """ Using properties is safe. """ - - __slots__ = ['tmp', '_value'] - - @property - def test(self): - return self._value - - @test.setter - def test(self, value): - # pylint: disable=attribute-defined-outside-init - self._value = value - - def __init__(self): - self.test = 42 - -class PropertyGood2(object): - """ Using properties in the body of the class is safe. """ - __slots__ = ['_value'] - - def _getter(self): - return self._value - - def _setter(self, value): - # pylint: disable=attribute-defined-outside-init - self._value = value - - test = property(_getter, _setter) - - def __init__(self): - self.test = 24 - -class UnicodeSlots(object): - """Using unicode objects in __slots__ is okay. - - On Python 3.3 onward, u'' is equivalent to '', - so this test should be safe for both versions. - """ - __slots__ = (u'first', u'second') - - def __init__(self): - self.first = 42 - self.second = 24 - - -class DataDescriptor(object): - def __init__(self, name, default=''): - self.__name = name - self.__default = default - - def __get__(self, inst, cls): - return getattr(inst, self.__name, self.__default) - - def __set__(self, inst, value): - setattr(inst, self.__name, value) - - -class NonDataDescriptor(object): - def __get__(self, inst, cls): - return 42 - - -class SlotsWithDescriptor(object): - __slots__ = ['_err'] - data_descriptor = DataDescriptor('_err') - non_data_descriptor = NonDataDescriptor() - missing_descriptor = Unknown() - - -def dont_emit_for_descriptors(): - inst = SlotsWithDescriptor() - # This should not emit, because attr is - # a data descriptor - inst.data_descriptor = 'foo' - inst.non_data_descriptor = 'lala' # [assigning-non-slot] - return diff --git a/pymode/libs/pylint/test/functional/assigning_non_slot.txt b/pymode/libs/pylint/test/functional/assigning_non_slot.txt deleted file mode 100644 index f6187b51..00000000 --- a/pymode/libs/pylint/test/functional/assigning_non_slot.txt +++ /dev/null @@ -1,4 +0,0 @@ -assigning-non-slot:18:Bad.__init__:Assigning to attribute 'missing' not defined in class slots -assigning-non-slot:26:Bad2.__init__:Assigning to attribute 'missing' not defined in class slots -assigning-non-slot:36:Bad3.__init__:Assigning to attribute 'missing' not defined in class slots -assigning-non-slot:132:dont_emit_for_descriptors:Assigning to attribute 'non_data_descriptor' not defined in class slots \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/async_functions.py b/pymode/libs/pylint/test/functional/async_functions.py deleted file mode 100644 index 486c9ba4..00000000 --- a/pymode/libs/pylint/test/functional/async_functions.py +++ /dev/null @@ -1,64 +0,0 @@ -"""Check that Python 3.5's async functions are properly analyzed by Pylint.""" -# pylint: disable=missing-docstring,invalid-name,too-few-public-methods -# pylint: disable=using-constant-test - -async def next(): # [redefined-builtin] - pass - -async def some_function(arg1, arg2): # [unused-argument] - await arg1 - - -class OtherClass(object): - - @staticmethod - def test(): - return 42 - - -class Class(object): - - async def some_method(self): - super(OtherClass, self).test() # [bad-super-call] - - -# +1: [too-many-arguments,too-many-return-statements, too-many-branches] -async def complex_function(this, function, has, more, arguments, than, - one, _, should, have): - if 1: - return this - elif 1: - return function - elif 1: - return has - elif 1: - return more - elif 1: - return arguments - elif 1: - return than - try: - return one - finally: - pass - if 2: - return should - while True: - pass - if 1: - return have - elif 2: - return function - elif 3: - pass - - -# +1: [duplicate-argument-name,dangerous-default-value] -async def func(a, a, b=[]): - return a, b - - -# +1: [empty-docstring, blacklisted-name] -async def foo(): - "" - \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/async_functions.rc b/pymode/libs/pylint/test/functional/async_functions.rc deleted file mode 100644 index 03004f2c..00000000 --- a/pymode/libs/pylint/test/functional/async_functions.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/async_functions.txt b/pymode/libs/pylint/test/functional/async_functions.txt deleted file mode 100644 index 94a66783..00000000 --- a/pymode/libs/pylint/test/functional/async_functions.txt +++ /dev/null @@ -1,10 +0,0 @@ -redefined-builtin:5:next:"Redefining built-in 'next'" -unused-argument:8:some_function:"Unused argument 'arg2'" -bad-super-call:22:Class.some_method:"Bad first argument 'OtherClass' given to super()" -too-many-arguments:26:complex_function:Too many arguments (10/5) -too-many-branches:26:complex_function:Too many branches (13/12) -too-many-return-statements:26:complex_function:Too many return statements (10/6) -dangerous-default-value:57:func:Dangerous default value [] as argument -duplicate-argument-name:57:func:Duplicate argument name a in function definition -blacklisted-name:62:foo:Black listed name "foo" -empty-docstring:62:foo:Empty function docstring \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/attribute_defined_outside_init.py b/pymode/libs/pylint/test/functional/attribute_defined_outside_init.py deleted file mode 100644 index 912bc459..00000000 --- a/pymode/libs/pylint/test/functional/attribute_defined_outside_init.py +++ /dev/null @@ -1,62 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods,invalid-name - -class A(object): - - def __init__(self): - self.x = 0 - self.setUp() - - def set_y(self, y): - self.y = y - - def set_x(self, x): - self.x = x - - def set_z(self, z): - self.z = z # [attribute-defined-outside-init] - - def setUp(self): - self.x = 0 - self.y = 0 - - -class B(A): - - def test(self): - self.z = 44 # [attribute-defined-outside-init] - - -class C(object): - - def __init__(self): - self._init() - - def _init(self): - self.z = 44 - - -class D(object): - - def setUp(self): - self.set_z() - - def set_z(self): - self.z = 42 - - -class E(object): - - def __init__(self): - i = self._init - i() - - def _init(self): - self.z = 44 - - -class Mixin(object): - - def test_mixin(self): - """Don't emit attribute-defined-outside-init for mixin classes.""" - if self.defined_already: # pylint: disable=access-member-before-definition - self.defined_already = None diff --git a/pymode/libs/pylint/test/functional/attribute_defined_outside_init.txt b/pymode/libs/pylint/test/functional/attribute_defined_outside_init.txt deleted file mode 100644 index 51456e30..00000000 --- a/pymode/libs/pylint/test/functional/attribute_defined_outside_init.txt +++ /dev/null @@ -1,2 +0,0 @@ -attribute-defined-outside-init:16:A.set_z:Attribute 'z' defined outside __init__ -attribute-defined-outside-init:26:B.test:Attribute 'z' defined outside __init__ diff --git a/pymode/libs/pylint/test/functional/bad_continuation.py b/pymode/libs/pylint/test/functional/bad_continuation.py deleted file mode 100644 index c0918a64..00000000 --- a/pymode/libs/pylint/test/functional/bad_continuation.py +++ /dev/null @@ -1,191 +0,0 @@ -"""Regression test case for bad-continuation.""" -# pylint: disable=print-statement,using-constant-test, redefined-variable-type -# Various alignment for brackets -from __future__ import print_function - -LIST0 = [ - 1, 2, 3 -] -LIST1 = [ - 1, 2, 3 - ] -LIST2 = [ - 1, 2, 3 - ] # [bad-continuation] - -# Alignment inside literals -W0 = [1, 2, 3, - 4, 5, 6, - 7, # [bad-continuation] - 8, 9, 10, - 11, 12, 13, - # and a comment - 14, 15, 16] - -W1 = { - 'a': 1, - 'b': 2, # [bad-continuation] - 'c': 3, - } - -W2 = { - 'a': 1, - 'b': 2, # [bad-continuation] - 'c': 3, - } - -W2 = ['some', 'contents' # with a continued comment that may be aligned - # under the previous comment (optionally) - 'and', - 'more', # but this - # [bad-continuation] is not accepted - 'contents', # [bad-continuation] nor this. - ] - -# Values in dictionaries should be indented 4 spaces further if they are on a -# different line than their key -W4 = { - 'key1': - 'value1', # Grandfather in the old style - 'key2': - 'value2', # [bad-continuation] - 'key3': - 'value3', # Comma here - } - -# And should follow the same rules as continuations within parens -W5 = { - 'key1': 'long value' - 'long continuation', - 'key2': 'breaking' - 'wrong', # [bad-continuation] - 'key3': 2*( - 2+2), - 'key4': ('parenthesis', - 'continuation') # No comma here - } - -# Allow values to line up with their keys when the key is next to the brace -W6 = {'key1': - 'value1', - 'key2': - 'value2', - } - -# Or allow them to be indented -W7 = {'key1': - 'value1', - 'key2': - 'value2' - } - -# Bug that caused a warning on the previous two cases permitted these odd -# incorrect indentations -W8 = {'key1': -'value1', # [bad-continuation] - } - -W9 = {'key1': - 'value1', # [bad-continuation] - } - -# Alignment of arguments in function definitions -def continue1(some_arg, - some_other_arg): - """A function with well-aligned arguments.""" - print(some_arg, some_other_arg) - - -def continue2( - some_arg, - some_other_arg): - """A function with well-aligned arguments.""" - print(some_arg, some_other_arg) - -def continue3( - some_arg, # [bad-continuation] - some_other_arg): # [bad-continuation] - """A function with misaligned arguments""" - print(some_arg, some_other_arg) - -def continue4( # pylint:disable=missing-docstring - arg1, - arg2): print(arg1, arg2) - - -def callee(*args): - """noop""" - print(args) - - -callee( - "a", - "b" - ) - -callee("a", - "b") # [bad-continuation] - -callee(5, {'a': 'b', - 'c': 'd'}) - -if ( - 1 - ): pass - -if ( - 1 -): pass -if ( - 1 - ): pass # [bad-continuation] - -if (1 and - 2): # [bad-continuation] - pass - -while (1 and - 2): - pass - -while (1 and - 2 and # [bad-continuation] - 3): - pass - -if ( - 2): pass # [bad-continuation] - -if (1 or - 2 or - 3): pass - -if (1 or - 2 or # [bad-continuation] - 3): print(1, 2) - -if (1 and - 2): pass # [bad-continuation] - -if ( - 2): pass - -if ( - 2): # [bad-continuation] - pass - -L1 = (lambda a, - b: a + b) - -if not (1 and - 2): - print(3) - -if not (1 and - 2): # [bad-continuation] - print(3) - -continue2("foo", - some_other_arg="this " - "is " - "fine") diff --git a/pymode/libs/pylint/test/functional/bad_continuation.txt b/pymode/libs/pylint/test/functional/bad_continuation.txt deleted file mode 100644 index 672f0afd..00000000 --- a/pymode/libs/pylint/test/functional/bad_continuation.txt +++ /dev/null @@ -1,63 +0,0 @@ -bad-continuation:14::"Wrong hanging indentation. - ] # [bad-continuation] -| ^|" -bad-continuation:19::"Wrong continued indentation (remove 3 spaces). - 7, # [bad-continuation] - | ^" -bad-continuation:27::"Wrong hanging indentation (add 1 space). - 'b': 2, # [bad-continuation] - ^|" -bad-continuation:33::"Wrong hanging indentation (add 1 space). - 'b': 2, # [bad-continuation] - ^|" -bad-continuation:41::"Wrong continued indentation. - # [bad-continuation] is not accepted - | | ^" -bad-continuation:42::"Wrong continued indentation (remove 20 spaces). - 'contents', # [bad-continuation] nor this. - | ^" -bad-continuation:51::"Wrong hanging indentation in dict value. - 'value2', # [bad-continuation] - | ^ |" -bad-continuation:61::"Wrong continued indentation (add 4 spaces). - 'wrong', # [bad-continuation] - ^ |" -bad-continuation:85::"Wrong hanging indentation in dict value. -'value1', # [bad-continuation] -^ | |" -bad-continuation:89::"Wrong hanging indentation in dict value. - 'value1', # [bad-continuation] - ^ | |" -bad-continuation:106::"Wrong hanging indentation before block (add 4 spaces). - some_arg, # [bad-continuation] - ^ |" -bad-continuation:107::"Wrong hanging indentation before block (add 4 spaces). - some_other_arg): # [bad-continuation] - ^ |" -bad-continuation:127::"Wrong continued indentation (add 3 spaces). - ""b"") # [bad-continuation] - ^ |" -bad-continuation:141::"Wrong hanging indentation before block. - ): pass # [bad-continuation] -| ^|" -bad-continuation:144::"Wrong continued indentation before block (add 4 spaces). - 2): # [bad-continuation] - ^ |" -bad-continuation:152::"Wrong continued indentation (remove 2 spaces). - 2 and # [bad-continuation] - | ^" -bad-continuation:157::"Wrong hanging indentation before block. - 2): pass # [bad-continuation] - ^ | |" -bad-continuation:164::"Wrong continued indentation before block. - 2 or # [bad-continuation] - |^ |" -bad-continuation:168::"Wrong continued indentation before block. - 2): pass # [bad-continuation] - ^ | |" -bad-continuation:174::"Wrong hanging indentation before block. - 2): # [bad-continuation] - ^ | |" -bad-continuation:185::"Wrong continued indentation (add 4 spaces). - 2): # [bad-continuation] - ^ |" diff --git a/pymode/libs/pylint/test/functional/bad_exception_context.py b/pymode/libs/pylint/test/functional/bad_exception_context.py deleted file mode 100644 index af3e4fb9..00000000 --- a/pymode/libs/pylint/test/functional/bad_exception_context.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Check that raise ... from .. uses a proper exception context """ - -# pylint: disable=unreachable, import-error, multiple-imports - -import socket, unknown - -__revision__ = 0 - -class ExceptionSubclass(Exception): - """ subclass """ - -def test(): - """ docstring """ - raise IndexError from 1 # [bad-exception-context] - raise IndexError from None - raise IndexError from ZeroDivisionError - raise IndexError from object() # [bad-exception-context] - raise IndexError from ExceptionSubclass - raise IndexError from socket.error - raise IndexError() from None - raise IndexError() from ZeroDivisionError - raise IndexError() from ZeroDivisionError() - raise IndexError() from object() # [bad-exception-context] - raise IndexError() from unknown diff --git a/pymode/libs/pylint/test/functional/bad_exception_context.rc b/pymode/libs/pylint/test/functional/bad_exception_context.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/bad_exception_context.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/bad_exception_context.txt b/pymode/libs/pylint/test/functional/bad_exception_context.txt deleted file mode 100644 index 14107555..00000000 --- a/pymode/libs/pylint/test/functional/bad_exception_context.txt +++ /dev/null @@ -1,3 +0,0 @@ -bad-exception-context:14:test:Exception context set to something which is not an exception, nor None -bad-exception-context:17:test:Exception context set to something which is not an exception, nor None -bad-exception-context:23:test:Exception context set to something which is not an exception, nor None \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/bad_indentation.py b/pymode/libs/pylint/test/functional/bad_indentation.py deleted file mode 100644 index 4c50eae0..00000000 --- a/pymode/libs/pylint/test/functional/bad_indentation.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=missing-docstring, pointless-statement -from __future__ import print_function - - -def totoo(): - print('malindented') # [bad-indentation] - -def tutuu(): - print('good indentation') - -def titii(): - 1 # and this. # [bad-indentation] - -def tataa(kdict): - for key in ['1', '2', '3']: - key = key.lower() - - if key in kdict: - del kdict[key] diff --git a/pymode/libs/pylint/test/functional/bad_indentation.txt b/pymode/libs/pylint/test/functional/bad_indentation.txt deleted file mode 100644 index c5c00bb1..00000000 --- a/pymode/libs/pylint/test/functional/bad_indentation.txt +++ /dev/null @@ -1,2 +0,0 @@ -bad-indentation:6::Bad indentation. Found 1 spaces, expected 4 -bad-indentation:12::Bad indentation. Found 5 spaces, expected 4 diff --git a/pymode/libs/pylint/test/functional/bad_inline_option.py b/pymode/libs/pylint/test/functional/bad_inline_option.py deleted file mode 100644 index be6e2408..00000000 --- a/pymode/libs/pylint/test/functional/bad_inline_option.py +++ /dev/null @@ -1,5 +0,0 @@ -"""errors-only is not usable as an inline option""" -# +1: [bad-inline-option] -# pylint: errors-only - -CONST = "This is not a pylint: inline option." diff --git a/pymode/libs/pylint/test/functional/bad_inline_option.rc b/pymode/libs/pylint/test/functional/bad_inline_option.rc deleted file mode 100644 index b211d725..00000000 --- a/pymode/libs/pylint/test/functional/bad_inline_option.rc +++ /dev/null @@ -1,2 +0,0 @@ -[Messages Control] -enable=I diff --git a/pymode/libs/pylint/test/functional/bad_inline_option.txt b/pymode/libs/pylint/test/functional/bad_inline_option.txt deleted file mode 100644 index 91ac1af3..00000000 --- a/pymode/libs/pylint/test/functional/bad_inline_option.txt +++ /dev/null @@ -1 +0,0 @@ -bad-inline-option:3::Unable to consider inline option 'errors-only' diff --git a/pymode/libs/pylint/test/functional/bad_open_mode.py b/pymode/libs/pylint/test/functional/bad_open_mode.py deleted file mode 100644 index 6b749de0..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Warnings for using open() with an invalid mode string.""" - -open('foo.bar', 'w', 2) -open('foo.bar', 'rw') # [bad-open-mode] -open(name='foo.bar', buffering=10, mode='rw') # [bad-open-mode] -open(mode='rw', name='foo.bar') # [bad-open-mode] -open('foo.bar', 'U+') -open('foo.bar', 'rb+') -open('foo.bar', 'Uw') # [bad-open-mode] -open('foo.bar', 2) # [bad-open-mode] -open('foo.bar', buffering=2) -WRITE_MODE = 'w' -open('foo.bar', 'U' + WRITE_MODE + 'z') # [bad-open-mode] -open('foo.bar', 'br') # [bad-open-mode] -open('foo.bar', 'wU') # [bad-open-mode] -open('foo.bar', 'r+b') -open('foo.bar', 'r+') -open('foo.bar', 'w+') -open('foo.bar', 'xb') # [bad-open-mode] -open('foo.bar', 'rx') # [bad-open-mode] -open('foo.bar', 'Ur') -open('foo.bar', 'rU') -open('foo.bar', 'rUb') -open('foo.bar', 'rUb+') -open('foo.bar', 'rU+b') -open('foo.bar', 'r+Ub') -open('foo.bar', '+rUb') # [bad-open-mode] -open('foo.bar', 'ab+') -open('foo.bar', 'a+b') -open('foo.bar', 'aU') # [bad-open-mode] -open('foo.bar', 'U+b') -open('foo.bar', '+Ub') -open('foo.bar', 'b+U') -open('foo.bar', 'Urb+') -open('foo.bar', 'Ur+b') -open('foo.bar', 'Ubr') # [bad-open-mode] -open('foo.bar', 'Ut') # [bad-open-mode] diff --git a/pymode/libs/pylint/test/functional/bad_open_mode.rc b/pymode/libs/pylint/test/functional/bad_open_mode.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/bad_open_mode.txt b/pymode/libs/pylint/test/functional/bad_open_mode.txt deleted file mode 100644 index b0222863..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode.txt +++ /dev/null @@ -1,14 +0,0 @@ -bad-open-mode:4::"""rw"" is not a valid mode for open." -bad-open-mode:5::"""rw"" is not a valid mode for open." -bad-open-mode:6::"""rw"" is not a valid mode for open." -bad-open-mode:9::"""Uw"" is not a valid mode for open." -bad-open-mode:10::"""2"" is not a valid mode for open." -bad-open-mode:13::"""Uwz"" is not a valid mode for open." -bad-open-mode:14::"""br"" is not a valid mode for open." -bad-open-mode:15::"""wU"" is not a valid mode for open." -bad-open-mode:19::"""xb"" is not a valid mode for open." -bad-open-mode:20::"""rx"" is not a valid mode for open." -bad-open-mode:27::"""+rUb"" is not a valid mode for open." -bad-open-mode:30::"""aU"" is not a valid mode for open." -bad-open-mode:36::"""Ubr"" is not a valid mode for open." -bad-open-mode:37::"""Ut"" is not a valid mode for open." diff --git a/pymode/libs/pylint/test/functional/bad_open_mode_py3.py b/pymode/libs/pylint/test/functional/bad_open_mode_py3.py deleted file mode 100644 index 93fcd068..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode_py3.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Warnings for using open() with an invalid mode string.""" - -NAME = "foo.bar" -open(NAME, "wb") -open(NAME, "w") -open(NAME, "rb") -open(NAME, "x") -open(NAME, "br") -open(NAME, "+r") -open(NAME, "xb") -open(NAME, "rwx") # [bad-open-mode] -open(NAME, "rr") # [bad-open-mode] -open(NAME, "+") # [bad-open-mode] -open(NAME, "xw") # [bad-open-mode] -open(NAME, "ab+") -open(NAME, "a+b") -open(NAME, "+ab") -open(NAME, "+rUb") -open(NAME, "x+b") -open(NAME, "Ua") # [bad-open-mode] -open(NAME, "Ur++") # [bad-open-mode] -open(NAME, "Ut") -open(NAME, "Ubr") diff --git a/pymode/libs/pylint/test/functional/bad_open_mode_py3.rc b/pymode/libs/pylint/test/functional/bad_open_mode_py3.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/bad_open_mode_py3.txt b/pymode/libs/pylint/test/functional/bad_open_mode_py3.txt deleted file mode 100644 index 25397374..00000000 --- a/pymode/libs/pylint/test/functional/bad_open_mode_py3.txt +++ /dev/null @@ -1,6 +0,0 @@ -bad-open-mode:11::"""rwx"" is not a valid mode for open." -bad-open-mode:12::"""rr"" is not a valid mode for open." -bad-open-mode:13::"""+"" is not a valid mode for open." -bad-open-mode:14::"""xw"" is not a valid mode for open." -bad-open-mode:20::"""Ua"" is not a valid mode for open." -bad-open-mode:21::"""Ur++"" is not a valid mode for open." diff --git a/pymode/libs/pylint/test/functional/bad_reversed_sequence.py b/pymode/libs/pylint/test/functional/bad_reversed_sequence.py deleted file mode 100644 index 6deb7957..00000000 --- a/pymode/libs/pylint/test/functional/bad_reversed_sequence.py +++ /dev/null @@ -1,71 +0,0 @@ -""" Checks that reversed() receive proper argument """ -# pylint: disable=missing-docstring -# pylint: disable=too-few-public-methods,no-self-use,no-absolute-import -from collections import deque - -__revision__ = 0 - -class GoodReversed(object): - """ Implements __reversed__ """ - def __reversed__(self): - return [1, 2, 3] - -class SecondGoodReversed(object): - """ Implements __len__ and __getitem__ """ - def __len__(self): - return 3 - - def __getitem__(self, index): - return index - -class BadReversed(object): - """ implements only len() """ - def __len__(self): - return 3 - -class SecondBadReversed(object): - """ implements only __getitem__ """ - def __getitem__(self, index): - return index - -class ThirdBadReversed(dict): - """ dict subclass """ - -def uninferable(seq): - """ This can't be infered at this moment, - make sure we don't have a false positive. - """ - return reversed(seq) - -def test(path): - """ test function """ - seq = reversed() # No argument given - seq = reversed(None) # [bad-reversed-sequence] - seq = reversed([1, 2, 3]) - seq = reversed((1, 2, 3)) - seq = reversed(set()) # [bad-reversed-sequence] - seq = reversed({'a': 1, 'b': 2}) # [bad-reversed-sequence] - seq = reversed(iter([1, 2, 3])) # [bad-reversed-sequence] - seq = reversed(GoodReversed()) - seq = reversed(SecondGoodReversed()) - seq = reversed(BadReversed()) # [bad-reversed-sequence] - seq = reversed(SecondBadReversed()) # [bad-reversed-sequence] - seq = reversed(range(100)) - seq = reversed(ThirdBadReversed()) # [bad-reversed-sequence] - seq = reversed(lambda: None) # [bad-reversed-sequence] - seq = reversed(deque([])) - seq = reversed("123") - seq = uninferable([1, 2, 3]) - seq = reversed(path.split("/")) - return seq - -def test_dict_ancestor_and_reversed(): - """Don't emit for subclasses of dict, with __reversed__ implemented.""" - from collections import OrderedDict - - class Child(dict): - def __reversed__(self): - return reversed(range(10)) - - seq = reversed(OrderedDict()) - return reversed(Child()), seq diff --git a/pymode/libs/pylint/test/functional/bad_reversed_sequence.txt b/pymode/libs/pylint/test/functional/bad_reversed_sequence.txt deleted file mode 100644 index 19c51a12..00000000 --- a/pymode/libs/pylint/test/functional/bad_reversed_sequence.txt +++ /dev/null @@ -1,8 +0,0 @@ -bad-reversed-sequence:43:test:The first reversed() argument is not a sequence -bad-reversed-sequence:46:test:The first reversed() argument is not a sequence -bad-reversed-sequence:47:test:The first reversed() argument is not a sequence -bad-reversed-sequence:48:test:The first reversed() argument is not a sequence -bad-reversed-sequence:51:test:The first reversed() argument is not a sequence -bad-reversed-sequence:52:test:The first reversed() argument is not a sequence -bad-reversed-sequence:54:test:The first reversed() argument is not a sequence -bad-reversed-sequence:55:test:The first reversed() argument is not a sequence diff --git a/pymode/libs/pylint/test/functional/bad_staticmethod_argument.py b/pymode/libs/pylint/test/functional/bad_staticmethod_argument.py deleted file mode 100644 index a71a40e5..00000000 --- a/pymode/libs/pylint/test/functional/bad_staticmethod_argument.py +++ /dev/null @@ -1,16 +0,0 @@ -# pylint: disable=missing-docstring, no-staticmethod-decorator - -class Abcd(object): - - def method1(self): # [bad-staticmethod-argument] - pass - - method1 = staticmethod(method1) - - def method2(cls): # [bad-staticmethod-argument] - pass - - method2 = staticmethod(method2) - - def __init__(self): - pass diff --git a/pymode/libs/pylint/test/functional/bad_staticmethod_argument.txt b/pymode/libs/pylint/test/functional/bad_staticmethod_argument.txt deleted file mode 100644 index a9d5b468..00000000 --- a/pymode/libs/pylint/test/functional/bad_staticmethod_argument.txt +++ /dev/null @@ -1,2 +0,0 @@ -bad-staticmethod-argument:5:Abcd.method1:Static method with 'self' as first argument -bad-staticmethod-argument:10:Abcd.method2:Static method with 'cls' as first argument \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/bad_whitespace.py b/pymode/libs/pylint/test/functional/bad_whitespace.py deleted file mode 100644 index fe22a21e..00000000 --- a/pymode/libs/pylint/test/functional/bad_whitespace.py +++ /dev/null @@ -1,3 +0,0 @@ -# pylint: disable = invalid-name, missing-docstring, unused-variable, unused-argument -def function(hello): - x, y, z = (1,2,3,) # [bad-whitespace, bad-whitespace, missing-final-newline] \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/bad_whitespace.txt b/pymode/libs/pylint/test/functional/bad_whitespace.txt deleted file mode 100644 index 524d4d93..00000000 --- a/pymode/libs/pylint/test/functional/bad_whitespace.txt +++ /dev/null @@ -1,7 +0,0 @@ -bad-whitespace:3::"Exactly one space required after comma - x, y, z = (1,2,3,) # [bad-whitespace, bad-whitespace, missing-final-newline] - ^" -bad-whitespace:3::"Exactly one space required after comma - x, y, z = (1,2,3,) # [bad-whitespace, bad-whitespace, missing-final-newline] - ^" -missing-final-newline:3::"Final newline missing" diff --git a/pymode/libs/pylint/test/functional/bare_except.py b/pymode/libs/pylint/test/functional/bare_except.py deleted file mode 100644 index 47a20792..00000000 --- a/pymode/libs/pylint/test/functional/bare_except.py +++ /dev/null @@ -1,6 +0,0 @@ -# pylint: disable=missing-docstring, import-error - -try: - 1 + "2" -except: # [bare-except] - pass diff --git a/pymode/libs/pylint/test/functional/bare_except.txt b/pymode/libs/pylint/test/functional/bare_except.txt deleted file mode 100644 index ccb7ba90..00000000 --- a/pymode/libs/pylint/test/functional/bare_except.txt +++ /dev/null @@ -1 +0,0 @@ -bare-except:5::No exception type(s) specified \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/blacklisted_name.py b/pymode/libs/pylint/test/functional/blacklisted_name.py deleted file mode 100644 index b62c6d27..00000000 --- a/pymode/libs/pylint/test/functional/blacklisted_name.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=missing-docstring - -def baz(): # [blacklisted-name] - pass diff --git a/pymode/libs/pylint/test/functional/blacklisted_name.txt b/pymode/libs/pylint/test/functional/blacklisted_name.txt deleted file mode 100644 index f0fc9c20..00000000 --- a/pymode/libs/pylint/test/functional/blacklisted_name.txt +++ /dev/null @@ -1 +0,0 @@ -blacklisted-name:3:baz:Black listed name "baz" diff --git a/pymode/libs/pylint/test/functional/boolean_datetime.py b/pymode/libs/pylint/test/functional/boolean_datetime.py deleted file mode 100644 index c8276666..00000000 --- a/pymode/libs/pylint/test/functional/boolean_datetime.py +++ /dev/null @@ -1,30 +0,0 @@ -""" Checks for boolean uses of datetime.time. """ -# pylint: disable=superfluous-parens,print-statement,no-absolute-import -import datetime - -if datetime.time(0, 0, 0): # [boolean-datetime] - print("datetime.time(0,0,0) is not a bug!") -else: - print("datetime.time(0,0,0) is a bug!") - -if not datetime.time(0, 0, 1): # [boolean-datetime] - print("datetime.time(0,0,1) is not a bug!") -else: - print("datetime.time(0,0,1) is a bug!") - -DATA = not datetime.time(0, 0, 0) # [boolean-datetime] -DATA1 = True if datetime.time(0, 0, 0) else False # [boolean-datetime] -DATA2 = datetime.time(0, 0, 0) or True # [boolean-datetime] -DATA3 = datetime.time(0, 0, 0) and True # [boolean-datetime] -DATA4 = False or True or datetime.time(0, 0, 0) # [boolean-datetime] -DATA5 = False and datetime.time(0, 0, 0) or True # [boolean-datetime] - - -def cant_infer(data): - """ Can't infer what data is """ - hophop = not data - troptrop = True if data else False - toptop = data or True - return hophop, troptrop, toptop - -cant_infer(datetime.time(0, 0, 0)) diff --git a/pymode/libs/pylint/test/functional/boolean_datetime.rc b/pymode/libs/pylint/test/functional/boolean_datetime.rc deleted file mode 100644 index abe8fdf1..00000000 --- a/pymode/libs/pylint/test/functional/boolean_datetime.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.5 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/boolean_datetime.txt b/pymode/libs/pylint/test/functional/boolean_datetime.txt deleted file mode 100644 index f3287d4f..00000000 --- a/pymode/libs/pylint/test/functional/boolean_datetime.txt +++ /dev/null @@ -1,8 +0,0 @@ -boolean-datetime:5::Using datetime.time in a boolean context. -boolean-datetime:10::Using datetime.time in a boolean context. -boolean-datetime:15::Using datetime.time in a boolean context. -boolean-datetime:16::Using datetime.time in a boolean context. -boolean-datetime:17::Using datetime.time in a boolean context. -boolean-datetime:18::Using datetime.time in a boolean context. -boolean-datetime:19::Using datetime.time in a boolean context. -boolean-datetime:20::Using datetime.time in a boolean context. diff --git a/pymode/libs/pylint/test/functional/cellvar_escaping_loop.py b/pymode/libs/pylint/test/functional/cellvar_escaping_loop.py deleted file mode 100644 index a6d87a20..00000000 --- a/pymode/libs/pylint/test/functional/cellvar_escaping_loop.py +++ /dev/null @@ -1,130 +0,0 @@ -# pylint: disable=print-statement -"""Tests for loopvar-in-closure.""" -from __future__ import print_function - -def good_case(): - """No problems here.""" - lst = [] - for i in range(10): - lst.append(i) - - -def good_case2(): - """No problems here.""" - return [i for i in range(10)] - - -def good_case3(): - """No problems here.""" - lst = [] - for i in range(10): # [unused-variable] - lst.append(lambda i=i: i) - - -def good_case4(): - """No problems here.""" - lst = [] - for i in range(10): - print(i) - lst.append(lambda i: i) - - -def good_case5(): - """No problems here.""" - return (i for i in range(10)) - - -def good_case6(): - """Accept use of the variable after the loop. - - There's already a warning about possibly undefined loop variables, and - the value will not change any more.""" - for i in range(10): - print(i) - return lambda: i # [undefined-loop-variable] - - -def good_case7(): - """Accept use of the variable inside return.""" - for i in range(10): - if i == 8: - return lambda: i - return lambda: -1 - - -def good_case8(): - """Lambda defined and called in loop.""" - for i in range(10): - print((lambda x: i + x)(1)) - - -def good_case9(): - """Another eager binding of the cell variable.""" - funs = [] - for i in range(10): - def func(bound_i=i): - """Ignore.""" - return bound_i - funs.append(func) - return funs - - -def bad_case(): - """Closing over a loop variable.""" - lst = [] - for i in range(10): - print(i) - lst.append(lambda: i) # [cell-var-from-loop] - - -def bad_case2(): - """Closing over a loop variable.""" - return [lambda: i for i in range(10)] # [cell-var-from-loop] - - -def bad_case3(): - """Closing over variable defined in loop.""" - lst = [] - for i in range(10): - j = i * i - lst.append(lambda: j) # [cell-var-from-loop] - return lst - - -def bad_case4(): - """Closing over variable defined in loop.""" - lst = [] - for i in range(10): - def nested(): - """Nested function.""" - return i**2 # [cell-var-from-loop] - lst.append(nested) - return lst - - -def bad_case5(): - """Problematic case. - - If this function is used as - - >>> [x() for x in bad_case5()] - - it behaves 'as expected', i.e. the result is range(10). - - If it's used with - - >>> lst = list(bad_case5()) - >>> [x() for x in lst] - - the result is [9] * 10 again. - """ - return (lambda: i for i in range(10)) # [cell-var-from-loop] - - -def bad_case6(): - """Closing over variable defined in loop.""" - lst = [] - for i, j in zip(range(10), range(10, 20)): - print(j) - lst.append(lambda: i) # [cell-var-from-loop] - return lst diff --git a/pymode/libs/pylint/test/functional/cellvar_escaping_loop.txt b/pymode/libs/pylint/test/functional/cellvar_escaping_loop.txt deleted file mode 100644 index a34ed28d..00000000 --- a/pymode/libs/pylint/test/functional/cellvar_escaping_loop.txt +++ /dev/null @@ -1,8 +0,0 @@ -unused-variable:20:good_case3:Unused variable 'i' -undefined-loop-variable:44:good_case6.:Using possibly undefined loop variable 'i' -cell-var-from-loop:77:bad_case.:Cell variable i defined in loop -cell-var-from-loop:82:bad_case2.:Cell variable i defined in loop -cell-var-from-loop:90:bad_case3.:Cell variable j defined in loop -cell-var-from-loop:100:bad_case4.nested:Cell variable i defined in loop -cell-var-from-loop:121:bad_case5.:Cell variable i defined in loop -cell-var-from-loop:129:bad_case6.:Cell variable i defined in loop diff --git a/pymode/libs/pylint/test/functional/class_members_py27.py b/pymode/libs/pylint/test/functional/class_members_py27.py deleted file mode 100644 index f8bbe59a..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py27.py +++ /dev/null @@ -1,65 +0,0 @@ -""" Various tests for class members access. """ -# pylint: disable=R0903,print-statement,no-absolute-import, metaclass-assignment,import-error,no-init,missing-docstring, wrong-import-order,wrong-import-position -from missing import Missing -class MyClass(object): - """class docstring""" - - def __init__(self): - """init""" - self.correct = 1 - - def test(self): - """test""" - self.correct += 2 - self.incorrect += 2 # [no-member] - del self.havenot # [no-member] - self.nonexistent1.truc() # [no-member] - self.nonexistent2[1] = 'hehe' # [no-member] - -class XYZMixin(object): - """access to undefined members should be ignored in mixin classes by - default - """ - def __init__(self): - print self.nonexistent - - -class NewClass(object): - """use object.__setattr__""" - def __init__(self): - self.__setattr__('toto', 'tutu') - -from abc import ABCMeta - -class TestMetaclass(object): - """ Test attribute access for metaclasses. """ - __metaclass__ = ABCMeta - -class Metaclass(type): - """ metaclass """ - @classmethod - def test(mcs): - """ classmethod """ - -class UsingMetaclass(object): - """ empty """ - __metaclass__ = Metaclass - -#TestMetaclass.register(int) -#UsingMetaclass.test() -TestMetaclass().register(int) # [no-member] -UsingMetaclass().test() # [no-member] - - -class NoKnownBases(Missing): - """Don't emit no-member if we don't know the bases of a class.""" - -NoKnownBases().lalala() - -# Should be enabled on astroid > 1.4.0 -#class MetaClass(object): -# """Look some methods in the implicit metaclass.""" -# -# @classmethod -# def whatever(cls): -# return cls.mro() + cls.missing() diff --git a/pymode/libs/pylint/test/functional/class_members_py27.rc b/pymode/libs/pylint/test/functional/class_members_py27.rc deleted file mode 100644 index c4f2e664..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py27.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -min_pyver=2.7 -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/class_members_py27.txt b/pymode/libs/pylint/test/functional/class_members_py27.txt deleted file mode 100644 index e5e60052..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py27.txt +++ /dev/null @@ -1,6 +0,0 @@ -no-member:14:MyClass.test:Instance of 'MyClass' has no 'incorrect' member:INFERENCE -no-member:15:MyClass.test:Instance of 'MyClass' has no 'havenot' member:INFERENCE -no-member:16:MyClass.test:Instance of 'MyClass' has no 'nonexistent1' member:INFERENCE -no-member:17:MyClass.test:Instance of 'MyClass' has no 'nonexistent2' member:INFERENCE -no-member:50::Instance of 'TestMetaclass' has no 'register' member:INFERENCE -no-member:51::Instance of 'UsingMetaclass' has no 'test' member:INFERENCE diff --git a/pymode/libs/pylint/test/functional/class_members_py30.py b/pymode/libs/pylint/test/functional/class_members_py30.py deleted file mode 100644 index 05ba75a8..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py30.py +++ /dev/null @@ -1,63 +0,0 @@ -""" Various tests for class members access. """ -# pylint: disable=R0903,import-error,no-init,missing-docstring, wrong-import-position,wrong-import-order -from missing import Missing -class MyClass(object): - """class docstring""" - - def __init__(self): - """init""" - self.correct = 1 - - def test(self): - """test""" - self.correct += 2 - self.incorrect += 2 # [no-member] - del self.havenot # [no-member] - self.nonexistent1.truc() # [no-member] - self.nonexistent2[1] = 'hehe' # [no-member] - -class XYZMixin(object): - """access to undefined members should be ignored in mixin classes by - default - """ - def __init__(self): - print(self.nonexistent) - - -class NewClass(object): - """use object.__setattr__""" - def __init__(self): - self.__setattr__('toto', 'tutu') - -from abc import ABCMeta - -class TestMetaclass(object, metaclass=ABCMeta): - """ Test attribute access for metaclasses. """ - -class Metaclass(type): - """ metaclass """ - @classmethod - def test(mcs): - """ classmethod """ - -class UsingMetaclass(object, metaclass=Metaclass): - """ empty """ - -# TestMetaclass.register(int) -# UsingMetaclass.test() -TestMetaclass().register(int) # [no-member] -UsingMetaclass().test() # [no-member] - - -class NoKnownBases(Missing): - """Don't emit no-member if we don't know the bases of a class.""" - -NoKnownBases().lalala() - -# Enabled on a more capable astroid (1.4.0) -# class MetaClass(object): -# """Look some methods in the implicit metaclass.""" -# -# @classmethod -# def whatever(cls): -# return cls.mro() + cls.missing() diff --git a/pymode/libs/pylint/test/functional/class_members_py30.rc b/pymode/libs/pylint/test/functional/class_members_py30.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py30.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/class_members_py30.txt b/pymode/libs/pylint/test/functional/class_members_py30.txt deleted file mode 100644 index b6d369f0..00000000 --- a/pymode/libs/pylint/test/functional/class_members_py30.txt +++ /dev/null @@ -1,7 +0,0 @@ -no-member:14:MyClass.test:Instance of 'MyClass' has no 'incorrect' member:INFERENCE -no-member:15:MyClass.test:Instance of 'MyClass' has no 'havenot' member:INFERENCE -no-member:16:MyClass.test:Instance of 'MyClass' has no 'nonexistent1' member:INFERENCE -no-member:17:MyClass.test:Instance of 'MyClass' has no 'nonexistent2' member:INFERENCE -no-member:48::Instance of 'TestMetaclass' has no 'register' member:INFERENCE -no-member:49::Instance of 'UsingMetaclass' has no 'test' member:INFERENCE -no-member:63:MetaClass.whatever:Class 'MetaClass' has no 'missing' member:INFERENCE \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/class_scope.py b/pymode/libs/pylint/test/functional/class_scope.py deleted file mode 100644 index dfc8dd83..00000000 --- a/pymode/libs/pylint/test/functional/class_scope.py +++ /dev/null @@ -1,22 +0,0 @@ -# pylint: disable=R0903,W0232 -"""check for scope problems""" - -__revision__ = None - -class Well(object): - """well""" - attr = 42 - get_attr = lambda arg=attr: arg * 24 - # +1: [used-before-assignment] - get_attr_bad = lambda arg=revattr: revattr * 42 - revattr = 24 - bad_lambda = lambda: get_attr_bad # [undefined-variable] - - class Data(object): - """base hidden class""" - class Sub(Data): - """whaou, is Data found???""" - attr = Data() # [undefined-variable] - def func(self): - """check Sub is not defined here""" - return Sub(), self # [undefined-variable] diff --git a/pymode/libs/pylint/test/functional/class_scope.txt b/pymode/libs/pylint/test/functional/class_scope.txt deleted file mode 100644 index ea6c45ab..00000000 --- a/pymode/libs/pylint/test/functional/class_scope.txt +++ /dev/null @@ -1,4 +0,0 @@ -used-before-assignment:11:Well.:Using variable 'revattr' before assignment -undefined-variable:13:Well.:Undefined variable 'get_attr_bad' -undefined-variable:19:Well.Sub:Undefined variable 'Data' -undefined-variable:22:Well.func:Undefined variable 'Sub' diff --git a/pymode/libs/pylint/test/functional/confidence_filter.py b/pymode/libs/pylint/test/functional/confidence_filter.py deleted file mode 100644 index b934c9d3..00000000 --- a/pymode/libs/pylint/test/functional/confidence_filter.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Test for the confidence filter.""" -from __future__ import print_function - -class Client(object): - """use provider class""" - - def __init__(self): - self.set_later = 0 - - def set_set_later(self, value): - """set set_later attribute (introduce an inference ambiguity)""" - self.set_later = value - -print(Client().set_later.lower()) -print(Client().foo) # [no-member] diff --git a/pymode/libs/pylint/test/functional/confidence_filter.rc b/pymode/libs/pylint/test/functional/confidence_filter.rc deleted file mode 100644 index 74953b68..00000000 --- a/pymode/libs/pylint/test/functional/confidence_filter.rc +++ /dev/null @@ -1,3 +0,0 @@ -[Messages Control] -disable=no-init,too-few-public-methods,undefined-variable,print-statement -confidence=INFERENCE,HIGH,UNDEFINED diff --git a/pymode/libs/pylint/test/functional/confidence_filter.txt b/pymode/libs/pylint/test/functional/confidence_filter.txt deleted file mode 100644 index 50a3767c..00000000 --- a/pymode/libs/pylint/test/functional/confidence_filter.txt +++ /dev/null @@ -1 +0,0 @@ -no-member:15::Instance of 'Client' has no 'foo' member:INFERENCE diff --git a/pymode/libs/pylint/test/functional/confusing_with_statement.py b/pymode/libs/pylint/test/functional/confusing_with_statement.py deleted file mode 100644 index 1444a979..00000000 --- a/pymode/libs/pylint/test/functional/confusing_with_statement.py +++ /dev/null @@ -1,27 +0,0 @@ -# pylint: disable=undefined-variable,not-context-manager,missing-docstring - -# both context managers are named -with one as first, two as second: - pass - -# first matched as tuple; this is ok -with one as (first, second), third: - pass - -# the first context manager doesn't have as name -with one, two as second: - pass - -# the second is a function call; this is ok -with one as first, two(): - pass - -# nested with statements; make sure no message is emited -# this could be a false positive on Py2 -with one as first: - with two: - pass - -# ambiguous looking with statement -with one as first, two: # [confusing-with-statement] - pass diff --git a/pymode/libs/pylint/test/functional/confusing_with_statement.txt b/pymode/libs/pylint/test/functional/confusing_with_statement.txt deleted file mode 100644 index 750ad714..00000000 --- a/pymode/libs/pylint/test/functional/confusing_with_statement.txt +++ /dev/null @@ -1 +0,0 @@ -confusing-with-statement:26::Following "as" with another context manager looks like a tuple. diff --git a/pymode/libs/pylint/test/functional/consider_iterating_dictionary.py b/pymode/libs/pylint/test/functional/consider_iterating_dictionary.py deleted file mode 100644 index f5b95728..00000000 --- a/pymode/libs/pylint/test/functional/consider_iterating_dictionary.py +++ /dev/null @@ -1,28 +0,0 @@ -# pylint: disable=missing-docstring, expression-not-assigned, too-few-public-methods, no-member, import-error, no-self-use - -from unknown import Unknown - - -class CustomClass(object): - def keys(self): - return [] - -for key in Unknown().keys(): - pass -for key in Unknown.keys(): - pass -for key in dict.keys(): - pass -for key in {}.values(): - pass -for key in {}.key(): - pass -for key in CustomClass().keys(): - pass - -[key for key in {}.keys()] # [consider-iterating-dictionary] -(key for key in {}.keys()) # [consider-iterating-dictionary] -{key for key in {}.keys()} # [consider-iterating-dictionary] -{key: key for key in {}.keys()} # [consider-iterating-dictionary] -for key in {}.keys(): # [consider-iterating-dictionary] - pass diff --git a/pymode/libs/pylint/test/functional/consider_iterating_dictionary.txt b/pymode/libs/pylint/test/functional/consider_iterating_dictionary.txt deleted file mode 100644 index b862cbbb..00000000 --- a/pymode/libs/pylint/test/functional/consider_iterating_dictionary.txt +++ /dev/null @@ -1,5 +0,0 @@ -consider-iterating-dictionary:23::Consider iterating the dictionary directly instead of calling .keys() -consider-iterating-dictionary:24::Consider iterating the dictionary directly instead of calling .keys() -consider-iterating-dictionary:25::Consider iterating the dictionary directly instead of calling .keys() -consider-iterating-dictionary:26::Consider iterating the dictionary directly instead of calling .keys() -consider-iterating-dictionary:27::Consider iterating the dictionary directly instead of calling .keys() diff --git a/pymode/libs/pylint/test/functional/consider_using_enumerate.py b/pymode/libs/pylint/test/functional/consider_using_enumerate.py deleted file mode 100644 index 4457f5c5..00000000 --- a/pymode/libs/pylint/test/functional/consider_using_enumerate.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Emit a message for iteration through range and len is encountered.""" - -# pylint: disable=missing-docstring, import-error - -def bad(): - iterable = [1, 2, 3] - for obj in range(len(iterable)): # [consider-using-enumerate] - yield iterable[obj] - - -def good(): - iterable = other_obj = [1, 2, 3] - total = 0 - for obj in range(len(iterable)): - total += obj - yield total - yield iterable[obj + 1: 2] - yield iterable[len(obj)] - for obj in iterable: - yield iterable[obj - 1] - - for index, obj in enumerate(iterable): - yield iterable[index] - for index in range(0, 10): - yield iterable[index + 1] - for index in range(10): - yield iterable[index] - for index in range(len([1, 2, 3, 4])): - yield index - for index in range(len(iterable)): - yield [1, 2, 3][index] - yield len([1, 2, 3]) - for index in range(len(iterable)): - yield other_obj[index] - - from unknown import unknown - for index in range(unknown(iterable)): - yield iterable[index] - - for index in range(len(iterable)): - def test(iterable): - return iterable[index] - yield test([1, 2, 3]) diff --git a/pymode/libs/pylint/test/functional/consider_using_enumerate.txt b/pymode/libs/pylint/test/functional/consider_using_enumerate.txt deleted file mode 100644 index 36cd55d4..00000000 --- a/pymode/libs/pylint/test/functional/consider_using_enumerate.txt +++ /dev/null @@ -1 +0,0 @@ -consider-using-enumerate:7:bad:Consider using enumerate instead of iterating with range and len diff --git a/pymode/libs/pylint/test/functional/continue_in_finally.py b/pymode/libs/pylint/test/functional/continue_in_finally.py deleted file mode 100644 index d40d63ca..00000000 --- a/pymode/libs/pylint/test/functional/continue_in_finally.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Test that `continue` is catched when met inside a `finally` clause.""" - -# pylint: disable=missing-docstring, lost-exception, broad-except - -while True: - try: - pass - finally: - continue # [continue-in-finally] - -while True: - try: - pass - finally: - break - -while True: - try: - pass - except Exception: - pass - else: - continue - \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/continue_in_finally.txt b/pymode/libs/pylint/test/functional/continue_in_finally.txt deleted file mode 100644 index cb2ee168..00000000 --- a/pymode/libs/pylint/test/functional/continue_in_finally.txt +++ /dev/null @@ -1 +0,0 @@ -continue-in-finally:9::'continue' not supported inside 'finally' clause diff --git a/pymode/libs/pylint/test/functional/crash_missing_module_type.py b/pymode/libs/pylint/test/functional/crash_missing_module_type.py deleted file mode 100644 index 61e2dd6d..00000000 --- a/pymode/libs/pylint/test/functional/crash_missing_module_type.py +++ /dev/null @@ -1,18 +0,0 @@ -""" Test for a crash found in -https://bitbucket.org/logilab/astroid/issue/45/attributeerror-module-object-has-no#comment-11944673 -""" -# pylint: disable=no-init, invalid-name, too-few-public-methods, redefined-outer-name -def decor(trop): - """ decorator """ - return trop - -class Foo(object): - """ Class """ - @decor - def prop(self): - """ method """ - return self - -if __name__ == '__main__': - trop = Foo() - trop.prop = 42 diff --git a/pymode/libs/pylint/test/functional/crash_missing_module_type.txt b/pymode/libs/pylint/test/functional/crash_missing_module_type.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/functional/ctor_arguments.py b/pymode/libs/pylint/test/functional/ctor_arguments.py deleted file mode 100644 index f7437b37..00000000 --- a/pymode/libs/pylint/test/functional/ctor_arguments.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Test function argument checker on __init__ - -Based on test/functional/arguments.py -""" -# pylint: disable=C0111,R0903,W0231 - - -class Class1Arg(object): - def __init__(self, first_argument): - """one argument function""" - -class Class3Arg(object): - def __init__(self, first_argument, second_argument, third_argument): - """three arguments function""" - -class ClassDefaultArg(object): - def __init__(self, one=1, two=2): - """function with default value""" - -class Subclass1Arg(Class1Arg): - pass - -class ClassAllArgs(Class1Arg): - def __init__(self, *args, **kwargs): - pass - -class ClassMultiInheritance(Class1Arg, Class3Arg): - pass - -class ClassNew(object): - def __new__(cls, first_argument, kwarg=None): - return first_argument, kwarg - -Class1Arg(420) -Class1Arg() # [no-value-for-parameter] -Class1Arg(1337, 347) # [too-many-function-args] - -Class3Arg(420, 789) # [no-value-for-parameter] -# +1:[no-value-for-parameter,no-value-for-parameter,no-value-for-parameter] -Class3Arg() -Class3Arg(1337, 347, 456) -Class3Arg('bab', 'bebe', None, 5.6) # [too-many-function-args] - -ClassDefaultArg(1, two=5) -ClassDefaultArg(two=5) - -Class1Arg(bob=4) # [no-value-for-parameter,unexpected-keyword-arg] -ClassDefaultArg(1, 4, coin="hello") # [unexpected-keyword-arg] - -ClassDefaultArg(1, one=5) # [redundant-keyword-arg] - -Subclass1Arg(420) -Subclass1Arg() # [no-value-for-parameter] -Subclass1Arg(1337, 347) # [too-many-function-args] - -ClassAllArgs() -ClassAllArgs(1, 2, 3, even=4, more=5) - -ClassMultiInheritance(1) -ClassMultiInheritance(1, 2, 3) # [too-many-function-args] - -ClassNew(1, kwarg=1) -ClassNew(1, 2, 3) # [too-many-function-args] -ClassNew(one=2) # [no-value-for-parameter,unexpected-keyword-arg] - - -class Metaclass(type): - def __new__(mcs, name, bases, namespace): - return type.__new__(mcs, name, bases, namespace) - -def with_metaclass(meta, base=object): - """Create a new type that can be used as a metaclass.""" - return meta("NewBase", (base, ), {}) - -class ClassWithMeta(with_metaclass(Metaclass)): - pass - -ClassWithMeta() - - -class BuiltinExc(Exception): - def __init__(self, val=True): - self.val = val - -BuiltinExc(42, 24, badarg=1) # [too-many-function-args,unexpected-keyword-arg] - - -class Clsmethod(object): - def __init__(self, first, second): - self.first = first - self.second = second - - @classmethod - def from_nothing(cls): - return cls(1, 2, 3, 4) # [too-many-function-args] - - @classmethod - def from_nothing1(cls): - return cls() # [no-value-for-parameter,no-value-for-parameter] - - @classmethod - def from_nothing2(cls): - # +1: [no-value-for-parameter,unexpected-keyword-arg] - return cls(1, not_argument=2) diff --git a/pymode/libs/pylint/test/functional/ctor_arguments.txt b/pymode/libs/pylint/test/functional/ctor_arguments.txt deleted file mode 100644 index 639e92ce..00000000 --- a/pymode/libs/pylint/test/functional/ctor_arguments.txt +++ /dev/null @@ -1,24 +0,0 @@ -no-value-for-parameter:35::No value for argument 'first_argument' in constructor call -too-many-function-args:36::Too many positional arguments for constructor call -no-value-for-parameter:38::No value for argument 'third_argument' in constructor call -no-value-for-parameter:40::No value for argument 'first_argument' in constructor call -no-value-for-parameter:40::No value for argument 'second_argument' in constructor call -no-value-for-parameter:40::No value for argument 'third_argument' in constructor call -too-many-function-args:42::Too many positional arguments for constructor call -no-value-for-parameter:47::No value for argument 'first_argument' in constructor call -unexpected-keyword-arg:47::Unexpected keyword argument 'bob' in constructor call -unexpected-keyword-arg:48::Unexpected keyword argument 'coin' in constructor call -redundant-keyword-arg:50::Argument 'one' passed by position and keyword in constructor call -no-value-for-parameter:53::No value for argument 'first_argument' in constructor call -too-many-function-args:54::Too many positional arguments for constructor call -too-many-function-args:60::Too many positional arguments for constructor call -too-many-function-args:63::Too many positional arguments for constructor call -no-value-for-parameter:64::No value for argument 'first_argument' in constructor call -unexpected-keyword-arg:64::Unexpected keyword argument 'one' in constructor call -too-many-function-args:85::Too many positional arguments for constructor call -unexpected-keyword-arg:85::Unexpected keyword argument 'badarg' in constructor call -too-many-function-args:95:Clsmethod.from_nothing:Too many positional arguments for constructor call -no-value-for-parameter:99:Clsmethod.from_nothing1:"No value for argument 'first' in constructor call" -no-value-for-parameter:99:Clsmethod.from_nothing1:"No value for argument 'second' in constructor call" -no-value-for-parameter:104:Clsmethod.from_nothing2:"No value for argument 'second' in constructor call" -unexpected-keyword-arg:104:Clsmethod.from_nothing2:"Unexpected keyword argument 'not_argument' in constructor call" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value.py b/pymode/libs/pylint/test/functional/dangerous_default_value.py deleted file mode 100644 index 58a22f44..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value.py +++ /dev/null @@ -1,79 +0,0 @@ -# pylint: disable=missing-docstring - - -HEHE = {} - -def function1(value=[]): # [dangerous-default-value] - """docstring""" - return value - -def function2(value=HEHE): # [dangerous-default-value] - """docstring""" - return value - -def function3(value): - """docstring""" - return value - -def function4(value=set()): # [dangerous-default-value] - """set is mutable and dangerous.""" - return value - -def function5(value=frozenset()): - """frozenset is immutable and safe.""" - return value - -GLOBAL_SET = set() - -def function6(value=GLOBAL_SET): # [dangerous-default-value] - """set is mutable and dangerous.""" - return value - -def function7(value=dict()): # [dangerous-default-value] - """dict is mutable and dangerous.""" - return value - -def function8(value=list()): # [dangerous-default-value] - """list is mutable and dangerous.""" - return value - -def function9(value=[1, 2, 3, 4]): # [dangerous-default-value] - """list with items should not output item values in error message""" - return value - -def function10(value={'a': 1, 'b': 2}): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -def function11(value=list([1, 2, 3])): # [dangerous-default-value] - """list with items should not output item values in error message""" - return value - -def function12(value=dict([('a', 1), ('b', 2)])): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -OINK = { - 'a': 1, - 'b': 2 -} - -def function13(value=OINK): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -def function14(value=dict([(1, 2), (1, 2, 3)])): # [dangerous-default-value] - """a dictionary which will not be inferred to a syntax AST, but to an - astroid.Instance. - """ - return value - -INVALID_DICT = dict([(1, 2), (1, 2, 3)]) - -def function15(value=INVALID_DICT): # [dangerous-default-value] - """The same situation as function14.""" - return value - -def function16(value={1}): # [dangerous-default-value] - """set literal as default value""" - return value diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value.rc b/pymode/libs/pylint/test/functional/dangerous_default_value.rc deleted file mode 100644 index b11e16d5..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value.txt b/pymode/libs/pylint/test/functional/dangerous_default_value.txt deleted file mode 100644 index 92180e90..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value.txt +++ /dev/null @@ -1,14 +0,0 @@ -dangerous-default-value:6:function1:Dangerous default value [] as argument -dangerous-default-value:10:function2:Dangerous default value HEHE (__builtin__.dict) as argument -dangerous-default-value:18:function4:Dangerous default value set() (__builtin__.set) as argument -dangerous-default-value:28:function6:Dangerous default value GLOBAL_SET (__builtin__.set) as argument -dangerous-default-value:32:function7:Dangerous default value dict() (__builtin__.dict) as argument -dangerous-default-value:36:function8:Dangerous default value list() (__builtin__.list) as argument -dangerous-default-value:40:function9:Dangerous default value [] as argument -dangerous-default-value:44:function10:Dangerous default value {} as argument -dangerous-default-value:48:function11:Dangerous default value list() (__builtin__.list) as argument -dangerous-default-value:52:function12:Dangerous default value dict() (__builtin__.dict) as argument -dangerous-default-value:61:function13:Dangerous default value OINK (__builtin__.dict) as argument -dangerous-default-value:65:function14:Dangerous default value dict() (__builtin__.dict) as argument -dangerous-default-value:73:function15:Dangerous default value INVALID_DICT (__builtin__.dict) as argument -dangerous-default-value:77:function16:Dangerous default value set() as argument diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.py b/pymode/libs/pylint/test/functional/dangerous_default_value_py30.py deleted file mode 100644 index 58a22f44..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.py +++ /dev/null @@ -1,79 +0,0 @@ -# pylint: disable=missing-docstring - - -HEHE = {} - -def function1(value=[]): # [dangerous-default-value] - """docstring""" - return value - -def function2(value=HEHE): # [dangerous-default-value] - """docstring""" - return value - -def function3(value): - """docstring""" - return value - -def function4(value=set()): # [dangerous-default-value] - """set is mutable and dangerous.""" - return value - -def function5(value=frozenset()): - """frozenset is immutable and safe.""" - return value - -GLOBAL_SET = set() - -def function6(value=GLOBAL_SET): # [dangerous-default-value] - """set is mutable and dangerous.""" - return value - -def function7(value=dict()): # [dangerous-default-value] - """dict is mutable and dangerous.""" - return value - -def function8(value=list()): # [dangerous-default-value] - """list is mutable and dangerous.""" - return value - -def function9(value=[1, 2, 3, 4]): # [dangerous-default-value] - """list with items should not output item values in error message""" - return value - -def function10(value={'a': 1, 'b': 2}): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -def function11(value=list([1, 2, 3])): # [dangerous-default-value] - """list with items should not output item values in error message""" - return value - -def function12(value=dict([('a', 1), ('b', 2)])): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -OINK = { - 'a': 1, - 'b': 2 -} - -def function13(value=OINK): # [dangerous-default-value] - """dictionaries with items should not output item values in error message""" - return value - -def function14(value=dict([(1, 2), (1, 2, 3)])): # [dangerous-default-value] - """a dictionary which will not be inferred to a syntax AST, but to an - astroid.Instance. - """ - return value - -INVALID_DICT = dict([(1, 2), (1, 2, 3)]) - -def function15(value=INVALID_DICT): # [dangerous-default-value] - """The same situation as function14.""" - return value - -def function16(value={1}): # [dangerous-default-value] - """set literal as default value""" - return value diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.rc b/pymode/libs/pylint/test/functional/dangerous_default_value_py30.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.txt b/pymode/libs/pylint/test/functional/dangerous_default_value_py30.txt deleted file mode 100644 index 7571c00f..00000000 --- a/pymode/libs/pylint/test/functional/dangerous_default_value_py30.txt +++ /dev/null @@ -1,14 +0,0 @@ -dangerous-default-value:6:function1:Dangerous default value [] as argument -dangerous-default-value:10:function2:Dangerous default value HEHE (builtins.dict) as argument -dangerous-default-value:18:function4:Dangerous default value set() (builtins.set) as argument -dangerous-default-value:28:function6:Dangerous default value GLOBAL_SET (builtins.set) as argument -dangerous-default-value:32:function7:Dangerous default value dict() (builtins.dict) as argument -dangerous-default-value:36:function8:Dangerous default value list() (builtins.list) as argument -dangerous-default-value:40:function9:Dangerous default value [] as argument -dangerous-default-value:44:function10:Dangerous default value {} as argument -dangerous-default-value:48:function11:Dangerous default value list() (builtins.list) as argument -dangerous-default-value:52:function12:Dangerous default value dict() (builtins.dict) as argument -dangerous-default-value:61:function13:Dangerous default value OINK (builtins.dict) as argument -dangerous-default-value:65:function14:Dangerous default value dict() (builtins.dict) as argument -dangerous-default-value:73:function15:Dangerous default value INVALID_DICT (builtins.dict) as argument -dangerous-default-value:77:function16:Dangerous default value set() as argument \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/defined_and_used_on_same_line.py b/pymode/libs/pylint/test/functional/defined_and_used_on_same_line.py deleted file mode 100644 index a61bcd76..00000000 --- a/pymode/libs/pylint/test/functional/defined_and_used_on_same_line.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Check for definitions and usage happening on the same line.""" -#pylint: disable=missing-docstring,multiple-statements,no-absolute-import,parameter-unpacking,wrong-import-position -from __future__ import print_function -print([index - for index in range(10)]) - -print((index - for index in range(10))) - -FILTER_FUNC = lambda x: not x - -def func(xxx): return xxx - -def func2(xxx): return xxx + func2(1) - -import sys; print(sys.exc_info()) - -for i in range(10): print(i) - -j = 4; LAMB = lambda x: x+j - -FUNC4 = lambda a, b: a != b - -# test http://www.logilab.org/ticket/6954: - -with open('f') as f: print(f.read()) - -with open('f') as f, open(f.read()) as g: - print(g.read()) diff --git a/pymode/libs/pylint/test/functional/deprecated_lambda.py b/pymode/libs/pylint/test/functional/deprecated_lambda.py deleted file mode 100644 index 807a00fe..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_lambda.py +++ /dev/null @@ -1,23 +0,0 @@ -# pylint: disable=missing-docstring,invalid-name,no-absolute-import - -import functools - -# Don't do this, use a comprehension instead. -assert map(lambda x: x*2, [1, 2, 3]) == [2, 4, 6] # [deprecated-lambda] - -assert filter(lambda x: x != 1, [1, 2, 3]) == [2, 3] # [deprecated-lambda] - -# It's still ok to use map and filter with anything but an inline lambda. -double = lambda x: x * 2 -assert map(double, [1, 2, 3]) == [2, 4, 6] - -# It's also ok to pass lambdas to other functions. -assert functools.reduce(lambda x, y: x * y, [1, 2, 3, 4]) == 24 - -# Or to a undefined function or one with varargs -def f(*a): - return len(a) - -f(lambda x, y: x + y, [1, 2, 3]) - -undefined_function(lambda: 2) # pylint: disable=undefined-variable diff --git a/pymode/libs/pylint/test/functional/deprecated_lambda.rc b/pymode/libs/pylint/test/functional/deprecated_lambda.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_lambda.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/deprecated_lambda.txt b/pymode/libs/pylint/test/functional/deprecated_lambda.txt deleted file mode 100644 index 78cd9fbf..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_lambda.txt +++ /dev/null @@ -1,2 +0,0 @@ -deprecated-lambda:6::map/filter on lambda could be replaced by comprehension -deprecated-lambda:8::map/filter on lambda could be replaced by comprehension diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py2.py b/pymode/libs/pylint/test/functional/deprecated_methods_py2.py deleted file mode 100644 index ceba1e4f..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py2.py +++ /dev/null @@ -1,9 +0,0 @@ -""" Functional test for deprecated methods in Python 2 """ -# pylint: disable=no-member -import os -import xml.etree.ElementTree - -os.popen2('') # [deprecated-method] -os.popen3('') # [deprecated-method] -os.popen4('') # [deprecated-method] -xml.etree.ElementTree.Element('elem').getchildren() # [deprecated-method] diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py2.rc b/pymode/libs/pylint/test/functional/deprecated_methods_py2.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py2.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py2.txt b/pymode/libs/pylint/test/functional/deprecated_methods_py2.txt deleted file mode 100644 index e1038185..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py2.txt +++ /dev/null @@ -1,4 +0,0 @@ -deprecated-method:6::Using deprecated method popen2() -deprecated-method:7::Using deprecated method popen3() -deprecated-method:8::Using deprecated method popen4() -deprecated-method:9::Using deprecated method getchildren() diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py3.py b/pymode/libs/pylint/test/functional/deprecated_methods_py3.py deleted file mode 100644 index 3e2897f4..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py3.py +++ /dev/null @@ -1,37 +0,0 @@ -""" Functional tests for method deprecation. """ -# pylint: disable=missing-docstring, super-init-not-called, not-callable -import base64 -import cgi -import inspect -import logging -import nntplib -import platform -import unittest -import xml.etree.ElementTree - - -class MyTest(unittest.TestCase): - def test(self): - self.assert_(True) # [deprecated-method] - -xml.etree.ElementTree.Element('tag').getchildren() # [deprecated-method] -xml.etree.ElementTree.Element('tag').getiterator() # [deprecated-method] -xml.etree.ElementTree.XMLParser('tag', None, None).doctype(None, None, None) # [deprecated-method] -nntplib.NNTP(None).xpath(None) # [deprecated-method] -inspect.getmoduleinfo(inspect) # [deprecated-method] - -inspect.getargspec(None) # [deprecated-method] -logging.warn("a") # [deprecated-method] -platform.popen([]) # [deprecated-method] -base64.encodestring("42") # [deprecated-method] -base64.decodestring("42") # [deprecated-method] -cgi.escape("a") # [deprecated-method] - - -class SuperCrash(unittest.TestCase): - - def __init__(self): - # should not crash. - super(SuperCrash, self)() - -xml.etree.ElementTree.iterparse(None) diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py3.rc b/pymode/libs/pylint/test/functional/deprecated_methods_py3.rc deleted file mode 100644 index 28c99bc2..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.3 diff --git a/pymode/libs/pylint/test/functional/deprecated_methods_py3.txt b/pymode/libs/pylint/test/functional/deprecated_methods_py3.txt deleted file mode 100644 index 972b97b6..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_methods_py3.txt +++ /dev/null @@ -1,12 +0,0 @@ -deprecated-method:15:MyTest.test:Using deprecated method assert_() -deprecated-method:17::Using deprecated method getchildren() -deprecated-method:18::Using deprecated method getiterator() -deprecated-method:19::Using deprecated method doctype() -deprecated-method:20::Using deprecated method xpath() -deprecated-method:21::Using deprecated method getmoduleinfo() -deprecated-method:23::Using deprecated method getargspec() -deprecated-method:24::Using deprecated method warn() -deprecated-method:25::Using deprecated method popen() -deprecated-method:26::Using deprecated method encodestring() -deprecated-method:27::Using deprecated method decodestring() -deprecated-method:28::Using deprecated method escape() diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py2.py b/pymode/libs/pylint/test/functional/deprecated_module_py2.py deleted file mode 100644 index b0d18654..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py2.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Test deprecated modules.""" -# pylint: disable=unused-import,no-name-in-module,import-error,ungrouped-imports - -import Bastion # [deprecated-module] -import rexec # [deprecated-module] - -from Bastion import bastion_module # [deprecated-module] -from rexec import rexec_module # [deprecated-module] diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py2.rc b/pymode/libs/pylint/test/functional/deprecated_module_py2.rc deleted file mode 100644 index 41315d22..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py2.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -max_pyver=3.0 -except_implementations=Jython \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py2.txt b/pymode/libs/pylint/test/functional/deprecated_module_py2.txt deleted file mode 100644 index 54f55550..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py2.txt +++ /dev/null @@ -1,4 +0,0 @@ -deprecated-module:4::Uses of a deprecated module 'Bastion' -deprecated-module:5::Uses of a deprecated module 'rexec' -deprecated-module:7::Uses of a deprecated module 'Bastion' -deprecated-module:8::Uses of a deprecated module 'rexec' diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py3.py b/pymode/libs/pylint/test/functional/deprecated_module_py3.py deleted file mode 100644 index 308d400e..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py3.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Test deprecated modules.""" -# pylint: disable=unused-import - -import optparse # [deprecated-module] diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py3.rc b/pymode/libs/pylint/test/functional/deprecated_module_py3.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py3.txt b/pymode/libs/pylint/test/functional/deprecated_module_py3.txt deleted file mode 100644 index c41bf3b6..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py3.txt +++ /dev/null @@ -1 +0,0 @@ -deprecated-module:4::Uses of a deprecated module 'optparse' diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py4.py b/pymode/libs/pylint/test/functional/deprecated_module_py4.py deleted file mode 100644 index 3cad959e..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py4.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Test deprecated modules.""" - -from deprecated import foo # [deprecated-module] -import deprecated # [deprecated-module] diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py4.rc b/pymode/libs/pylint/test/functional/deprecated_module_py4.rc deleted file mode 100644 index 6fbd3407..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py4.rc +++ /dev/null @@ -1,4 +0,0 @@ -[Messages Control] -deprecated-modules=deprecated -disable=all -enable=deprecated-module diff --git a/pymode/libs/pylint/test/functional/deprecated_module_py4.txt b/pymode/libs/pylint/test/functional/deprecated_module_py4.txt deleted file mode 100644 index 74062f7b..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_py4.txt +++ /dev/null @@ -1,2 +0,0 @@ -deprecated-module:3::Uses of a deprecated module 'deprecated' -deprecated-module:4::Uses of a deprecated module 'deprecated' diff --git a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.py b/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.py deleted file mode 100644 index 52d55fa8..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Test deprecated modules uninstalled.""" -# pylint: disable=unused-import,no-name-in-module,import-error - -from uninstalled import uninstalled_module # [deprecated-module] -import uninstalled # [deprecated-module] diff --git a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.rc b/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.rc deleted file mode 100644 index 05973daa..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.rc +++ /dev/null @@ -1,2 +0,0 @@ -[Messages Control] -deprecated-modules=uninstalled \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.txt b/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.txt deleted file mode 100644 index 6f14ddd2..00000000 --- a/pymode/libs/pylint/test/functional/deprecated_module_uninstalled.txt +++ /dev/null @@ -1,2 +0,0 @@ -deprecated-module:4::Uses of a deprecated module 'uninstalled' -deprecated-module:5::Uses of a deprecated module 'uninstalled' diff --git a/pymode/libs/pylint/test/functional/docstrings.py b/pymode/libs/pylint/test/functional/docstrings.py deleted file mode 100644 index 142809b0..00000000 --- a/pymode/libs/pylint/test/functional/docstrings.py +++ /dev/null @@ -1,83 +0,0 @@ -# pylint: disable=R0201 -# -1: [missing-docstring] -from __future__ import print_function - -# +1: [empty-docstring] -def function0(): - """""" - -# +1: [missing-docstring] -def function1(value): - # missing docstring - print(value) - -def function2(value): - """docstring""" - print(value) - -def function3(value): - """docstring""" - print(value) - -# +1: [missing-docstring] -class AAAA(object): - # missing docstring - -## class BBBB: -## # missing docstring -## pass - -## class CCCC: -## """yeah !""" -## def method1(self): -## pass - -## def method2(self): -## """ yeah !""" -## pass - - # +1: [missing-docstring] - def method1(self): - pass - - def method2(self): - """ yeah !""" - pass - - # +1: [empty-docstring] - def method3(self): - """""" - pass - - def __init__(self): - pass - -class DDDD(AAAA): - """yeah !""" - - def __init__(self): - AAAA.__init__(self) - - # +1: [empty-docstring] - def method2(self): - """""" - pass - - def method3(self): - pass - - # +1: [missing-docstring] - def method4(self): - pass - -# pylint: disable=missing-docstring -def function4(): - pass - -# pylint: disable=empty-docstring -def function5(): - """""" - pass - -def function6(): - """ I am a {} docstring.""".format("good") diff --git a/pymode/libs/pylint/test/functional/docstrings.txt b/pymode/libs/pylint/test/functional/docstrings.txt deleted file mode 100644 index e30e4629..00000000 --- a/pymode/libs/pylint/test/functional/docstrings.txt +++ /dev/null @@ -1,8 +0,0 @@ -missing-docstring:1::Missing module docstring -empty-docstring:6:function0:Empty function docstring -missing-docstring:10:function1:Missing function docstring -missing-docstring:23:AAAA:Missing class docstring -missing-docstring:40:AAAA.method1:Missing method docstring:INFERENCE -empty-docstring:48:AAAA.method3:Empty method docstring:INFERENCE -empty-docstring:62:DDDD.method2:Empty method docstring:INFERENCE -missing-docstring:70:DDDD.method4:Missing method docstring:INFERENCE diff --git a/pymode/libs/pylint/test/functional/duplicate_argument_name.py b/pymode/libs/pylint/test/functional/duplicate_argument_name.py deleted file mode 100644 index 2b939ed5..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_argument_name.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Check for duplicate function arguments.""" - - -def foo1(_, _): # [duplicate-argument-name] - """Function with duplicate argument name.""" - -def foo2(_, *_): # [duplicate-argument-name] - """Function with duplicate argument name.""" - -def foo3(_, _=3): # [duplicate-argument-name] - """Function with duplicate argument name.""" diff --git a/pymode/libs/pylint/test/functional/duplicate_argument_name.txt b/pymode/libs/pylint/test/functional/duplicate_argument_name.txt deleted file mode 100644 index c51e4dfc..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_argument_name.txt +++ /dev/null @@ -1,3 +0,0 @@ -duplicate-argument-name:4:foo1:Duplicate argument name _ in function definition -duplicate-argument-name:7:foo2:Duplicate argument name _ in function definition -duplicate-argument-name:10:foo3:Duplicate argument name _ in function definition diff --git a/pymode/libs/pylint/test/functional/duplicate_bases.py b/pymode/libs/pylint/test/functional/duplicate_bases.py deleted file mode 100644 index 9088e53c..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_bases.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Test duplicate bases error.""" -# pylint: disable=missing-docstring,too-few-public-methods,no-init - - -class Duplicates(str, str): # [duplicate-bases] - pass - - -class Alpha(str): - pass - - -class NotDuplicates(Alpha, str): - """The error should not be emitted for this case, since the - other same base comes from the ancestors.""" diff --git a/pymode/libs/pylint/test/functional/duplicate_bases.txt b/pymode/libs/pylint/test/functional/duplicate_bases.txt deleted file mode 100644 index beb91b53..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_bases.txt +++ /dev/null @@ -1 +0,0 @@ -duplicate-bases:5:Duplicates:Duplicate bases for class 'Duplicates' \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.py b/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.py deleted file mode 100644 index 3fae8b7e..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Check multiple key definition""" -# pylint: disable=C0103 - -correct_dict = { - 'tea': 'for two', - 'two': 'for tea', -} - -wrong_dict = { # [duplicate-key] - 'tea': 'for two', - 'two': 'for tea', - 'tea': 'time', - -} diff --git a/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.txt b/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.txt deleted file mode 100644 index 97804800..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_dict_literal_key.txt +++ /dev/null @@ -1 +0,0 @@ -duplicate-key:9::Duplicate key 'tea' in dictionary diff --git a/pymode/libs/pylint/test/functional/duplicate_except.py b/pymode/libs/pylint/test/functional/duplicate_except.py deleted file mode 100644 index c68cf7a2..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_except.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Test for duplicate-check.""" - -def main(): - """The second ValueError should be flagged.""" - try: - raise ValueError('test') - except ValueError: - return 1 - except ValueError: # [duplicate-except] - return 2 - except (OSError, TypeError): - return 3 diff --git a/pymode/libs/pylint/test/functional/duplicate_except.txt b/pymode/libs/pylint/test/functional/duplicate_except.txt deleted file mode 100644 index a037948e..00000000 --- a/pymode/libs/pylint/test/functional/duplicate_except.txt +++ /dev/null @@ -1 +0,0 @@ -duplicate-except:9:main:Catching previously caught exception type ValueError diff --git a/pymode/libs/pylint/test/functional/eval_used.py b/pymode/libs/pylint/test/functional/eval_used.py deleted file mode 100644 index d03dad7c..00000000 --- a/pymode/libs/pylint/test/functional/eval_used.py +++ /dev/null @@ -1,10 +0,0 @@ -"""test for eval usage""" - -eval('os.listdir(".")') # [eval-used] -eval('os.listdir(".")', globals={}) # [eval-used] - -eval('os.listdir(".")', globals=globals()) # [eval-used] - -def func(): - """ eval in local scope""" - eval('b = 1') # [eval-used] diff --git a/pymode/libs/pylint/test/functional/eval_used.txt b/pymode/libs/pylint/test/functional/eval_used.txt deleted file mode 100644 index 6b1b078c..00000000 --- a/pymode/libs/pylint/test/functional/eval_used.txt +++ /dev/null @@ -1,4 +0,0 @@ -eval-used:3::Use of eval -eval-used:4::Use of eval -eval-used:6::Use of eval -eval-used:10:func:Use of eval \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/exception_is_binary_op.py b/pymode/libs/pylint/test/functional/exception_is_binary_op.py deleted file mode 100644 index f71163d1..00000000 --- a/pymode/libs/pylint/test/functional/exception_is_binary_op.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Warn about binary operations used as exceptions.""" -from __future__ import print_function -try: - pass -except Exception or BaseException: # [binary-op-exception] - print("caught1") -except Exception and BaseException: # [binary-op-exception] - print("caught2") -except Exception or BaseException: # [binary-op-exception] - print("caught3") -except (Exception or BaseException) as exc: # [binary-op-exception] - print("caught4") diff --git a/pymode/libs/pylint/test/functional/exception_is_binary_op.txt b/pymode/libs/pylint/test/functional/exception_is_binary_op.txt deleted file mode 100644 index e6512c96..00000000 --- a/pymode/libs/pylint/test/functional/exception_is_binary_op.txt +++ /dev/null @@ -1,4 +0,0 @@ -binary-op-exception:5::"Exception to catch is the result of a binary ""or"" operation" -binary-op-exception:7::"Exception to catch is the result of a binary ""and"" operation" -binary-op-exception:9::"Exception to catch is the result of a binary ""or"" operation" -binary-op-exception:11::"Exception to catch is the result of a binary ""or"" operation" diff --git a/pymode/libs/pylint/test/functional/exec_used_py2.py b/pymode/libs/pylint/test/functional/exec_used_py2.py deleted file mode 100644 index 8f7f07d9..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py2.py +++ /dev/null @@ -1,10 +0,0 @@ -# pylint: disable=missing-docstring - -exec 'a = __revision__' # [exec-used] -VALUES = {} -exec 'a = 1' in VALUES # [exec-used] - -exec 'a = 1' in globals() # [exec-used] - -def func(): - exec 'b = 1' # [exec-used] diff --git a/pymode/libs/pylint/test/functional/exec_used_py2.rc b/pymode/libs/pylint/test/functional/exec_used_py2.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py2.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/exec_used_py2.txt b/pymode/libs/pylint/test/functional/exec_used_py2.txt deleted file mode 100644 index a7e10509..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py2.txt +++ /dev/null @@ -1,4 +0,0 @@ -exec-used:3::Use of exec -exec-used:5::Use of exec -exec-used:7::Use of exec -exec-used:10:func:Use of exec \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/exec_used_py3.py b/pymode/libs/pylint/test/functional/exec_used_py3.py deleted file mode 100644 index 5f849480..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py3.py +++ /dev/null @@ -1,9 +0,0 @@ -# pylint: disable=missing-docstring - -exec('a = __revision__') # [exec-used] -exec('a = 1', globals={}) # [exec-used] - -exec('a = 1', globals=globals()) # [exec-used] - -def func(): - exec('b = 1') # [exec-used] diff --git a/pymode/libs/pylint/test/functional/exec_used_py3.rc b/pymode/libs/pylint/test/functional/exec_used_py3.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/exec_used_py3.txt b/pymode/libs/pylint/test/functional/exec_used_py3.txt deleted file mode 100644 index c19ee947..00000000 --- a/pymode/libs/pylint/test/functional/exec_used_py3.txt +++ /dev/null @@ -1,4 +0,0 @@ -exec-used:3::Use of exec -exec-used:4::Use of exec -exec-used:6::Use of exec -exec-used:9:func:Use of exec \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/fallback_import_disabled.py b/pymode/libs/pylint/test/functional/fallback_import_disabled.py deleted file mode 100644 index 321eb115..00000000 --- a/pymode/libs/pylint/test/functional/fallback_import_disabled.py +++ /dev/null @@ -1,10 +0,0 @@ -# pylint: disable=missing-docstring,unused-import -try: - import urllib2 as urllib_request #@ - import urllib2 as urllib_error - from urlparse import urlparse -except ImportError: - # python2 - from urllib import request as urllib_request - from urllib import error as urllib_error - from urllib.parse import urlparseq diff --git a/pymode/libs/pylint/test/functional/fallback_import_disabled.txt b/pymode/libs/pylint/test/functional/fallback_import_disabled.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/functional/fallback_import_enabled.py b/pymode/libs/pylint/test/functional/fallback_import_enabled.py deleted file mode 100644 index 9420830f..00000000 --- a/pymode/libs/pylint/test/functional/fallback_import_enabled.py +++ /dev/null @@ -1,5 +0,0 @@ -# pylint: disable=missing-docstring,unused-import -try: - import collections.missing # [no-name-in-module] -except ImportError: - from collections import missing # [no-name-in-module] diff --git a/pymode/libs/pylint/test/functional/fallback_import_enabled.rc b/pymode/libs/pylint/test/functional/fallback_import_enabled.rc deleted file mode 100644 index 204ce11b..00000000 --- a/pymode/libs/pylint/test/functional/fallback_import_enabled.rc +++ /dev/null @@ -1,2 +0,0 @@ -[IMPORTS] -analyse-fallback-blocks=yes \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/fallback_import_enabled.txt b/pymode/libs/pylint/test/functional/fallback_import_enabled.txt deleted file mode 100644 index e795b82c..00000000 --- a/pymode/libs/pylint/test/functional/fallback_import_enabled.txt +++ /dev/null @@ -1,2 +0,0 @@ -no-name-in-module:3::No name 'missing' in module 'collections' -no-name-in-module:5::No name 'missing' in module 'collections' \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/fixme.py b/pymode/libs/pylint/test/functional/fixme.py deleted file mode 100644 index 9d5d966b..00000000 --- a/pymode/libs/pylint/test/functional/fixme.py +++ /dev/null @@ -1,18 +0,0 @@ -# pylint: disable=missing-docstring, unused-variable - - -# +1: [fixme] -# FIXME: beep - - -def function(): - variable = "FIXME: Ignore me!" - # +1: [fixme] - test = "text" # FIXME: Valid test - - # +1: [fixme] - # TODO: Do something with the variables - # +1: [fixme] - xxx = "n/a" # XXX: Fix this later - # +1: [fixme] - #FIXME: no space after hash diff --git a/pymode/libs/pylint/test/functional/fixme.txt b/pymode/libs/pylint/test/functional/fixme.txt deleted file mode 100644 index 581788ae..00000000 --- a/pymode/libs/pylint/test/functional/fixme.txt +++ /dev/null @@ -1,5 +0,0 @@ -fixme:5::"FIXME: beep" -fixme:11::"FIXME: Valid test" -fixme:14::"TODO: Do something with the variables" -fixme:16::"XXX: Fix this later" -fixme:18::"FIXME: no space after hash" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/formatting.txt b/pymode/libs/pylint/test/functional/formatting.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/functional/function_redefined.py b/pymode/libs/pylint/test/functional/function_redefined.py deleted file mode 100644 index d043cb00..00000000 --- a/pymode/libs/pylint/test/functional/function_redefined.py +++ /dev/null @@ -1,74 +0,0 @@ -# pylint: disable=R0201,missing-docstring,using-constant-test -from __future__ import division -__revision__ = '' - -class AAAA(object): - """docstring""" - def __init__(self): - pass - def method1(self): - """docstring""" - - def method2(self): - """docstring""" - - def method2(self): # [function-redefined] - """docstring""" - -class AAAA(object): # [function-redefined] - """docstring""" - def __init__(self): - pass - def yeah(self): - """hehehe""" - def yoo(self): - """yoo""" -def func1(): - """docstring""" - -def func2(): - """docstring""" - -def func2(): # [function-redefined] - """docstring""" - __revision__ = 1 # [redefined-outer-name] - return __revision__ - -if __revision__: - def exclusive_func(): - "docstring" -else: - def exclusive_func(): - "docstring" - -try: - def exclusive_func2(): - "docstring" -except TypeError: - def exclusive_func2(): - "docstring" -else: - def exclusive_func2(): # [function-redefined] - "this one redefine the one defined line 42" - - -def with_inner_function_1(): - """docstring""" - def callback(): - """callback docstring""" - pass - return callback - -def with_inner_function_2(): - """docstring""" - def callback(): - """does not redefine callback returned by with_inner_function_1""" - pass - return callback - -def some_func(): - """Don't emit if we defined a variable with the same name as a - __future__ directive. - """ - division = 2 - return division diff --git a/pymode/libs/pylint/test/functional/function_redefined.txt b/pymode/libs/pylint/test/functional/function_redefined.txt deleted file mode 100644 index 56fabc5e..00000000 --- a/pymode/libs/pylint/test/functional/function_redefined.txt +++ /dev/null @@ -1,5 +0,0 @@ -function-redefined:15:AAAA.method2:method already defined line 12 -function-redefined:18:AAAA:class already defined line 5 -function-redefined:32:func2:function already defined line 29 -redefined-outer-name:34:func2:Redefining name '__revision__' from outer scope (line 3) -function-redefined:51:exclusive_func2:function already defined line 45 diff --git a/pymode/libs/pylint/test/functional/future_import.py b/pymode/libs/pylint/test/functional/future_import.py deleted file mode 100644 index e4d3785a..00000000 --- a/pymode/libs/pylint/test/functional/future_import.py +++ /dev/null @@ -1,3 +0,0 @@ -"""a docstring""" - -from __future__ import generators diff --git a/pymode/libs/pylint/test/functional/future_unicode_literals.py b/pymode/libs/pylint/test/functional/future_unicode_literals.py deleted file mode 100644 index 30c2bd6b..00000000 --- a/pymode/libs/pylint/test/functional/future_unicode_literals.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Unicode literals in Python 2.*""" -from __future__ import unicode_literals - - -BAD_STRING = b'\u1234' # >= 2.7.4:[anomalous-unicode-escape-in-string] -GOOD_STRING = '\u1234' diff --git a/pymode/libs/pylint/test/functional/future_unicode_literals.rc b/pymode/libs/pylint/test/functional/future_unicode_literals.rc deleted file mode 100644 index eb52949d..00000000 --- a/pymode/libs/pylint/test/functional/future_unicode_literals.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -except_implementations=Jython \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/future_unicode_literals.txt b/pymode/libs/pylint/test/functional/future_unicode_literals.txt deleted file mode 100644 index 60d291e7..00000000 --- a/pymode/libs/pylint/test/functional/future_unicode_literals.txt +++ /dev/null @@ -1 +0,0 @@ -anomalous-unicode-escape-in-string:5::"Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix." diff --git a/pymode/libs/pylint/test/functional/generated_members.py b/pymode/libs/pylint/test/functional/generated_members.py deleted file mode 100644 index 529677c6..00000000 --- a/pymode/libs/pylint/test/functional/generated_members.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Test the generated-members config option.""" -# pylint: disable=pointless-statement -from __future__ import print_function -from astroid import node_classes -from pylint import checkers - -class Klass(object): - """A class with a generated member.""" - -print(Klass().DoesNotExist) -print(Klass().aBC_set1) -node_classes.Tuple.does.not_.exist -checkers.base.doesnotexist() diff --git a/pymode/libs/pylint/test/functional/generated_members.rc b/pymode/libs/pylint/test/functional/generated_members.rc deleted file mode 100644 index 2d750958..00000000 --- a/pymode/libs/pylint/test/functional/generated_members.rc +++ /dev/null @@ -1,5 +0,0 @@ -[Messages Control] -disable=too-few-public-methods,print-statement - -[typecheck] -generated-members=DoesNotExist,"[a-zA-Z]+_set{1,2}",node_classes.Tuple.*,checkers.*?base diff --git a/pymode/libs/pylint/test/functional/genexpr_variable_scope.py b/pymode/libs/pylint/test/functional/genexpr_variable_scope.py deleted file mode 100644 index a00d72d3..00000000 --- a/pymode/libs/pylint/test/functional/genexpr_variable_scope.py +++ /dev/null @@ -1,5 +0,0 @@ -"""test name defined in generator expression are not available -outside the genexpr scope -""" -from __future__ import print_function -print(n) # [undefined-variable] diff --git a/pymode/libs/pylint/test/functional/genexpr_variable_scope.txt b/pymode/libs/pylint/test/functional/genexpr_variable_scope.txt deleted file mode 100644 index 3cfa6c5e..00000000 --- a/pymode/libs/pylint/test/functional/genexpr_variable_scope.txt +++ /dev/null @@ -1 +0,0 @@ -undefined-variable:5::Undefined variable 'n' diff --git a/pymode/libs/pylint/test/functional/globals.py b/pymode/libs/pylint/test/functional/globals.py deleted file mode 100644 index c2844b1f..00000000 --- a/pymode/libs/pylint/test/functional/globals.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Warnings about global statements and usage of global variables.""" -from __future__ import print_function - -global CSTE # [global-at-module-level] -print(CSTE) # [undefined-variable] - -CONSTANT = 1 - -def fix_contant(value): - """all this is ok, but try not using global ;)""" - global CONSTANT # [global-statement] - print(CONSTANT) - CONSTANT = value - - -def other(): - """global behaviour test""" - global HOP # [global-variable-not-assigned] - print(HOP) # [undefined-variable] - - -def define_constant(): - """ok but somevar is not defined at the module scope""" - global SOMEVAR # [global-variable-undefined] - SOMEVAR = 2 diff --git a/pymode/libs/pylint/test/functional/globals.txt b/pymode/libs/pylint/test/functional/globals.txt deleted file mode 100644 index c6759064..00000000 --- a/pymode/libs/pylint/test/functional/globals.txt +++ /dev/null @@ -1,6 +0,0 @@ -global-at-module-level:4::Using the global statement at the module level -undefined-variable:5::Undefined variable 'CSTE' -global-statement:11:fix_contant:Using the global statement -global-variable-not-assigned:18:other:Using global for 'HOP' but no assignment is done -undefined-variable:19:other:Undefined variable 'HOP' -global-variable-undefined:24:define_constant:Global variable 'SOMEVAR' undefined at the module level diff --git a/pymode/libs/pylint/test/functional/import_error.py b/pymode/libs/pylint/test/functional/import_error.py deleted file mode 100644 index b6f6aa2d..00000000 --- a/pymode/libs/pylint/test/functional/import_error.py +++ /dev/null @@ -1,27 +0,0 @@ -""" Test that import errors are detected. """ -# pylint: disable=invalid-name, unused-import, no-absolute-import, bare-except, broad-except, wrong-import-order, wrong-import-position -import totally_missing # [import-error] - -try: - import maybe_missing -except ImportError: - maybe_missing = None - -try: - import maybe_missing_1 -except (ImportError, SyntaxError): - maybe_missing_1 = None - -try: - import maybe_missing_2 # [import-error] -except ValueError: - maybe_missing_2 = None - - -try: - if maybe_missing: - import really_missing -except ImportError: - pass - -from .collections import missing # [import-error] diff --git a/pymode/libs/pylint/test/functional/import_error.txt b/pymode/libs/pylint/test/functional/import_error.txt deleted file mode 100644 index b8746e9d..00000000 --- a/pymode/libs/pylint/test/functional/import_error.txt +++ /dev/null @@ -1,3 +0,0 @@ -import-error:3::"Unable to import 'totally_missing'" -import-error:16::"Unable to import 'maybe_missing_2'" -import-error:27::"Unable to import 'functional.collections'" diff --git a/pymode/libs/pylint/test/functional/inconsistent_mro.py b/pymode/libs/pylint/test/functional/inconsistent_mro.py deleted file mode 100644 index 0ae67e40..00000000 --- a/pymode/libs/pylint/test/functional/inconsistent_mro.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Tests for inconsistent-mro.""" -# pylint: disable=missing-docstring,too-few-public-methods,no-init - -class Str(str): - pass - - -class Inconsistent(str, Str): # [inconsistent-mro] - pass diff --git a/pymode/libs/pylint/test/functional/inconsistent_mro.txt b/pymode/libs/pylint/test/functional/inconsistent_mro.txt deleted file mode 100644 index 1ae9687d..00000000 --- a/pymode/libs/pylint/test/functional/inconsistent_mro.txt +++ /dev/null @@ -1 +0,0 @@ -inconsistent-mro:8:Inconsistent:Inconsistent method resolution order for class 'Inconsistent' diff --git a/pymode/libs/pylint/test/functional/indexing_exception.py b/pymode/libs/pylint/test/functional/indexing_exception.py deleted file mode 100644 index 9ac1a7c6..00000000 --- a/pymode/libs/pylint/test/functional/indexing_exception.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Check for indexing exceptions. -""" -# pylint: disable=import-error, no-absolute-import - -from unknown import ExtensionException -__revision__ = 0 - -class SubException(IndexError): - """ empty """ - -_ = IndexError("test")[0] # [indexing-exception] -_ = ZeroDivisionError("error")[0] # [indexing-exception] -_ = ExtensionException("error")[0] -_ = SubException("error")[1] # [indexing-exception] diff --git a/pymode/libs/pylint/test/functional/indexing_exception.rc b/pymode/libs/pylint/test/functional/indexing_exception.rc deleted file mode 100644 index 9540bc95..00000000 --- a/pymode/libs/pylint/test/functional/indexing_exception.rc +++ /dev/null @@ -1,5 +0,0 @@ -[testoptions] -max_pyver=3.0 - -[Messages Control] -enable=python3 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/indexing_exception.txt b/pymode/libs/pylint/test/functional/indexing_exception.txt deleted file mode 100644 index 268e2602..00000000 --- a/pymode/libs/pylint/test/functional/indexing_exception.txt +++ /dev/null @@ -1,3 +0,0 @@ -indexing-exception:12::Indexing exceptions will not work on Python 3 -indexing-exception:13::Indexing exceptions will not work on Python 3 -indexing-exception:15::Indexing exceptions will not work on Python 3 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/inherit_non_class.py b/pymode/libs/pylint/test/functional/inherit_non_class.py deleted file mode 100644 index d0be4c11..00000000 --- a/pymode/libs/pylint/test/functional/inherit_non_class.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Test that inheriting from something which is not -a class emits a warning. """ - -# pylint: disable=no-init, import-error, invalid-name, using-constant-test -# pylint: disable=missing-docstring, too-few-public-methods, no-absolute-import - -from missing import Missing - -if 1: - Ambiguous = None -else: - Ambiguous = int - -class Empty(object): - """ Empty class. """ - -def return_class(): - """ Return a class. """ - return Good3 - -class Bad(1): # [inherit-non-class] - """ Can't inherit from instance. """ - -class Bad1(lambda abc: 42): # [inherit-non-class] - """ Can't inherit from lambda. """ - -class Bad2(object()): # [inherit-non-class] - """ Can't inherit from an instance of object. """ - -class Bad3(return_class): # [inherit-non-class] - """ Can't inherit from function. """ - -class Bad4(Empty()): # [inherit-non-class] - """ Can't inherit from instance. """ - -class Good(object): - pass - -class Good1(int): - pass - -class Good2(type): - pass - -class Good3(type(int)): - pass - -class Good4(return_class()): - pass - -class Good5(Good4, int, object): - pass - -class Good6(Ambiguous): - """ Inherits from something ambiguous. - - This could emit a warning when we will have - flow detection. - """ - -class Unknown(Missing): - pass - -class Unknown1(Good5 if True else Bad1): - pass - - -class NotInheritableBool(bool): # [inherit-non-class] - pass - - -class NotInheritableRange(range): # [inherit-non-class] - pass - - -class NotInheritableSlice(slice): # [inherit-non-class] - pass - - -class NotInheritableMemoryView(memoryview): # [inherit-non-class] - pass diff --git a/pymode/libs/pylint/test/functional/inherit_non_class.txt b/pymode/libs/pylint/test/functional/inherit_non_class.txt deleted file mode 100644 index 3be70cb9..00000000 --- a/pymode/libs/pylint/test/functional/inherit_non_class.txt +++ /dev/null @@ -1,9 +0,0 @@ -inherit-non-class:21:Bad:Inheriting '1', which is not a class. -inherit-non-class:24:Bad1:"Inheriting 'lambda abc: 42', which is not a class." -inherit-non-class:27:Bad2:Inheriting 'object()', which is not a class. -inherit-non-class:30:Bad3:Inheriting 'return_class', which is not a class. -inherit-non-class:33:Bad4:Inheriting 'Empty()', which is not a class. -inherit-non-class:68:NotInheritableBool:Inheriting 'bool', which is not a class. -inherit-non-class:72:NotInheritableRange:Inheriting 'range', which is not a class. -inherit-non-class:76:NotInheritableSlice:Inheriting 'slice', which is not a class. -inherit-non-class:80:NotInheritableMemoryView:Inheriting 'memoryview', which is not a class. \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/init_is_generator.py b/pymode/libs/pylint/test/functional/init_is_generator.py deleted file mode 100644 index 882200c7..00000000 --- a/pymode/libs/pylint/test/functional/init_is_generator.py +++ /dev/null @@ -1,5 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods - -class SomeClass(object): - def __init__(self): # [init-is-generator] - yield None diff --git a/pymode/libs/pylint/test/functional/init_is_generator.txt b/pymode/libs/pylint/test/functional/init_is_generator.txt deleted file mode 100644 index 5d2132a1..00000000 --- a/pymode/libs/pylint/test/functional/init_is_generator.txt +++ /dev/null @@ -1 +0,0 @@ -init-is-generator:4:SomeClass.__init__:__init__ method is a generator diff --git a/pymode/libs/pylint/test/functional/init_not_called.py b/pymode/libs/pylint/test/functional/init_not_called.py deleted file mode 100644 index 38c0f7a1..00000000 --- a/pymode/libs/pylint/test/functional/init_not_called.py +++ /dev/null @@ -1,64 +0,0 @@ -# pylint: disable=R0903,import-error,missing-docstring,wrong-import-position -"""test for __init__ not called -""" -from __future__ import print_function - -class AAAA: # <3.0:[old-style-class] - """ancestor 1""" - - def __init__(self): - print('init', self) - -class BBBB: # <3.0:[old-style-class] - """ancestor 2""" - - def __init__(self): - print('init', self) - -class CCCC: # <3.0:[old-style-class,no-init] - """ancestor 3""" - - -class ZZZZ(AAAA, BBBB, CCCC): - """derived class""" - - def __init__(self): # [super-init-not-called] - AAAA.__init__(self) - -class NewStyleA(object): - """new style class""" - def __init__(self): - super(NewStyleA, self).__init__() - print('init', self) - -class NewStyleB(NewStyleA): - """derived new style class""" - def __init__(self): - super(NewStyleB, self).__init__() - -class NoInit(object): - """No __init__ defined""" - -class Init(NoInit): - """Don't complain for not calling the super __init__""" - - def __init__(self, arg): - self.arg = arg - -class NewStyleC(object): - """__init__ defined by assignemnt.""" - def xx_init(self): - """Initializer.""" - pass - - __init__ = xx_init - -class AssignedInit(NewStyleC): - """No init called.""" - def __init__(self): # [super-init-not-called] - self.arg = 0 - -from missing import Missing - -class UnknownBases(Missing): - """Don't emit no-init if the bases aren't known.""" diff --git a/pymode/libs/pylint/test/functional/init_not_called.txt b/pymode/libs/pylint/test/functional/init_not_called.txt deleted file mode 100644 index b0bc4188..00000000 --- a/pymode/libs/pylint/test/functional/init_not_called.txt +++ /dev/null @@ -1,6 +0,0 @@ -old-style-class:6:AAAA:Old-style class defined. -old-style-class:12:BBBB:Old-style class defined. -no-init:18:CCCC:Class has no __init__ method -old-style-class:18:CCCC:Old-style class defined. -super-init-not-called:25:ZZZZ.__init__:__init__ method from base class 'BBBB' is not called -super-init-not-called:58:AssignedInit.__init__:__init__ method from base class 'NewStyleC' is not called diff --git a/pymode/libs/pylint/test/functional/invalid_all_object.py b/pymode/libs/pylint/test/functional/invalid_all_object.py deleted file mode 100644 index 729f0510..00000000 --- a/pymode/libs/pylint/test/functional/invalid_all_object.py +++ /dev/null @@ -1,6 +0,0 @@ -# pylint: disable=missing-docstring -__all__ = ( - 1, # [invalid-all-object] - lambda: None, # [invalid-all-object] - None, # [invalid-all-object] -) diff --git a/pymode/libs/pylint/test/functional/invalid_all_object.txt b/pymode/libs/pylint/test/functional/invalid_all_object.txt deleted file mode 100644 index d463f44b..00000000 --- a/pymode/libs/pylint/test/functional/invalid_all_object.txt +++ /dev/null @@ -1,3 +0,0 @@ -invalid-all-object:3::Invalid object '1' in __all__, must contain only strings -invalid-all-object:4::"Invalid object 'lambda : None' in __all__, must contain only strings" -invalid-all-object:5::Invalid object 'None' in __all__, must contain only strings \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/invalid_exceptions_caught.py b/pymode/libs/pylint/test/functional/invalid_exceptions_caught.py deleted file mode 100644 index 2d87239e..00000000 --- a/pymode/libs/pylint/test/functional/invalid_exceptions_caught.py +++ /dev/null @@ -1,123 +0,0 @@ -# pylint: disable=missing-docstring, too-few-public-methods -# pylint: disable=too-many-ancestors, no-absolute-import, import-error, multiple-imports,wrong-import-position -from __future__ import print_function - -import socket, binascii, abc, six - -class MyException(object): - """Custom 'exception'.""" - -class MySecondException(object): - """Custom 'exception'.""" - -class MyGoodException(Exception): - """Custom exception.""" - -class MySecondGoodException(MyGoodException): - """Custom exception.""" - -class SkipException(socket.error): - """Not an exception for Python 2, but one in 3.""" - -class SecondSkipException(SkipException): - """Also a good exception.""" - -try: - 1 + 1 -except MyException: # [catching-non-exception] - print("caught") - -try: - 1 + 2 -# +1:[catching-non-exception,catching-non-exception] -except (MyException, MySecondException): - print("caught") - -try: - 1 + 3 -except MyGoodException: - print("caught") - -try: - 1 + 3 -except (MyGoodException, MySecondGoodException): - print("caught") - -try: - 1 + 3 -except (SkipException, SecondSkipException): - print("caught") - -try: - 1 + 42 -# +1:[catching-non-exception,catching-non-exception] -except (None, list()): - print("caught") - -try: - 1 + 24 -except None: # [catching-non-exception] - print("caught") - -EXCEPTION = None -EXCEPTION = ZeroDivisionError -try: - 1 + 46 -except EXCEPTION: - print("caught") - -try: - 1 + 42 -# +1:[catching-non-exception,catching-non-exception,catching-non-exception] -except (list([4, 5, 6]), None, ZeroDivisionError, 4): - print("caught") - -EXCEPTION_TUPLE = (ZeroDivisionError, OSError) -NON_EXCEPTION_TUPLE = (ZeroDivisionError, OSError, 4) - -try: - 1 + 42 -except EXCEPTION_TUPLE: - print("caught") - -try: - 1 + 42 -except NON_EXCEPTION_TUPLE: # [catching-non-exception] - print("caught") - -from missing_import import UnknownError -UNKNOWN_COMPONENTS = (ZeroDivisionError, UnknownError) - -try: - 1 + 42 -except UNKNOWN_COMPONENTS: - print("caught") - -try: - 1 + 42 -except binascii.Error: - print('builtin and detected') - -try: - 1 + 45 -except object: # [catching-non-exception] - print('caught') - -try: - 1 + 42 -except range: # [catching-non-exception] - print('caught') - - -class HasErrorInMRO(six.with_metaclass(abc.ABCMeta, Exception)): - pass - - -class Second(HasErrorInMRO): - pass - - -try: - raise Second -except Second: - pass diff --git a/pymode/libs/pylint/test/functional/invalid_exceptions_caught.txt b/pymode/libs/pylint/test/functional/invalid_exceptions_caught.txt deleted file mode 100644 index 3cd4822f..00000000 --- a/pymode/libs/pylint/test/functional/invalid_exceptions_caught.txt +++ /dev/null @@ -1,12 +0,0 @@ -catching-non-exception:27::"Catching an exception which doesn't inherit from BaseException: MyException" -catching-non-exception:33::"Catching an exception which doesn't inherit from BaseException: MyException" -catching-non-exception:33::"Catching an exception which doesn't inherit from BaseException: MySecondException" -catching-non-exception:54::"Catching an exception which doesn't inherit from BaseException: None" -catching-non-exception:54::"Catching an exception which doesn't inherit from BaseException: list()" -catching-non-exception:59::"Catching an exception which doesn't inherit from BaseException: None" -catching-non-exception:72::"Catching an exception which doesn't inherit from BaseException: 4" -catching-non-exception:72::"Catching an exception which doesn't inherit from BaseException: None" -catching-non-exception:72::"Catching an exception which doesn't inherit from BaseException: list([4, 5, 6])" -catching-non-exception:85::"Catching an exception which doesn't inherit from BaseException: NON_EXCEPTION_TUPLE" -catching-non-exception:103::"Catching an exception which doesn't inherit from BaseException: object" -catching-non-exception:108::"Catching an exception which doesn't inherit from BaseException: range" diff --git a/pymode/libs/pylint/test/functional/invalid_exceptions_raised.py b/pymode/libs/pylint/test/functional/invalid_exceptions_raised.py deleted file mode 100644 index 118d3981..00000000 --- a/pymode/libs/pylint/test/functional/invalid_exceptions_raised.py +++ /dev/null @@ -1,83 +0,0 @@ -# pylint:disable=too-few-public-methods,old-style-class,no-init,import-error,missing-docstring, not-callable -"""test pb with exceptions and old/new style classes""" - - -class ValidException(Exception): - """Valid Exception.""" - -class OldStyleClass: - """Not an exception.""" - -class NewStyleClass(object): - """Not an exception.""" - - -def good_case(): - """raise""" - raise ValidException('hop') - -def good_case1(): - """zlib.error is defined in C module.""" - import zlib - raise zlib.error(4) - -def good_case2(): - """decimal.DivisionByZero is defined in C on Python 3.""" - import decimal - raise decimal.DivisionByZero(4) - -def good_case3(): - """io.BlockingIOError is defined in C.""" - import io - raise io.BlockingIOError - -def bad_case0(): - """raise""" - # +2:<3.0:[nonstandard-exception] - # +1:>=3.0:[raising-non-exception] - raise OldStyleClass('hop') - -def bad_case1(): - """raise""" - raise NewStyleClass() # [raising-non-exception] - -def bad_case2(): - """raise""" - # +2:<3.0:[nonstandard-exception] - # +1:>=3.0:[raising-non-exception] - raise OldStyleClass('hop') - -def bad_case3(): - """raise""" - raise NewStyleClass # [raising-non-exception] - -def bad_case4(): - """raise""" - raise NotImplemented('hop') # [notimplemented-raised] - -def bad_case5(): - """raise""" - raise 1 # [raising-bad-type] - -def bad_case6(): - """raise""" - raise None # [raising-bad-type] - -def bad_case7(): - """raise list""" - raise list # [raising-non-exception] - -def bad_case8(): - """raise tuple""" - raise tuple # [raising-non-exception] - -def bad_case9(): - """raise dict""" - raise dict # [raising-non-exception] - -def unknown_bases(): - """Don't emit when we don't know the bases.""" - from lala import bala - class MyException(bala): - pass - raise MyException diff --git a/pymode/libs/pylint/test/functional/invalid_exceptions_raised.txt b/pymode/libs/pylint/test/functional/invalid_exceptions_raised.txt deleted file mode 100644 index 47eb0fec..00000000 --- a/pymode/libs/pylint/test/functional/invalid_exceptions_raised.txt +++ /dev/null @@ -1,12 +0,0 @@ -nonstandard-exception:38:bad_case0:"Exception doesn't inherit from standard ""Exception"" class" -raising-non-exception:38:bad_case0:Raising a new style class which doesn't inherit from BaseException -raising-non-exception:42:bad_case1:Raising a new style class which doesn't inherit from BaseException -nonstandard-exception:48:bad_case2:"Exception doesn't inherit from standard ""Exception"" class" -raising-non-exception:48:bad_case2:Raising a new style class which doesn't inherit from BaseException -raising-non-exception:52:bad_case3:Raising a new style class which doesn't inherit from BaseException -notimplemented-raised:56:bad_case4:NotImplemented raised - should raise NotImplementedError -raising-bad-type:60:bad_case5:Raising int while only classes or instances are allowed -raising-bad-type:64:bad_case6:Raising NoneType while only classes or instances are allowed -raising-non-exception:68:bad_case7:Raising a new style class which doesn't inherit from BaseException -raising-non-exception:72:bad_case8:Raising a new style class which doesn't inherit from BaseException -raising-non-exception:76:bad_case9:Raising a new style class which doesn't inherit from BaseException \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/invalid_length_returned.py b/pymode/libs/pylint/test/functional/invalid_length_returned.py deleted file mode 100644 index cdc35639..00000000 --- a/pymode/libs/pylint/test/functional/invalid_length_returned.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Check invalid value returned by __len__ """ - -# pylint: disable=too-few-public-methods,missing-docstring,no-self-use,import-error -import sys - -import six - -from missing import Missing - - -class FirstGoodLen(object): - """__len__ returns """ - - def __len__(self): - return 0 - - -class SecondGoodLen(object): - """__len__ returns """ - - def __len__(self): - return sys.maxsize + 1 - - -class LenMetaclass(type): - def __len__(cls): - return 1 - - -@six.add_metaclass(LenMetaclass) -class ThirdGoodLen(object): - """Length through the metaclass.""" - - -class FirstBadLen(object): - """ __len__ returns a negative integer """ - - def __len__(self): # [invalid-length-returned] - return -1 - - -class SecondBadLen(object): - """ __len__ returns non-int """ - - def __len__(self): # [invalid-length-returned] - return 3.0 - - -class ThirdBadLen(object): - """ __len__ returns node which does not have 'value' in AST """ - - def __len__(self): # [invalid-length-returned] - return lambda: 3 - - -class AmbigousLen(object): - """ Uninferable return value """ - __len__ = lambda self: Missing diff --git a/pymode/libs/pylint/test/functional/invalid_length_returned.txt b/pymode/libs/pylint/test/functional/invalid_length_returned.txt deleted file mode 100644 index 6febeb61..00000000 --- a/pymode/libs/pylint/test/functional/invalid_length_returned.txt +++ /dev/null @@ -1,3 +0,0 @@ -invalid-length-returned:38:FirstBadLen.__len__:__len__ does not return non-negative integer -invalid-length-returned:45:SecondBadLen.__len__:__len__ does not return non-negative integer -invalid-length-returned:52:ThirdBadLen.__len__:__len__ does not return non-negative integer diff --git a/pymode/libs/pylint/test/functional/invalid_name.py b/pymode/libs/pylint/test/functional/invalid_name.py deleted file mode 100644 index 061a3476..00000000 --- a/pymode/libs/pylint/test/functional/invalid_name.py +++ /dev/null @@ -1,31 +0,0 @@ -""" Tests for invalid-name checker. """ -# pylint: disable=unused-import, no-absolute-import, wrong-import-position - -AAA = 24 -try: - import collections -except ImportError: - collections = None - -aaa = 42 # [invalid-name] -try: - import time -except ValueError: - time = None # [invalid-name] - -try: - from sys import argv, executable as python -except ImportError: - argv = 42 - python = 24 - -def test(): - """ Shouldn't emit an invalid-name here. """ - try: - import re - except ImportError: - re = None - return re - -def a(): # [invalid-name] - """yo""" diff --git a/pymode/libs/pylint/test/functional/invalid_name.txt b/pymode/libs/pylint/test/functional/invalid_name.txt deleted file mode 100644 index b5e9b7e4..00000000 --- a/pymode/libs/pylint/test/functional/invalid_name.txt +++ /dev/null @@ -1,3 +0,0 @@ -invalid-name:10::"Invalid constant name ""aaa""" -invalid-name:14::"Invalid constant name ""time""" -invalid-name:30:a:"Invalid function name ""a""" diff --git a/pymode/libs/pylint/test/functional/invalid_sequence_index.py b/pymode/libs/pylint/test/functional/invalid_sequence_index.py deleted file mode 100644 index 2cf9ae65..00000000 --- a/pymode/libs/pylint/test/functional/invalid_sequence_index.py +++ /dev/null @@ -1,224 +0,0 @@ -"""Errors for invalid sequence indices""" -# pylint: disable=too-few-public-methods, no-self-use, import-error, missing-docstring - -from unknown import Unknown - -TESTLIST = [1, 2, 3] -TESTTUPLE = (1, 2, 3) -TESTSTR = '123' - -# getitem tests with bad indices -def function1(): - """list index is a function""" - return TESTLIST[id] # [invalid-sequence-index] - -def function2(): - """list index is None""" - return TESTLIST[None] # [invalid-sequence-index] - -def function3(): - """list index is a float expression""" - return TESTLIST[float(0)] # [invalid-sequence-index] - -def function4(): - """list index is a str constant""" - return TESTLIST['0'] # [invalid-sequence-index] - -def function5(): - """list index does not implement __index__""" - class NonIndexType(object): - """Class without __index__ method""" - pass - - return TESTLIST[NonIndexType()] # [invalid-sequence-index] - -def function6(): - """Tuple index is None""" - return TESTTUPLE[None] # [invalid-sequence-index] - -def function7(): - """String index is None""" - return TESTSTR[None] # [invalid-sequence-index] - -def function8(): - """Index of subclass of tuple is None""" - class TupleTest(tuple): - """Subclass of tuple""" - pass - return TupleTest()[None] # [invalid-sequence-index] - -# getitem tests with good indices -def function9(): - """list index is an int constant""" - return TESTLIST[0] # no error - -def function10(): - """list index is a integer expression""" - return TESTLIST[int(0.0)] # no error - -def function11(): - """list index is a slice""" - return TESTLIST[slice(1, 2, 3)] # no error - -def function12(): - """list index implements __index__""" - class IndexType(object): - """Class with __index__ method""" - def __index__(self): - """Allow objects of this class to be used as slice indices""" - return 0 - - return TESTLIST[IndexType()] # no error - -def function13(): - """list index implements __index__ in a superclass""" - class IndexType(object): - """Class with __index__ method""" - def __index__(self): - """Allow objects of this class to be used as slice indices""" - return 0 - - class IndexSubType(IndexType): - """Class with __index__ in parent""" - pass - - return TESTLIST[IndexSubType()] # no error - -def function14(): - """Tuple index is an int constant""" - return TESTTUPLE[0] - -def function15(): - """String index is an int constant""" - return TESTSTR[0] - -def function16(): - """Index of subclass of tuple is an int constant""" - class TupleTest(tuple): - """Subclass of tuple""" - pass - return TupleTest()[0] # no error - -def function17(): - """Index of subclass of tuple with custom __getitem__ is None""" - class TupleTest(tuple): - """Subclass of tuple with custom __getitem__""" - def __getitem__(self, index): - """Allow non-integer indices""" - return 0 - return TupleTest()[None] # no error - -def function18(): - """Index of subclass of tuple with __getitem__ in superclass is None""" - class TupleTest(tuple): - """Subclass of tuple with custom __getitem__""" - def __getitem__(self, index): - """Allow non-integer indices""" - return 0 - - class SubTupleTest(TupleTest): - """Subclass of a subclass of tuple""" - pass - - return SubTupleTest()[None] # no error - -# Test with set and delete statements -def function19(): - """Set with None and integer indices""" - TESTLIST[None] = 0 # [invalid-sequence-index] - TESTLIST[0] = 0 # no error - -def function20(): - """Delete with None and integer indicies""" - del TESTLIST[None] # [invalid-sequence-index] - del TESTLIST[0] # no error - -def function21(): - """Set and delete on a subclass of list""" - class ListTest(list): - """Inherit all list get/set/del handlers""" - pass - test = ListTest() - - # Set and delete with invalid indices - test[None] = 0 # [invalid-sequence-index] - del test[None] # [invalid-sequence-index] - - # Set and delete with valid indices - test[0] = 0 # no error - del test[0] # no error - -def function22(): - """Get, set, and delete on a subclass of list that overrides __setitem__""" - class ListTest(list): - """Override setitem but not get or del""" - def __setitem__(self, key, value): - pass - test = ListTest() - - # failure on the getitem with None - test[None][0] = 0 # [invalid-sequence-index] - # failure on the getitem with None - del test[None] # [invalid-sequence-index] - - test[0][0] = 0 # getitem with int and setitem with int, no error - test[None] = 0 # setitem overridden, no error - test[0] = 0 # setitem with int, no error - del test[0] # delitem with int, no error - -def function23(): - """Get, set, and delete on a subclass of list that overrides __delitem__""" - class ListTest(list): - """Override delitem but not get or set""" - def __delitem__(self, key): - pass - test = ListTest() - - # failure on the getitem with None - test[None][0] = 0 # [invalid-sequence-index] - # setitem with invalid index - test[None] = 0 # [invalid-sequence-index] - - test[0][0] = 0 # getitem with int and setitem with int, no error - test[0] = 0 # setitem with int, no error - del test[None] # delitem overriden, no error - del test[0] # delitem with int, no error - -def function24(): - """Get, set, and delete on a subclass of list that overrides __getitem__""" - class ListTest(list): - """Override gelitem but not del or set""" - def __getitem__(self, key): - pass - test = ListTest() - - # setitem with invalid index - test[None] = 0 # [invalid-sequence-index] - # delitem with invalid index - del test[None] # [invalid-sequence-index] - - test[None][0] = 0 # getitem overriden, no error - test[0][0] = 0 # getitem with int and setitem with int, no error - test[0] = 0 # setitem with int, no error - del test[0] # delitem with int, no error - -# Teest ExtSlice usage -def function25(): - """Extended slice used with a list""" - return TESTLIST[..., 0] # [invalid-sequence-index] - -def function26(): - """Extended slice used with an object that implements __getitem__""" - class ExtSliceTest(object): - """Permit extslice syntax by implementing __getitem__""" - def __getitem__(self, index): - return 0 - return ExtSliceTest()[..., 0] # no error - -def function27(): - """Don't warn in the case where the indexed object has unknown base classes.""" - class UnknownBase(Unknown): - pass - slices = UnknownBase["aaaa"] + UnknownBase()[object] - ext_slices = UnknownBase[..., 0] + UnknownBase()[..., 0] - return slices, ext_slices diff --git a/pymode/libs/pylint/test/functional/invalid_sequence_index.txt b/pymode/libs/pylint/test/functional/invalid_sequence_index.txt deleted file mode 100644 index 204aebc9..00000000 --- a/pymode/libs/pylint/test/functional/invalid_sequence_index.txt +++ /dev/null @@ -1,20 +0,0 @@ -invalid-sequence-index:13:function1:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:17:function2:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:21:function3:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:25:function4:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:33:function5:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:37:function6:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:41:function7:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:48:function8:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:128:function19:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:133:function20:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:144:function21:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:145:function21:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:159:function22:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:160:function22:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:162:function22:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:178:function23:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:180:function23:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:196:function24:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:198:function24:Sequence index is not an int, slice, or instance with __index__ -invalid-sequence-index:208:function25:Sequence index is not an int, slice, or instance with __index__ \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/invalid_slice_index.py b/pymode/libs/pylint/test/functional/invalid_slice_index.py deleted file mode 100644 index 63ba252b..00000000 --- a/pymode/libs/pylint/test/functional/invalid_slice_index.py +++ /dev/null @@ -1,60 +0,0 @@ -"""Errors for invalid slice indices""" -# pylint: disable=too-few-public-methods, no-self-use - - -TESTLIST = [1, 2, 3] - -# Invalid indices -def function1(): - """functions used as indices""" - return TESTLIST[id:id:] # [invalid-slice-index,invalid-slice-index] - -def function2(): - """strings used as indices""" - return TESTLIST['0':'1':] # [invalid-slice-index,invalid-slice-index] - -def function3(): - """class without __index__ used as index""" - - class NoIndexTest(object): - """Class with no __index__ method""" - pass - - return TESTLIST[NoIndexTest()::] # [invalid-slice-index] - -# Valid indices -def function4(): - """integers used as indices""" - return TESTLIST[0:0:0] # no error - -def function5(): - """None used as indices""" - return TESTLIST[None:None:None] # no error - -def function6(): - """class with __index__ used as index""" - class IndexTest(object): - """Class with __index__ method""" - def __index__(self): - """Allow objects of this class to be used as slice indices""" - return 0 - - return TESTLIST[IndexTest():None:None] # no error - -def function7(): - """class with __index__ in superclass used as index""" - class IndexType(object): - """Class with __index__ method""" - def __index__(self): - """Allow objects of this class to be used as slice indices""" - return 0 - - class IndexSubType(IndexType): - """Class with __index__ in parent""" - pass - - return TESTLIST[IndexSubType():None:None] # no error - -def function8(): - """slice object used as index""" - return TESTLIST[slice(1, 2, 3)] # no error diff --git a/pymode/libs/pylint/test/functional/invalid_slice_index.txt b/pymode/libs/pylint/test/functional/invalid_slice_index.txt deleted file mode 100644 index cd4dc6e9..00000000 --- a/pymode/libs/pylint/test/functional/invalid_slice_index.txt +++ /dev/null @@ -1,5 +0,0 @@ -invalid-slice-index:10:function1:Slice index is not an int, None, or instance with __index__ -invalid-slice-index:10:function1:Slice index is not an int, None, or instance with __index__ -invalid-slice-index:14:function2:Slice index is not an int, None, or instance with __index__ -invalid-slice-index:14:function2:Slice index is not an int, None, or instance with __index__ -invalid-slice-index:23:function3:Slice index is not an int, None, or instance with __index__ diff --git a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.py b/pymode/libs/pylint/test/functional/invalid_star_assignment_target.py deleted file mode 100644 index 112dd0b6..00000000 --- a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Test for *a = b """ - -*FIRST = [1, 2, 3] # [invalid-star-assignment-target] -(*FIRST, ) = [1, 2, 3] diff --git a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.rc b/pymode/libs/pylint/test/functional/invalid_star_assignment_target.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.txt b/pymode/libs/pylint/test/functional/invalid_star_assignment_target.txt deleted file mode 100644 index 8cef8eba..00000000 --- a/pymode/libs/pylint/test/functional/invalid_star_assignment_target.txt +++ /dev/null @@ -1 +0,0 @@ -invalid-star-assignment-target:3::Starred assignment target must be in a list or tuple diff --git a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.py b/pymode/libs/pylint/test/functional/invalid_unary_operand_type.py deleted file mode 100644 index 285c9ca4..00000000 --- a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Detect problems with invalid operands used on invalid objects.""" -# pylint: disable=missing-docstring,too-few-public-methods,invalid-name -# pylint: disable=unused-variable - -import collections - - -class Implemented(object): - def __invert__(self): - return 42 - def __pos__(self): - return 42 - def __neg__(self): - return 42 - - -def these_are_good(): - negative = -1 - negative1 = -1.0 - positive = +1 - positive2 = +1.0 - inverted = ~1 - not_int = not 1 - not_float = not 2.0 - not_string = not "" - not_list = not [] - not_dict = not {} - not_tuple = not (1, 2) - inverted_instance = ~Implemented() - positive_instance = +Implemented() - negative_instance = -Implemented() - not_instance = not Implemented() - - -def these_are_bad(): - invert_list = ~[] # [invalid-unary-operand-type] - invert_tuple = ~() # [invalid-unary-operand-type] - invert_dict = ~dict() # [invalid-unary-operand-type] - invert_dict_1 = ~{} # [invalid-unary-operand-type] - invert_set = ~set() # [invalid-unary-operand-type] - neg_set = -set() # [invalid-unary-operand-type] - neg_str = -"" # [invalid-unary-operand-type] - invert_str = ~"" # [invalid-unary-operand-type] - pos_str = +"" # [invalid-unary-operand-type] - class A(object): - pass - invert_func = ~(lambda: None) # [invalid-unary-operand-type] - invert_class = ~A # [invalid-unary-operand-type] - invert_instance = ~A() # [invalid-unary-operand-type] - invert_module = ~collections # [invalid-unary-operand-type] - invert_float = ~2.0 # [invalid-unary-operand-type] diff --git a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.rc b/pymode/libs/pylint/test/functional/invalid_unary_operand_type.rc deleted file mode 100644 index a7e3bb9f..00000000 --- a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=4.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.txt b/pymode/libs/pylint/test/functional/invalid_unary_operand_type.txt deleted file mode 100644 index 437d8e73..00000000 --- a/pymode/libs/pylint/test/functional/invalid_unary_operand_type.txt +++ /dev/null @@ -1,14 +0,0 @@ -invalid-unary-operand-type:36:these_are_bad:"bad operand type for unary ~: list" -invalid-unary-operand-type:37:these_are_bad:"bad operand type for unary ~: tuple" -invalid-unary-operand-type:38:these_are_bad:"bad operand type for unary ~: dict" -invalid-unary-operand-type:39:these_are_bad:"bad operand type for unary ~: dict" -invalid-unary-operand-type:40:these_are_bad:"bad operand type for unary ~: set" -invalid-unary-operand-type:41:these_are_bad:"bad operand type for unary -: set" -invalid-unary-operand-type:42:these_are_bad:"bad operand type for unary -: str" -invalid-unary-operand-type:43:these_are_bad:"bad operand type for unary ~: str" -invalid-unary-operand-type:44:these_are_bad:"bad operand type for unary +: str" -invalid-unary-operand-type:47:these_are_bad:"bad operand type for unary ~: " -invalid-unary-operand-type:48:these_are_bad:"bad operand type for unary ~: A" -invalid-unary-operand-type:49:these_are_bad:"bad operand type for unary ~: A" -invalid-unary-operand-type:50:these_are_bad:"bad operand type for unary ~: collections" -invalid-unary-operand-type:51:these_are_bad:"bad operand type for unary ~: float" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/iterable_context.py b/pymode/libs/pylint/test/functional/iterable_context.py deleted file mode 100644 index 05d85894..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context.py +++ /dev/null @@ -1,179 +0,0 @@ -""" -Checks that primitive values are not used in an -iterating/mapping context. -""" -# pylint: disable=missing-docstring,invalid-name,too-few-public-methods,no-init,no-self-use,import-error,unused-argument,bad-mcs-method-argument,wrong-import-position -from __future__ import print_function - -# primitives -numbers = [1, 2, 3] - -for i in numbers: - pass - -for i in iter(numbers): - pass - -for i in "123": - pass - -for i in u"123": - pass - -for i in b"123": - pass - -for i in bytearray(b"123"): - pass - -for i in set(numbers): - pass - -for i in frozenset(numbers): - pass - -for i in dict(a=1, b=2): - pass - -# comprehensions -for i in [x for x in range(10)]: - pass - -for i in {x for x in range(1, 100, 2)}: - pass - -for i in {x: 10 - x for x in range(10)}: - pass - -# generators -def powers_of_two(): - k = 0 - while k < 10: - yield 2 ** k - k += 1 - -for i in powers_of_two(): - pass - -for i in powers_of_two: # [not-an-iterable] - pass - -# check for custom iterators -class A(object): - pass - -class B(object): - def __iter__(self): - return self - - def __next__(self): - return 1 - - def next(self): - return 1 - -class C(object): - "old-style iterator" - def __getitem__(self, k): - if k > 10: - raise IndexError - return k + 1 - - def __len__(self): - return 10 - -for i in C(): - print(i) - - -def test(*args): - print(args) - - -test(*A()) # [not-an-iterable] -test(*B()) -test(*B) # [not-an-iterable] -for i in A(): # [not-an-iterable] - pass -for i in B(): - pass -for i in B: # [not-an-iterable] - pass - -for i in range: # [not-an-iterable] - pass - -# check that primitive non-iterable types are catched -for i in True: # [not-an-iterable] - pass - -for i in None: # [not-an-iterable] - pass - -for i in 8.5: # [not-an-iterable] - pass - -for i in 10: # [not-an-iterable] - pass - - -# skip uninferable instances -from some_missing_module import Iterable - -class MyClass(Iterable): - pass - -m = MyClass() -for i in m: - print(i) - -# skip checks if statement is inside mixin/base/abstract class -class ManagedAccessViewMixin(object): - access_requirements = None - - def get_access_requirements(self): - return self.access_requirements - - def dispatch(self, *_args, **_kwargs): - klasses = self.get_access_requirements() - - # no error should be emitted here - for requirement in klasses: - print(requirement) - -class BaseType(object): - valid_values = None - - def validate(self, value): - if self.valid_values is None: - return True - else: - # error should not be emitted here - for v in self.valid_values: - if value == v: - return True - return False - -class AbstractUrlMarkManager(object): - def __init__(self): - self._lineparser = None - self._init_lineparser() - # error should not be emitted here - for line in self._lineparser: - print(line) - - def _init_lineparser(self): - raise NotImplementedError - -# class is not named as abstract -# but still is deduceably abstract -class UrlMarkManager(object): - def __init__(self): - self._lineparser = None - self._init_lineparser() - # error should not be emitted here - for line in self._lineparser: - print(line) - - def _init_lineparser(self): - raise NotImplementedError diff --git a/pymode/libs/pylint/test/functional/iterable_context.txt b/pymode/libs/pylint/test/functional/iterable_context.txt deleted file mode 100644 index fbe14332..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context.txt +++ /dev/null @@ -1,10 +0,0 @@ -not-an-iterable:58::Non-iterable value powers_of_two is used in an iterating context -not-an-iterable:93::Non-iterable value A() is used in an iterating context -not-an-iterable:95::Non-iterable value B is used in an iterating context -not-an-iterable:96::Non-iterable value A() is used in an iterating context -not-an-iterable:100::Non-iterable value B is used in an iterating context -not-an-iterable:103::Non-iterable value range is used in an iterating context -not-an-iterable:107::Non-iterable value True is used in an iterating context -not-an-iterable:110::Non-iterable value None is used in an iterating context -not-an-iterable:113::Non-iterable value 8.5 is used in an iterating context -not-an-iterable:116::Non-iterable value 10 is used in an iterating context diff --git a/pymode/libs/pylint/test/functional/iterable_context_py2.py b/pymode/libs/pylint/test/functional/iterable_context_py2.py deleted file mode 100644 index 8687f84a..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py2.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -Checks that iterable metaclasses are recognized by pylint. -""" -# pylint: disable=missing-docstring,too-few-public-methods,no-init,no-self-use,unused-argument,bad-mcs-method-argument - -# metaclasses as iterables -class Meta(type): - def __iter__(self): - return iter((1, 2, 3)) - -class SomeClass(object): - __metaclass__ = Meta - - -for i in SomeClass: - print i -for i in SomeClass(): # [not-an-iterable] - print i diff --git a/pymode/libs/pylint/test/functional/iterable_context_py2.rc b/pymode/libs/pylint/test/functional/iterable_context_py2.rc deleted file mode 100644 index 61e01ea3..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py2.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -max_pyver=2.7 - diff --git a/pymode/libs/pylint/test/functional/iterable_context_py2.txt b/pymode/libs/pylint/test/functional/iterable_context_py2.txt deleted file mode 100644 index 8de579a3..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py2.txt +++ /dev/null @@ -1 +0,0 @@ -not-an-iterable:17::Non-iterable value SomeClass() is used in an iterating context diff --git a/pymode/libs/pylint/test/functional/iterable_context_py3.py b/pymode/libs/pylint/test/functional/iterable_context_py3.py deleted file mode 100644 index cb2a5050..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py3.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -Checks that iterable metaclasses are recognized by pylint. -""" -# pylint: disable=missing-docstring,too-few-public-methods,no-init,no-self-use,unused-argument,bad-mcs-method-argument - -# metaclasses as iterables -class Meta(type): - def __iter__(self): - return iter((1, 2, 3)) - -class SomeClass(metaclass=Meta): - pass - - -for i in SomeClass: - print(i) -for i in SomeClass(): # [not-an-iterable] - print(i) diff --git a/pymode/libs/pylint/test/functional/iterable_context_py3.rc b/pymode/libs/pylint/test/functional/iterable_context_py3.rc deleted file mode 100644 index 9bf6df0e..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py3.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -min_pyver=3.0 - diff --git a/pymode/libs/pylint/test/functional/iterable_context_py3.txt b/pymode/libs/pylint/test/functional/iterable_context_py3.txt deleted file mode 100644 index 8de579a3..00000000 --- a/pymode/libs/pylint/test/functional/iterable_context_py3.txt +++ /dev/null @@ -1 +0,0 @@ -not-an-iterable:17::Non-iterable value SomeClass() is used in an iterating context diff --git a/pymode/libs/pylint/test/functional/line_endings.py b/pymode/libs/pylint/test/functional/line_endings.py deleted file mode 100644 index bfff5146..00000000 --- a/pymode/libs/pylint/test/functional/line_endings.py +++ /dev/null @@ -1,3 +0,0 @@ -"mixing line endings are not welcome" -# +1: [unexpected-line-ending-format, mixed-line-endings] -CONST = 1 diff --git a/pymode/libs/pylint/test/functional/line_endings.rc b/pymode/libs/pylint/test/functional/line_endings.rc deleted file mode 100644 index 95532ea8..00000000 --- a/pymode/libs/pylint/test/functional/line_endings.rc +++ /dev/null @@ -1,2 +0,0 @@ -[Format] -expected-line-ending-format=LF diff --git a/pymode/libs/pylint/test/functional/line_endings.txt b/pymode/libs/pylint/test/functional/line_endings.txt deleted file mode 100644 index a18a8723..00000000 --- a/pymode/libs/pylint/test/functional/line_endings.txt +++ /dev/null @@ -1,2 +0,0 @@ -mixed-line-endings:3::Mixed line endings LF and CRLF -unexpected-line-ending-format:3::Unexpected line ending format. There is 'CRLF' while it should be 'LF'. diff --git a/pymode/libs/pylint/test/functional/line_too_long.py b/pymode/libs/pylint/test/functional/line_too_long.py deleted file mode 100644 index 21d279d6..00000000 --- a/pymode/libs/pylint/test/functional/line_too_long.py +++ /dev/null @@ -1,26 +0,0 @@ -# pylint: disable=invalid-encoded-data -# +1: [line-too-long] -##################################################################################################### -# +1: [line-too-long] -""" that one is too long tooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo loooooong""" - -# The next line is exactly 80 characters long. -A = '--------------------------------------------------------------------------' - -# Do not trigger the line-too-long warning if the only token that makes the -# line longer than 80 characters is a trailing pylint disable. -var = 'This line has a disable pragma and whitespace trailing beyond 80 chars. ' # pylint:disable=invalid-name - -# +1: [line-too-long] -badname = 'This line is already longer than 100 characters even without the pragma. Trust me. Please.' # pylint:disable=invalid-name - -# http://example.com/this/is/a/very/long/url?but=splitting&urls=is&a=pain&so=they&can=be&long - - -def function(): - # +3: [line-too-long] - """This is a docstring. - - That contains a very, very long line that exceeds the 100 characters limit by a good margin. So good? - """ - pass diff --git a/pymode/libs/pylint/test/functional/line_too_long.txt b/pymode/libs/pylint/test/functional/line_too_long.txt deleted file mode 100644 index 1f02bfdb..00000000 --- a/pymode/libs/pylint/test/functional/line_too_long.txt +++ /dev/null @@ -1,4 +0,0 @@ -line-too-long:3::Line too long (101/100) -line-too-long:5::Line too long (104/100) -line-too-long:15::Line too long (102/100) -line-too-long:24::Line too long (105/100) diff --git a/pymode/libs/pylint/test/functional/logging_format_interpolation.py b/pymode/libs/pylint/test/functional/logging_format_interpolation.py deleted file mode 100644 index 0f8f64db..00000000 --- a/pymode/libs/pylint/test/functional/logging_format_interpolation.py +++ /dev/null @@ -1,25 +0,0 @@ -# pylint: disable=E1101, no-absolute-import, import-error,line-too-long, missing-docstring,wrong-import-order,wrong-import-position - -try: - import __builtin__ as builtins -except ImportError: - import builtins - -# Muck up the names in an effort to confuse... -import logging as renamed_logging -import os as logging - -FORMAT_STR = '{0}, {1}' - -# Statements that should be flagged: -renamed_logging.debug('{0}, {1}'.format(4, 5)) # [logging-format-interpolation] -renamed_logging.log(renamed_logging.DEBUG, 'msg: {}'.format('Run!')) # [logging-format-interpolation] -renamed_logging.debug(FORMAT_STR.format(4, 5)) # [logging-format-interpolation] -renamed_logging.log(renamed_logging.DEBUG, FORMAT_STR.format(4, 5)) # [logging-format-interpolation] - -# Statements that should not be flagged: -renamed_logging.debug(format(66, 'x')) -renamed_logging.debug(builtins.format(66, 'x')) -renamed_logging.log(renamed_logging.DEBUG, 'msg: Run!'.upper()) -logging.debug('{0}, {1}'.format(4, 5)) -logging.log(logging.DEBUG, 'msg: {}'.format('Run!')) diff --git a/pymode/libs/pylint/test/functional/logging_format_interpolation.txt b/pymode/libs/pylint/test/functional/logging_format_interpolation.txt deleted file mode 100644 index 75281658..00000000 --- a/pymode/libs/pylint/test/functional/logging_format_interpolation.txt +++ /dev/null @@ -1,4 +0,0 @@ -logging-format-interpolation:15::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:16::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:17::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:18::Use % formatting in logging functions and pass the % parameters as arguments diff --git a/pymode/libs/pylint/test/functional/logging_not_lazy.py b/pymode/libs/pylint/test/functional/logging_not_lazy.py deleted file mode 100644 index b843431e..00000000 --- a/pymode/libs/pylint/test/functional/logging_not_lazy.py +++ /dev/null @@ -1,17 +0,0 @@ -# pylint: disable=missing-docstring,no-member,deprecated-method - -# Muck up the names in an effort to confuse... -import logging as renamed_logging -import os as logging - -# Statements that should be flagged: -renamed_logging.warn('%s, %s' % (4, 5)) # [logging-not-lazy] -renamed_logging.exception('%s' % 'Exceptional!') # [logging-not-lazy] -renamed_logging.log(renamed_logging.INFO, 'msg: %s' % 'Run!') # [logging-not-lazy] - -# Statements that should not be flagged: -renamed_logging.warn('%s, %s', 4, 5) -renamed_logging.log(renamed_logging.INFO, 'msg: %s', 'Run!') -renamed_logging.warn('%s' + ' the rest of a single string') -logging.warn('%s, %s' % (4, 5)) -logging.log(logging.INFO, 'msg: %s' % 'Run!') diff --git a/pymode/libs/pylint/test/functional/logging_not_lazy.txt b/pymode/libs/pylint/test/functional/logging_not_lazy.txt deleted file mode 100644 index 60c6c590..00000000 --- a/pymode/libs/pylint/test/functional/logging_not_lazy.txt +++ /dev/null @@ -1,3 +0,0 @@ -logging-not-lazy:8::Specify string format arguments as logging function parameters -logging-not-lazy:9::Specify string format arguments as logging function parameters -logging-not-lazy:10::Specify string format arguments as logging function parameters diff --git a/pymode/libs/pylint/test/functional/long_lines_with_utf8.py b/pymode/libs/pylint/test/functional/long_lines_with_utf8.py deleted file mode 100644 index a1d90edc..00000000 --- a/pymode/libs/pylint/test/functional/long_lines_with_utf8.py +++ /dev/null @@ -1,7 +0,0 @@ -# coding: utf-8 -"""Test data file files with non-ASCII content.""" - - -THIS_IS_A_LONG_VARIABLE_NAME = 'Существительное Частица' # but the line is okay - -THIS_IS_A_VERY_LONG_VARIABLE_NAME = 'Существительное Частица' # and the line is not okay # [line-too-long] diff --git a/pymode/libs/pylint/test/functional/long_lines_with_utf8.txt b/pymode/libs/pylint/test/functional/long_lines_with_utf8.txt deleted file mode 100644 index 42a7976a..00000000 --- a/pymode/libs/pylint/test/functional/long_lines_with_utf8.txt +++ /dev/null @@ -1 +0,0 @@ -line-too-long:7::Line too long (108/100) diff --git a/pymode/libs/pylint/test/functional/mapping_context.py b/pymode/libs/pylint/test/functional/mapping_context.py deleted file mode 100644 index 6968994f..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Checks that only valid values are used in a mapping context. -""" -# pylint: disable=missing-docstring,invalid-name,too-few-public-methods,no-self-use,import-error,wrong-import-position -from __future__ import print_function - - -def test(**kwargs): - print(kwargs) - - -# dictionary value/comprehension -dict_value = dict(a=1, b=2, c=3) -dict_comp = {chr(x): x for x in range(256)} -test(**dict_value) -test(**dict_comp) - - -# in order to be used in kwargs custom mapping class should define -# __iter__(), __getitem__(key) and keys(). -class CustomMapping(object): - def __init__(self): - self.data = dict(a=1, b=2, c=3, d=4, e=5) - - def __getitem__(self, key): - return self.data[key] - - def keys(self): - return self.data.keys() - -test(**CustomMapping()) -test(**CustomMapping) # [not-a-mapping] - -class NotMapping(object): - pass - -test(**NotMapping()) # [not-a-mapping] - -# skip checks if statement is inside mixin/base/abstract class -class SomeMixin(object): - kwargs = None - - def get_kwargs(self): - return self.kwargs - - def run(self, **kwargs): - print(kwargs) - - def dispatch(self): - kws = self.get_kwargs() - self.run(**kws) - -class AbstractThing(object): - kwargs = None - - def get_kwargs(self): - return self.kwargs - - def run(self, **kwargs): - print(kwargs) - - def dispatch(self): - kws = self.get_kwargs() - self.run(**kws) - -class BaseThing(object): - kwargs = None - - def get_kwargs(self): - return self.kwargs - - def run(self, **kwargs): - print(kwargs) - - def dispatch(self): - kws = self.get_kwargs() - self.run(**kws) - -# abstract class -class Thing(object): - def get_kwargs(self): - raise NotImplementedError - - def run(self, **kwargs): - print(kwargs) - - def dispatch(self): - kwargs = self.get_kwargs() - self.run(**kwargs) - -# skip uninferable instances -from some_missing_module import Mapping - -class MyClass(Mapping): - pass - -test(**MyClass()) diff --git a/pymode/libs/pylint/test/functional/mapping_context.txt b/pymode/libs/pylint/test/functional/mapping_context.txt deleted file mode 100644 index 201da1a6..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context.txt +++ /dev/null @@ -1,2 +0,0 @@ -not-a-mapping:32::Non-mapping value CustomMapping is used in a mapping context -not-a-mapping:37::Non-mapping value NotMapping() is used in a mapping context diff --git a/pymode/libs/pylint/test/functional/mapping_context_py2.py b/pymode/libs/pylint/test/functional/mapping_context_py2.py deleted file mode 100644 index afe4400e..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py2.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=missing-docstring,invalid-name,too-few-public-methods -from __future__ import print_function - - -def test(**kwargs): - print(kwargs) - -# metaclasses as mappings -class Meta(type): - def __getitem__(self, key): - return ord(key) - def keys(self): - return ['a', 'b', 'c'] - -class SomeClass(object): - __metaclass__ = Meta - -test(**SomeClass) -test(**SomeClass()) # [not-a-mapping] diff --git a/pymode/libs/pylint/test/functional/mapping_context_py2.rc b/pymode/libs/pylint/test/functional/mapping_context_py2.rc deleted file mode 100644 index 61e01ea3..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py2.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -max_pyver=2.7 - diff --git a/pymode/libs/pylint/test/functional/mapping_context_py2.txt b/pymode/libs/pylint/test/functional/mapping_context_py2.txt deleted file mode 100644 index 59cca6c4..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py2.txt +++ /dev/null @@ -1 +0,0 @@ -not-a-mapping:19::Non-mapping value SomeClass() is used in a mapping context diff --git a/pymode/libs/pylint/test/functional/mapping_context_py3.py b/pymode/libs/pylint/test/functional/mapping_context_py3.py deleted file mode 100644 index 042d4d02..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py3.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=missing-docstring,invalid-name,too-few-public-methods,no-self-use -from __future__ import print_function - -def test(**kwargs): - print(kwargs) - -# metaclasses as mappings -class Meta(type): - def __getitem__(cls, key): - return ord(key) - - def keys(cls): - return ['a', 'b', 'c'] - -class SomeClass(metaclass=Meta): - pass - -test(**SomeClass) -test(**SomeClass()) # [not-a-mapping] diff --git a/pymode/libs/pylint/test/functional/mapping_context_py3.rc b/pymode/libs/pylint/test/functional/mapping_context_py3.rc deleted file mode 100644 index 9bf6df0e..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py3.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -min_pyver=3.0 - diff --git a/pymode/libs/pylint/test/functional/mapping_context_py3.txt b/pymode/libs/pylint/test/functional/mapping_context_py3.txt deleted file mode 100644 index 59cca6c4..00000000 --- a/pymode/libs/pylint/test/functional/mapping_context_py3.txt +++ /dev/null @@ -1 +0,0 @@ -not-a-mapping:19::Non-mapping value SomeClass() is used in a mapping context diff --git a/pymode/libs/pylint/test/functional/member_checks.py b/pymode/libs/pylint/test/functional/member_checks.py deleted file mode 100644 index 9ae71766..00000000 --- a/pymode/libs/pylint/test/functional/member_checks.py +++ /dev/null @@ -1,171 +0,0 @@ -# pylint: disable=print-statement,missing-docstring,no-self-use,too-few-public-methods,bare-except,broad-except -# pylint: disable=using-constant-test,expression-not-assigned, redefined-variable-type -from __future__ import print_function - -class Provider(object): - """provide some attributes and method""" - cattr = 4 - def __init__(self): - self.attr = 4 - def method(self, val): - """impressive method""" - return self.attr * val - def hophop(self): - """hop method""" - print('hop hop hop', self) - - -class Client(object): - """use provider class""" - - def __init__(self): - self._prov = Provider() - self._prov_attr = Provider.cattr - self._prov_attr2 = Provider.cattribute # [no-member] - self.set_later = 0 - - def set_set_later(self, value): - """set set_later attribute (introduce an inference ambiguity)""" - self.set_later = value - - def use_method(self): - """use provider's method""" - self._prov.hophop() - self._prov.hophophop() # [no-member] - - def use_attr(self): - """use provider's attr""" - print(self._prov.attr) - print(self._prov.attribute) # [no-member] - - def debug(self): - """print debug information""" - print(self.__class__.__name__) - print(self.__doc__) - print(self.__dict__) - print(self.__module__) - - def test_bt_types(self): - """test access to unexistant member of builtin types""" - lis = [] - lis.apppend(self) # [no-member] - dic = {} - dic.set(self) # [no-member] - tup = () - tup.append(self) # [no-member] - string = 'toto' - print(string.loower()) # [no-member] - integer = 1 - print(integer.whatever) # [no-member] - - def test_no_false_positives(self): - none = None - print(none.whatever) - # No misssing in the parents. - super(Client, self).misssing() # [no-member] - - -class Mixin(object): - """No no-member should be emitted for mixins.""" - -class Getattr(object): - """no-member shouldn't be emitted for classes with dunder getattr.""" - - def __getattr__(self, attr): - return self.__dict__[attr] - - -class Getattribute(object): - """no-member shouldn't be emitted for classes with dunder getattribute.""" - - def __getattribute__(self, attr): - return 42 - -print(object.__init__) -print(property.__init__) -print(Client().set_later.lower()) # [no-member] -print(Mixin().nanana()) -print(Getattr().nananan()) -print(Getattribute().batman()) - -try: - Client().missing_method() -except AttributeError: - pass - -try: - Client().indeed() # [no-member] -except ImportError: - pass - -try: - Client.missing() -except AttributeError: - Client.missing() # [no-member] - -try: - Client.missing() -except AttributeError: - try: - Client.missing() # [no-member] - except ValueError: - pass - -try: - if Client: - Client().missing() -except AttributeError: - pass - -try: - Client().indeed() -except AttributeError: - try: - Client.missing() # [no-member] - except Exception: - pass - - -class SuperChecks(str, str): # pylint: disable=duplicate-bases - """Don't fail when the MRO is invalid.""" - def test(self): - super(SuperChecks, self).lalala() - -type(Client()).ala -type({}).bala -type('').portocala - - -def socket_false_positive(): - """Test a regression - Version used: - - - Pylint 0.10.0 - - Logilab common 0.15.0 - - Logilab astroid 0.15.1 - - False E1101 positive, line 23: - Instance of '_socketobject' has no 'connect' member - """ - - import socket - sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sckt.connect(('127.0.0.1', 80)) - sckt.close() - - -def no_conjugate_member(magic_flag): - """should not raise E1101 on something.conjugate""" - if magic_flag: - something = 1.0 - else: - something = 1.0j - if isinstance(something, float): - return something - return something.conjugate() - - -class NoDunderNameInInstance(object): - """Emit a warning when accessing __name__ from an instance.""" - def __init__(self): - self.var = self.__name__ # [no-member] diff --git a/pymode/libs/pylint/test/functional/member_checks.txt b/pymode/libs/pylint/test/functional/member_checks.txt deleted file mode 100644 index 8acc7762..00000000 --- a/pymode/libs/pylint/test/functional/member_checks.txt +++ /dev/null @@ -1,15 +0,0 @@ -no-member:24:Client.__init__:Class 'Provider' has no 'cattribute' member:INFERENCE -no-member:34:Client.use_method:Instance of 'Provider' has no 'hophophop' member:INFERENCE -no-member:39:Client.use_attr:Instance of 'Provider' has no 'attribute' member:INFERENCE -no-member:51:Client.test_bt_types:Instance of 'list' has no 'apppend' member:INFERENCE -no-member:53:Client.test_bt_types:Instance of 'dict' has no 'set' member:INFERENCE -no-member:55:Client.test_bt_types:Instance of 'tuple' has no 'append' member:INFERENCE -no-member:57:Client.test_bt_types:Instance of 'str' has no 'loower' member:INFERENCE -no-member:59:Client.test_bt_types:Instance of 'int' has no 'whatever' member:INFERENCE -no-member:65:Client.test_no_false_positives:Super of 'Client' has no 'misssing' member:INFERENCE -no-member:86::Instance of 'int' has no 'lower' member:INFERENCE_FAILURE -no-member:97::Instance of 'Client' has no 'indeed' member:INFERENCE -no-member:104::Class 'Client' has no 'missing' member:INFERENCE -no-member:110::Class 'Client' has no 'missing' member:INFERENCE -no-member:124::Class 'Client' has no 'missing' member:INFERENCE -no-member:171:NoDunderNameInInstance.__init__:Instance of 'NoDunderNameInInstance' has no '__name__' member:INFERENCE diff --git a/pymode/libs/pylint/test/functional/membership_protocol.py b/pymode/libs/pylint/test/functional/membership_protocol.py deleted file mode 100644 index 6b514d84..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol.py +++ /dev/null @@ -1,123 +0,0 @@ -# pylint: disable=missing-docstring,pointless-statement,expression-not-assigned,too-few-public-methods,import-error,no-init,wrong-import-position - -# standard types -1 in [1, 2, 3] -1 in {'a': 1, 'b': 2} -1 in {1, 2, 3} -1 in (1, 2, 3) -'1' in "123" -'1' in u"123" -'1' in bytearray(b"123") -1 in frozenset([1, 2, 3]) - -# comprehensions -1 in [x ** 2 % 10 for x in range(10)] -1 in {x ** 2 % 10 for x in range(10)} -1 in {x: x ** 2 % 10 for x in range(10)} - -# iterators -1 in iter([1, 2, 3]) - -# generator -def count(upto=float("inf")): - i = 0 - while True: - if i > upto: - break - yield i - i += 1 - -10 in count(upto=10) - -# custom instance -class UniversalContainer(object): - def __contains__(self, key): - return True - -42 in UniversalContainer() - -# custom iterable -class CustomIterable(object): - def __iter__(self): - return iter((1, 2, 3)) -3 in CustomIterable() - -# old-style iterable -class OldStyleIterable(object): - def __getitem__(self, key): - if key < 10: - return 2 ** key - else: - raise IndexError("bad index") -64 in OldStyleIterable() - -# do not emit warning if class has unknown bases -from some_missing_module import ImportedClass - -class MaybeIterable(ImportedClass): - pass - -10 in MaybeIterable() - -# do not emit warning inside mixins/abstract/base classes -class UsefulMixin(object): - stuff = None - - def get_stuff(self): - return self.stuff - - def act(self, thing): - stuff = self.get_stuff() - if thing in stuff: - pass - -class BaseThing(object): - valid_values = None - - def validate(self, value): - if self.valid_values is None: - return True - else: - # error should not be emitted here - return value in self.valid_values - -class AbstractThing(object): - valid_values = None - - def validate(self, value): - if self.valid_values is None: - return True - else: - # error should not be emitted here - return value in self.valid_values - -# class is not named as abstract -# but still is deduceably abstract -class Thing(object): - valid_values = None - - def __init__(self): - self._init_values() - - def validate(self, value): - if self.valid_values is None: - return True - else: - # error should not be emitted here - return value in self.valid_values - - def _init_values(self): - raise NotImplementedError - -# error cases -42 in 42 # [unsupported-membership-test] -42 not in None # [unsupported-membership-test] -42 in 8.5 # [unsupported-membership-test] - -class EmptyClass(object): - pass - -42 not in EmptyClass() # [unsupported-membership-test] -42 in EmptyClass # [unsupported-membership-test] -42 not in count # [unsupported-membership-test] -42 in range # [unsupported-membership-test] diff --git a/pymode/libs/pylint/test/functional/membership_protocol.txt b/pymode/libs/pylint/test/functional/membership_protocol.txt deleted file mode 100644 index edb2227a..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol.txt +++ /dev/null @@ -1,7 +0,0 @@ -unsupported-membership-test:113::Value '42' doesn't support membership test -unsupported-membership-test:114::Value 'None' doesn't support membership test -unsupported-membership-test:115::Value '8.5' doesn't support membership test -unsupported-membership-test:120::Value 'EmptyClass()' doesn't support membership test -unsupported-membership-test:121::Value 'EmptyClass' doesn't support membership test -unsupported-membership-test:122::Value 'count' doesn't support membership test -unsupported-membership-test:123::Value 'range' doesn't support membership test diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py2.py b/pymode/libs/pylint/test/functional/membership_protocol_py2.py deleted file mode 100644 index 1a016377..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py2.py +++ /dev/null @@ -1,36 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods,no-init,no-self-use,unused-argument,pointless-statement,expression-not-assigned,undefined-variable - -# metaclasses that support membership test protocol -class MetaIterable(type): - def __iter__(cls): - return iter((1, 2, 3)) - -class MetaOldIterable(type): - def __getitem__(cls, key): - if key < 10: - return key ** 2 - else: - raise IndexError("bad index") - -class MetaContainer(type): - def __contains__(cls, key): - return False - - -class IterableClass(object): - __metaclass__ = MetaIterable - -class OldIterableClass(object): - __metaclass__ = MetaOldIterable - -class ContainerClass(object): - __metaclass__ = MetaContainer - - -def test(): - 1 in IterableClass - 1 in OldIterableClass - 1 in ContainerClass - 1 in IterableClass() # [unsupported-membership-test] - 1 in OldIterableClass() # [unsupported-membership-test] - 1 in ContainerClass() # [unsupported-membership-test] diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py2.rc b/pymode/libs/pylint/test/functional/membership_protocol_py2.rc deleted file mode 100644 index c78f32fa..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py2.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -max_pyver=3.0 - diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py2.txt b/pymode/libs/pylint/test/functional/membership_protocol_py2.txt deleted file mode 100644 index 4ba75755..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py2.txt +++ /dev/null @@ -1,3 +0,0 @@ -unsupported-membership-test:34:test:Value 'IterableClass()' doesn't support membership test -unsupported-membership-test:35:test:Value 'OldIterableClass()' doesn't support membership test -unsupported-membership-test:36:test:Value 'ContainerClass()' doesn't support membership test diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py3.py b/pymode/libs/pylint/test/functional/membership_protocol_py3.py deleted file mode 100644 index 6a77f203..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py3.py +++ /dev/null @@ -1,36 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods,no-init,no-self-use,unused-argument,pointless-statement,expression-not-assigned - -# metaclasses that support membership test protocol -class MetaIterable(type): - def __iter__(cls): - return iter((1, 2, 3)) - -class MetaOldIterable(type): - def __getitem__(cls, key): - if key < 10: - return key ** 2 - else: - raise IndexError("bad index") - -class MetaContainer(type): - def __contains__(cls, key): - return False - - -class IterableClass(metaclass=MetaOldIterable): - pass - -class OldIterableClass(metaclass=MetaOldIterable): - pass - -class ContainerClass(metaclass=MetaContainer): - pass - - -def test(): - 1 in IterableClass - 1 in OldIterableClass - 1 in ContainerClass - 1 in IterableClass() # [unsupported-membership-test] - 1 in OldIterableClass() # [unsupported-membership-test] - 1 in ContainerClass() # [unsupported-membership-test] diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py3.rc b/pymode/libs/pylint/test/functional/membership_protocol_py3.rc deleted file mode 100644 index 9bf6df0e..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py3.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -min_pyver=3.0 - diff --git a/pymode/libs/pylint/test/functional/membership_protocol_py3.txt b/pymode/libs/pylint/test/functional/membership_protocol_py3.txt deleted file mode 100644 index 4ba75755..00000000 --- a/pymode/libs/pylint/test/functional/membership_protocol_py3.txt +++ /dev/null @@ -1,3 +0,0 @@ -unsupported-membership-test:34:test:Value 'IterableClass()' doesn't support membership test -unsupported-membership-test:35:test:Value 'OldIterableClass()' doesn't support membership test -unsupported-membership-test:36:test:Value 'ContainerClass()' doesn't support membership test diff --git a/pymode/libs/pylint/test/functional/method_hidden.py b/pymode/libs/pylint/test/functional/method_hidden.py deleted file mode 100644 index e0588aff..00000000 --- a/pymode/libs/pylint/test/functional/method_hidden.py +++ /dev/null @@ -1,16 +0,0 @@ -# pylint: disable=too-few-public-methods,print-statement -"""check method hidding ancestor attribute -""" -from __future__ import print_function - -class Abcd(object): - """dummy""" - def __init__(self): - self.abcd = 1 - -class Cdef(Abcd): - """dummy""" - def abcd(self): # [method-hidden] - """test - """ - print(self) diff --git a/pymode/libs/pylint/test/functional/method_hidden.txt b/pymode/libs/pylint/test/functional/method_hidden.txt deleted file mode 100644 index 7dfb8d3e..00000000 --- a/pymode/libs/pylint/test/functional/method_hidden.txt +++ /dev/null @@ -1 +0,0 @@ -method-hidden:13:Cdef.abcd:An attribute defined in functional.method_hidden line 9 hides this method diff --git a/pymode/libs/pylint/test/functional/misplaced_bare_raise.py b/pymode/libs/pylint/test/functional/misplaced_bare_raise.py deleted file mode 100644 index d54e22a9..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_bare_raise.py +++ /dev/null @@ -1,75 +0,0 @@ -# pylint: disable=missing-docstring, broad-except, unreachable -# pylint: disable=unused-variable, too-few-public-methods, invalid-name - -try: - raise # [misplaced-bare-raise] -except Exception: - pass - -try: - pass -except Exception: - raise - -# pylint: disable=misplaced-comparison-constant -try: - pass -except Exception: - if 1 == 2: - raise - -def test(): - try: - pass - except Exception: - def chest(): - try: - pass - except Exception: - raise - raise - -def test1(): - try: - if 1 > 2: - def best(): - raise # [misplaced-bare-raise] - except Exception: - pass - raise # [misplaced-bare-raise] -raise # [misplaced-bare-raise] - -try: - pass -finally: - # This might work or might not to, depending if there's - # an error raised inside the try block. But relying on this - # behaviour can be error prone, so we decided to warn - # against it. - raise # [misplaced-bare-raise] - - -class A(object): - try: - pass - except Exception: - raise - raise # [misplaced-bare-raise] - -# This works in Python 2, but the intent is nevertheless -# unclear. It will also not work on Python 3, so it's best -# not to rely on it. -exc = None -try: - 1/0 -except ZeroDivisionError as exc: - pass -if exc: - raise # [misplaced-bare-raise] - -# Don't emit if we're in ``__exit__``. -class ContextManager(object): - def __enter__(self): - return self - def __exit__(self, *args): - raise diff --git a/pymode/libs/pylint/test/functional/misplaced_bare_raise.txt b/pymode/libs/pylint/test/functional/misplaced_bare_raise.txt deleted file mode 100644 index 013e58c1..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_bare_raise.txt +++ /dev/null @@ -1,7 +0,0 @@ -misplaced-bare-raise:5::The raise statement is not inside an except clause -misplaced-bare-raise:36:test1.best:The raise statement is not inside an except clause -misplaced-bare-raise:39:test1:The raise statement is not inside an except clause -misplaced-bare-raise:40::The raise statement is not inside an except clause -misplaced-bare-raise:49::The raise statement is not inside an except clause -misplaced-bare-raise:57:A:The raise statement is not inside an except clause -misplaced-bare-raise:68::The raise statement is not inside an except clause diff --git a/pymode/libs/pylint/test/functional/misplaced_comparison_constant.py b/pymode/libs/pylint/test/functional/misplaced_comparison_constant.py deleted file mode 100644 index 45a03d1e..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_comparison_constant.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Check that the constants are on the right side of the comparisons""" - -# pylint: disable=singleton-comparison, missing-docstring, too-few-public-methods - -class MyClass(object): - def __init__(self): - self.attr = 1 - - def dummy_return(self): - return self.attr - -def dummy_return(): - return 2 - -def bad_comparisons(): - """this is not ok""" - instance = MyClass() - for i in range(10): - if 5 <= i: # [misplaced-comparison-constant] - pass - if 1 == i: # [misplaced-comparison-constant] - pass - if 3 < dummy_return(): # [misplaced-comparison-constant] - pass - if 4 != instance.dummy_return(): # [misplaced-comparison-constant] - pass - if 1 == instance.attr: # [misplaced-comparison-constant] - pass - if "aaa" == instance.attr: # [misplaced-comparison-constant] - pass - -def good_comparison(): - """this is ok""" - for i in range(10): - if i == 5: - pass diff --git a/pymode/libs/pylint/test/functional/misplaced_comparison_constant.txt b/pymode/libs/pylint/test/functional/misplaced_comparison_constant.txt deleted file mode 100644 index a7f0d956..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_comparison_constant.txt +++ /dev/null @@ -1,6 +0,0 @@ -misplaced-comparison-constant:19:bad_comparisons:Comparison should be i >= 5 -misplaced-comparison-constant:21:bad_comparisons:Comparison should be i == 1 -misplaced-comparison-constant:23:bad_comparisons:Comparison should be dummy_return() > 3 -misplaced-comparison-constant:25:bad_comparisons:Comparison should be instance.dummy_return() != 4 -misplaced-comparison-constant:27:bad_comparisons:Comparison should be instance.attr == 1 -misplaced-comparison-constant:29:bad_comparisons:Comparison should be instance.attr == 'aaa' diff --git a/pymode/libs/pylint/test/functional/misplaced_future.py b/pymode/libs/pylint/test/functional/misplaced_future.py deleted file mode 100644 index 34404856..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_future.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Test that __future__ is not the first statement after the docstring.""" -import collections -from __future__ import print_function # [misplaced-future] -from __future__ import with_statement - -DATA = collections diff --git a/pymode/libs/pylint/test/functional/misplaced_future.txt b/pymode/libs/pylint/test/functional/misplaced_future.txt deleted file mode 100644 index bc874cf1..00000000 --- a/pymode/libs/pylint/test/functional/misplaced_future.txt +++ /dev/null @@ -1 +0,0 @@ -misplaced-future:3::"__future__ import is not the first non docstring statement" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/missing_docstring.py b/pymode/libs/pylint/test/functional/missing_docstring.py deleted file mode 100644 index 607f2e6f..00000000 --- a/pymode/libs/pylint/test/functional/missing_docstring.py +++ /dev/null @@ -1,54 +0,0 @@ -# [missing-docstring] -# pylint: disable=too-few-public-methods - -def public_documented(): - """It has a docstring.""" - - -def _private_undocumented(): - # Doesn't need a docstring - pass - - -def _private_documented(): - """It has a docstring.""" - - -class ClassDocumented(object): - """It has a docstring.""" - - -class ClassUndocumented(object): # [missing-docstring] - pass - - -def public_undocumented(): # [missing-docstring] - pass - - -def __sizeof__(): - # Special - pass - - -def __mangled(): - pass - - -class Property(object): - """Don't warn about setters and deleters.""" - - def __init__(self): - self._value = None - - @property - def test(self): - """Default docstring for setters and deleters.""" - - @test.setter - def test(self, value): - self._value = value - - @test.deleter - def test(self): - pass diff --git a/pymode/libs/pylint/test/functional/missing_docstring.txt b/pymode/libs/pylint/test/functional/missing_docstring.txt deleted file mode 100644 index 2680319b..00000000 --- a/pymode/libs/pylint/test/functional/missing_docstring.txt +++ /dev/null @@ -1,3 +0,0 @@ -missing-docstring:1::Missing module docstring -missing-docstring:21:ClassUndocumented:Missing class docstring -missing-docstring:25:public_undocumented:Missing function docstring diff --git a/pymode/libs/pylint/test/functional/missing_final_newline.py b/pymode/libs/pylint/test/functional/missing_final_newline.py deleted file mode 100644 index 370f902b..00000000 --- a/pymode/libs/pylint/test/functional/missing_final_newline.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This file does not have a final newline.""" -from __future__ import print_function -# +1:[missing-final-newline] -print(1) \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/missing_final_newline.txt b/pymode/libs/pylint/test/functional/missing_final_newline.txt deleted file mode 100644 index b53c980a..00000000 --- a/pymode/libs/pylint/test/functional/missing_final_newline.txt +++ /dev/null @@ -1 +0,0 @@ -missing-final-newline:4::Final newline missing diff --git a/pymode/libs/pylint/test/functional/missing_self_argument.py b/pymode/libs/pylint/test/functional/missing_self_argument.py deleted file mode 100644 index 6477fcf4..00000000 --- a/pymode/libs/pylint/test/functional/missing_self_argument.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Checks that missing self in method defs don't crash Pylint.""" - - - -class MyClass(object): - """A class with some methods missing self args.""" - - def __init__(self): - self.var = "var" - - def method(): # [no-method-argument] - """A method without a self argument.""" - - def setup(): # [no-method-argument] - """A method without a self argument, but usage.""" - self.var = 1 # [undefined-variable] - - def correct(self): - """Correct.""" - self.var = "correct" diff --git a/pymode/libs/pylint/test/functional/missing_self_argument.txt b/pymode/libs/pylint/test/functional/missing_self_argument.txt deleted file mode 100644 index 1deef186..00000000 --- a/pymode/libs/pylint/test/functional/missing_self_argument.txt +++ /dev/null @@ -1,6 +0,0 @@ -no-method-argument:11:MyClass.method:Method has no argument -no-method-argument:13:MyClass.met:"""Method has no argument -"" -" -no-method-argument:14:MyClass.setup:Method has no argument -undefined-variable:16:MyClass.setup:Undefined variable 'self' diff --git a/pymode/libs/pylint/test/functional/mixed_indentation.py b/pymode/libs/pylint/test/functional/mixed_indentation.py deleted file mode 100644 index 724ecff7..00000000 --- a/pymode/libs/pylint/test/functional/mixed_indentation.py +++ /dev/null @@ -1,10 +0,0 @@ -"""test mixed tabs and spaces""" -from __future__ import print_function - -def spaces_func(): - """yo""" - print("yo") - -def tab_func(): - """yo""" # [mixed-indentation] - print("yo") # [mixed-indentation] diff --git a/pymode/libs/pylint/test/functional/mixed_indentation.txt b/pymode/libs/pylint/test/functional/mixed_indentation.txt deleted file mode 100644 index d4857e66..00000000 --- a/pymode/libs/pylint/test/functional/mixed_indentation.txt +++ /dev/null @@ -1,2 +0,0 @@ -mixed-indentation:9::Found indentation with tabs instead of spaces -mixed-indentation:10::Found indentation with tabs instead of spaces diff --git a/pymode/libs/pylint/test/functional/multiple_imports.py b/pymode/libs/pylint/test/functional/multiple_imports.py deleted file mode 100644 index 9008dcc5..00000000 --- a/pymode/libs/pylint/test/functional/multiple_imports.py +++ /dev/null @@ -1,2 +0,0 @@ -# pylint: disable=missing-docstring, unused-import -import os, socket # [multiple-imports] diff --git a/pymode/libs/pylint/test/functional/multiple_imports.txt b/pymode/libs/pylint/test/functional/multiple_imports.txt deleted file mode 100644 index a5df51e6..00000000 --- a/pymode/libs/pylint/test/functional/multiple_imports.txt +++ /dev/null @@ -1 +0,0 @@ -multiple-imports:2::Multiple imports on one line (os, socket) diff --git a/pymode/libs/pylint/test/functional/name_styles.py b/pymode/libs/pylint/test/functional/name_styles.py deleted file mode 100644 index a100bd54..00000000 --- a/pymode/libs/pylint/test/functional/name_styles.py +++ /dev/null @@ -1,119 +0,0 @@ -"""Test for the invalid-name warning.""" -# pylint: disable=no-absolute-import -from __future__ import print_function -import abc -import collections - -GOOD_CONST_NAME = '' -bad_const_name = 0 # [invalid-name] - - -def BADFUNCTION_name(): # [invalid-name] - """Bad function name.""" - BAD_LOCAL_VAR = 1 # [invalid-name] - print(BAD_LOCAL_VAR) - - -def func_bad_argname(NOT_GOOD): # [invalid-name] - """Function with a badly named argument.""" - return NOT_GOOD - - -def no_nested_args(arg1, arg21, arg22): - """Well-formed function.""" - print(arg1, arg21, arg22) - - -class bad_class_name(object): # [invalid-name] - """Class with a bad name.""" - - -class CorrectClassName(object): - """Class with a good name.""" - - def __init__(self): - self._good_private_name = 10 - self.__good_real_private_name = 11 - self.good_attribute_name = 12 - self._Bad_AtTR_name = None # [invalid-name] - self.Bad_PUBLIC_name = None # [invalid-name] - - zz = 'Bad Class Attribute' # [invalid-name] - GOOD_CLASS_ATTR = 'Good Class Attribute' - - def BadMethodName(self): # [invalid-name] - """A Method with a bad name.""" - - def good_method_name(self): - """A method with a good name.""" - - def __DunDER_IS_not_free_for_all__(self): # [invalid-name] - """Another badly named method.""" - - -class DerivedFromCorrect(CorrectClassName): - """A derived class with an invalid inherited members. - - Derived attributes and methods with invalid names do not trigger warnings. - """ - zz = 'Now a good class attribute' - - def __init__(self): - super(DerivedFromCorrect, self).__init__() - self._Bad_AtTR_name = None # Ignored - - def BadMethodName(self): - """Ignored since the method is in the interface.""" - - -V = [WHAT_Ever_inListComp for WHAT_Ever_inListComp in GOOD_CONST_NAME] - -def class_builder(): - """Function returning a class object.""" - - class EmbeddedClass(object): - """Useless class.""" - - return EmbeddedClass - -# +1:[invalid-name] -BAD_NAME_FOR_CLASS = collections.namedtuple('Named', ['tuple']) -NEXT_BAD_NAME_FOR_CLASS = class_builder() # [invalid-name] - -GoodName = collections.namedtuple('Named', ['tuple']) -ToplevelClass = class_builder() - -# Aliases for classes have the same name constraints. -AlsoCorrect = CorrectClassName -NOT_CORRECT = CorrectClassName # [invalid-name] - - -def test_globals(): - """Names in global statements are also checked.""" - global NOT_CORRECT - global AlsoCorrect # [invalid-name] - NOT_CORRECT = 1 - AlsoCorrect = 2 - - -class FooClass(object): - """A test case for property names. - - Since by default, the regex for attributes is the same as the one - for method names, we check the warning messages to contain the - string 'attribute'. - """ - @property - def PROPERTY_NAME(self): # [invalid-name] - """Ignored.""" - pass - - @abc.abstractproperty - def ABSTRACT_PROPERTY_NAME(self): # [invalid-name] - """Ignored.""" - pass - - @PROPERTY_NAME.setter - def PROPERTY_NAME_SETTER(self): # [invalid-name] - """Ignored.""" - pass diff --git a/pymode/libs/pylint/test/functional/name_styles.rc b/pymode/libs/pylint/test/functional/name_styles.rc deleted file mode 100644 index 1a63e671..00000000 --- a/pymode/libs/pylint/test/functional/name_styles.rc +++ /dev/null @@ -1,5 +0,0 @@ -[testoptions] -min_pyver=2.6 - -[Messages Control] -disable=too-few-public-methods,abstract-class-not-used,global-statement diff --git a/pymode/libs/pylint/test/functional/name_styles.txt b/pymode/libs/pylint/test/functional/name_styles.txt deleted file mode 100644 index 79352aa7..00000000 --- a/pymode/libs/pylint/test/functional/name_styles.txt +++ /dev/null @@ -1,17 +0,0 @@ -invalid-name:8::"Invalid constant name ""bad_const_name""" -invalid-name:11:BADFUNCTION_name:"Invalid function name ""BADFUNCTION_name""" -invalid-name:13:BADFUNCTION_name:"Invalid variable name ""BAD_LOCAL_VAR""" -invalid-name:17:func_bad_argname:"Invalid argument name ""NOT_GOOD""" -invalid-name:27:bad_class_name:"Invalid class name ""bad_class_name""" -invalid-name:38:CorrectClassName.__init__:"Invalid attribute name ""_Bad_AtTR_name""" -invalid-name:39:CorrectClassName.__init__:"Invalid attribute name ""Bad_PUBLIC_name""" -invalid-name:41:CorrectClassName:"Invalid class attribute name ""zz""" -invalid-name:44:CorrectClassName.BadMethodName:"Invalid method name ""BadMethodName""":INFERENCE -invalid-name:50:CorrectClassName.__DunDER_IS_not_free_for_all__:"Invalid method name ""__DunDER_IS_not_free_for_all__""":INFERENCE -invalid-name:80::"Invalid class name ""BAD_NAME_FOR_CLASS""" -invalid-name:81::"Invalid class name ""NEXT_BAD_NAME_FOR_CLASS""" -invalid-name:88::"Invalid class name ""NOT_CORRECT""" -invalid-name:94:test_globals:"Invalid constant name ""AlsoCorrect""" -invalid-name:107:FooClass.PROPERTY_NAME:"Invalid attribute name ""PROPERTY_NAME""":INFERENCE -invalid-name:112:FooClass.ABSTRACT_PROPERTY_NAME:"Invalid attribute name ""ABSTRACT_PROPERTY_NAME""":INFERENCE -invalid-name:117:FooClass.PROPERTY_NAME_SETTER:"Invalid attribute name ""PROPERTY_NAME_SETTER""":INFERENCE diff --git a/pymode/libs/pylint/test/functional/namedtuple_member_inference.py b/pymode/libs/pylint/test/functional/namedtuple_member_inference.py deleted file mode 100644 index 4488ceb0..00000000 --- a/pymode/libs/pylint/test/functional/namedtuple_member_inference.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Test namedtuple attributes. - -Regression test for: -https://bitbucket.org/logilab/pylint/issue/93/pylint-crashes-on-namedtuple-attribute -""" -from __future__ import absolute_import, print_function -from collections import namedtuple - -__revision__ = None - -Thing = namedtuple('Thing', ()) - -Fantastic = namedtuple('Fantastic', ['foo']) - -def test(): - """Test member access in named tuples.""" - print(Thing.x) # [no-member] - fan = Fantastic(1) - print(fan.foo) - # Should not raise protected-access. - fan2 = fan._replace(foo=2) - print(fan2.foo) diff --git a/pymode/libs/pylint/test/functional/namedtuple_member_inference.txt b/pymode/libs/pylint/test/functional/namedtuple_member_inference.txt deleted file mode 100644 index 1532814c..00000000 --- a/pymode/libs/pylint/test/functional/namedtuple_member_inference.txt +++ /dev/null @@ -1,2 +0,0 @@ -no-member:17:test:Class 'Thing' has no 'x' member:INFERENCE -no-member:23:test:Instance of 'Fantastic' has no 'foo' member:INFERENCE diff --git a/pymode/libs/pylint/test/functional/names_in__all__.py b/pymode/libs/pylint/test/functional/names_in__all__.py deleted file mode 100644 index afcb2cd2..00000000 --- a/pymode/libs/pylint/test/functional/names_in__all__.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable=too-few-public-methods,no-self-use, no-absolute-import,import-error -"""Test Pylint's use of __all__. - -* NonExistant is not defined in this module, and it is listed in - __all__. An error is expected. - -* This module imports path and republished it in __all__. No errors - are expected. -""" -from __future__ import print_function -from os import path -from collections import deque -from missing import Missing - -__all__ = [ - 'Dummy', - '', # [undefined-all-variable] - Missing, - SomeUndefined, # [undefined-variable] - 'NonExistant', # [undefined-all-variable] - 'path', - 'func', # [undefined-all-variable] - 'inner', # [undefined-all-variable] - 'InnerKlass', deque.__name__] # [undefined-all-variable] - - -class Dummy(object): - """A class defined in this module.""" - pass - -DUMMY = Dummy() - -def function(): - """Function docstring - """ - pass - -function() - -class Klass(object): - """A klass which contains a function""" - def func(self): - """A klass method""" - inner = None - print(inner) - - class InnerKlass(object): - """A inner klass""" - pass diff --git a/pymode/libs/pylint/test/functional/names_in__all__.txt b/pymode/libs/pylint/test/functional/names_in__all__.txt deleted file mode 100644 index 94873296..00000000 --- a/pymode/libs/pylint/test/functional/names_in__all__.txt +++ /dev/null @@ -1,6 +0,0 @@ -undefined-all-variable:17::Undefined variable name '' in __all__ -undefined-variable:19::Undefined variable 'SomeUndefined' -undefined-all-variable:20::Undefined variable name 'NonExistant' in __all__ -undefined-all-variable:22::Undefined variable name 'func' in __all__ -undefined-all-variable:23::Undefined variable name 'inner' in __all__ -undefined-all-variable:24::Undefined variable name 'InnerKlass' in __all__ diff --git a/pymode/libs/pylint/test/functional/newstyle__slots__.py b/pymode/libs/pylint/test/functional/newstyle__slots__.py deleted file mode 100644 index 306d6a14..00000000 --- a/pymode/libs/pylint/test/functional/newstyle__slots__.py +++ /dev/null @@ -1,17 +0,0 @@ -# pylint: disable=R0903 -"""test __slots__ on old style class""" - - -class NewStyleClass(object): - """correct usage""" - __slots__ = ('a', 'b') - - -class OldStyleClass: # <3.0:[old-style-class,slots-on-old-class] - """bad usage""" - __slots__ = ('a', 'b') - - def __init__(self): - pass - -__slots__ = 'hop' diff --git a/pymode/libs/pylint/test/functional/newstyle__slots__.txt b/pymode/libs/pylint/test/functional/newstyle__slots__.txt deleted file mode 100644 index 43203906..00000000 --- a/pymode/libs/pylint/test/functional/newstyle__slots__.txt +++ /dev/null @@ -1,2 +0,0 @@ -old-style-class:10:OldStyleClass:Old-style class defined. -slots-on-old-class:10:OldStyleClass:Use of __slots__ on an old style class:INFERENCE diff --git a/pymode/libs/pylint/test/functional/newstyle_properties.py b/pymode/libs/pylint/test/functional/newstyle_properties.py deleted file mode 100644 index 110fa3b4..00000000 --- a/pymode/libs/pylint/test/functional/newstyle_properties.py +++ /dev/null @@ -1,53 +0,0 @@ -# pylint: disable=too-few-public-methods -"""Test properties on old style classes and property.setter/deleter usage""" - - -def getter(self): - """interesting""" - return self - -class CorrectClass(object): - """correct usage""" - method = property(getter, doc='hop') - -class OldStyleClass: # <3.0:[old-style-class] - """bad usage""" - method = property(getter, doc='hop') # <3.0:[property-on-old-class] - - def __init__(self): - pass - - -def decorator(func): - """Redefining decorator.""" - def wrapped(self): - """Wrapper function.""" - return func(self) - return wrapped - - -class SomeClass(object): - """another docstring""" - - def __init__(self): - self._prop = None - - @property - def prop(self): - """I'm the 'prop' property.""" - return self._prop - - @prop.setter - def prop(self, value): - """I'm the 'prop' property.""" - self._prop = value - - @prop.deleter - def prop(self): - """I'm the 'prop' property.""" - del self._prop - - @decorator - def noregr(self): - """Just a normal method with a decorator.""" - return self.prop diff --git a/pymode/libs/pylint/test/functional/newstyle_properties.txt b/pymode/libs/pylint/test/functional/newstyle_properties.txt deleted file mode 100644 index a16686b6..00000000 --- a/pymode/libs/pylint/test/functional/newstyle_properties.txt +++ /dev/null @@ -1,2 +0,0 @@ -old-style-class:13:OldStyleClass:Old-style class defined. -property-on-old-class:15:OldStyleClass:"Use of ""property"" on an old style class":INFERENCE diff --git a/pymode/libs/pylint/test/functional/no_classmethod_decorator.py b/pymode/libs/pylint/test/functional/no_classmethod_decorator.py deleted file mode 100644 index b9e51cba..00000000 --- a/pymode/libs/pylint/test/functional/no_classmethod_decorator.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Checks class methods are declared with a decorator if within the class -scope and if classmethod's argument is a member of the class -""" - -# pylint: disable=too-few-public-methods, using-constant-test, no-self-argument - -class MyClass(object): - """Some class""" - def __init__(self): - pass - - def cmethod(cls): - """class method-to-be""" - cmethod = classmethod(cmethod) # [no-classmethod-decorator] - - if True: - cmethod = classmethod(cmethod) # [no-classmethod-decorator] - - @classmethod - def my_second_method(cls): - """correct class method definition""" - - def other_method(cls): - """some method""" - cmethod2 = classmethod(other_method) # [no-classmethod-decorator] - -def helloworld(): - """says hello""" - - -MyClass.new_class_method = classmethod(helloworld) - -class MyOtherClass(object): - """Some other class""" - _make = classmethod(tuple.__new__) diff --git a/pymode/libs/pylint/test/functional/no_classmethod_decorator.txt b/pymode/libs/pylint/test/functional/no_classmethod_decorator.txt deleted file mode 100644 index ba51f0be..00000000 --- a/pymode/libs/pylint/test/functional/no_classmethod_decorator.txt +++ /dev/null @@ -1,3 +0,0 @@ -no-classmethod-decorator:14:MyClass:Consider using a decorator instead of calling classmethod -no-classmethod-decorator:17:MyClass:Consider using a decorator instead of calling classmethod -no-classmethod-decorator:25:MyClass:Consider using a decorator instead of calling classmethod diff --git a/pymode/libs/pylint/test/functional/no_name_in_module.py b/pymode/libs/pylint/test/functional/no_name_in_module.py deleted file mode 100644 index f64341a7..00000000 --- a/pymode/libs/pylint/test/functional/no_name_in_module.py +++ /dev/null @@ -1,66 +0,0 @@ -#pylint: disable=W0401,W0611,no-absolute-import,invalid-name,import-error,bare-except,broad-except,wrong-import-order,ungrouped-imports,wrong-import-position -"""check unexistant names imported are reported""" -from __future__ import print_function - -import collections.tutu # [no-name-in-module] -from collections import toto # [no-name-in-module] -toto.yo() - -from xml.etree import ElementTree -ElementTree.nonexistant_function() # [no-member] -ElementTree.another.nonexistant.function() # [no-member] -print(collections.yo) # [no-member] - -import sys -print(sys.stdout, 'hello world') -print(sys.stdoout, 'bye bye world') # [no-member] - - -import re -re.finditer('*', 'yo') - -from rie import * -from re import findiiter, compiile # [no-name-in-module,no-name-in-module] - -import os -'SOMEVAR' in os.environ # [pointless-statement] - -try: - from collections import something -except ImportError: - something = None - -try: - from collections import anything # [no-name-in-module] -except ValueError: - anything = None - -try: - import collections.missing -except ImportError: - pass - -try: - import collections.indeed_missing # [no-name-in-module] -except ValueError: - pass - -try: - import collections.emit # [no-name-in-module] -except Exception: - pass - -try: - import collections.emit1 # [no-name-in-module] -except: - pass - -try: - if something: - import collections.emit2 # [no-name-in-module] -except Exception: - pass - -from .no_self_use import Super -from .no_self_use import lala # [no-name-in-module] -from .no_self_use.bla import lala1 # [no-name-in-module] diff --git a/pymode/libs/pylint/test/functional/no_name_in_module.txt b/pymode/libs/pylint/test/functional/no_name_in_module.txt deleted file mode 100644 index ad4b7bfc..00000000 --- a/pymode/libs/pylint/test/functional/no_name_in_module.txt +++ /dev/null @@ -1,16 +0,0 @@ -no-name-in-module:5::No name 'tutu' in module 'collections' -no-name-in-module:6::No name 'toto' in module 'collections' -no-member:10::Module 'xml.etree.ElementTree' has no 'nonexistant_function' member:INFERENCE -no-member:11::Module 'xml.etree.ElementTree' has no 'another' member:INFERENCE -no-member:12::Module 'collections' has no 'yo' member:INFERENCE -no-member:16::Module 'sys' has no 'stdoout' member:INFERENCE -no-name-in-module:23::No name 'compiile' in module 're' -no-name-in-module:23::No name 'findiiter' in module 're' -pointless-statement:26::Statement seems to have no effect -no-name-in-module:34::No name 'anything' in module 'collections' -no-name-in-module:44::No name 'indeed_missing' in module 'collections' -no-name-in-module:49::No name 'emit' in module 'collections' -no-name-in-module:54::No name 'emit1' in module 'collections' -no-name-in-module:60::No name 'emit2' in module 'collections' -no-name-in-module:65::No name 'lala' in module 'functional.no_self_use' -no-name-in-module:66::No name 'bla' in module 'functional.no_self_use' diff --git a/pymode/libs/pylint/test/functional/no_self_use.py b/pymode/libs/pylint/test/functional/no_self_use.py deleted file mode 100644 index 65e12fa7..00000000 --- a/pymode/libs/pylint/test/functional/no_self_use.py +++ /dev/null @@ -1,78 +0,0 @@ -# pylint: disable=R0903,W0232,missing-docstring -"""test detection of method which could be a function""" - -from __future__ import print_function - -class Toto(object): - """bla bal abl""" - - def __init__(self): - self.aaa = 2 - - def regular_method(self): - """this method is a real method since it access to self""" - self.function_method() - - def function_method(self): # [no-self-use] - """this method isn' a real method since it doesn't need self""" - print('hello') - - -class Base(object): - """an abstract class""" - - def __init__(self): - self.aaa = 2 - - def check(self, arg): - """an abstract method, could not be a function""" - raise NotImplementedError - - -class Sub(Base): - """a concret class""" - - def check(self, arg): - """a concret method, could not be a function since it need - polymorphism benefits - """ - return arg == 0 - -class Super(object): - """same as before without abstract""" - attr = 1 - def method(self): - """regular""" - print(self.attr) - -class Sub1(Super): - """override method with need for self""" - def method(self): - """no i can not be a function""" - print(42) - - def __len__(self): - """no i can not be a function""" - print(42) - - def __cmp__(self, other): - """no i can not be a function""" - print(42) - - def __copy__(self): - return 24 - - def __getstate__(self): - return 42 - - -class Prop(object): - - @property - def count(self): - """Don't emit no-self-use for properties. - - They can't be functions and they can be part of an - API specification. - """ - return 42 diff --git a/pymode/libs/pylint/test/functional/no_self_use.txt b/pymode/libs/pylint/test/functional/no_self_use.txt deleted file mode 100644 index e68dcff9..00000000 --- a/pymode/libs/pylint/test/functional/no_self_use.txt +++ /dev/null @@ -1 +0,0 @@ -no-self-use:16:Toto.function_method:Method could be a function \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/no_self_use_py3.py b/pymode/libs/pylint/test/functional/no_self_use_py3.py deleted file mode 100644 index f4015083..00000000 --- a/pymode/libs/pylint/test/functional/no_self_use_py3.py +++ /dev/null @@ -1,12 +0,0 @@ -# pylint: disable=missing-docstring,no-init,unused-argument,invalid-name,too-few-public-methods - -class A: - def __init__(self): - self.store = {} - - def get(self, key, default=None): - return self.store.get(key, default) - -class B(A): - def get_memo(self, obj): - return super().get(obj) diff --git a/pymode/libs/pylint/test/functional/no_self_use_py3.rc b/pymode/libs/pylint/test/functional/no_self_use_py3.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/no_self_use_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/no_self_use_py3.txt b/pymode/libs/pylint/test/functional/no_self_use_py3.txt deleted file mode 100644 index 8b137891..00000000 --- a/pymode/libs/pylint/test/functional/no_self_use_py3.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pymode/libs/pylint/test/functional/no_staticmethod_decorator.py b/pymode/libs/pylint/test/functional/no_staticmethod_decorator.py deleted file mode 100644 index 9acc5d74..00000000 --- a/pymode/libs/pylint/test/functional/no_staticmethod_decorator.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Checks static methods are declared with a decorator if within the class -scope and if static method's argument is a member of the class -""" - -# pylint: disable=too-few-public-methods, using-constant-test, no-method-argument - -class MyClass(object): - """Some class""" - def __init__(self): - pass - - def smethod(): - """static method-to-be""" - smethod = staticmethod(smethod) # [no-staticmethod-decorator] - - if True: - smethod = staticmethod(smethod) # [no-staticmethod-decorator] - - @staticmethod - def my_second_method(): - """correct static method definition""" - - def other_method(): - """some method""" - smethod2 = staticmethod(other_method) # [no-staticmethod-decorator] - -def helloworld(): - """says hello""" - - -MyClass.new_static_method = staticmethod(helloworld) - -class MyOtherClass(object): - """Some other class""" - _make = staticmethod(tuple.__new__) diff --git a/pymode/libs/pylint/test/functional/no_staticmethod_decorator.txt b/pymode/libs/pylint/test/functional/no_staticmethod_decorator.txt deleted file mode 100644 index c0aea0ea..00000000 --- a/pymode/libs/pylint/test/functional/no_staticmethod_decorator.txt +++ /dev/null @@ -1,3 +0,0 @@ -no-staticmethod-decorator:14:MyClass:Consider using a decorator instead of calling staticmethod -no-staticmethod-decorator:17:MyClass:Consider using a decorator instead of calling staticmethod -no-staticmethod-decorator:25:MyClass:Consider using a decorator instead of calling staticmethod diff --git a/pymode/libs/pylint/test/functional/non_iterator_returned.py b/pymode/libs/pylint/test/functional/non_iterator_returned.py deleted file mode 100644 index d2fa7580..00000000 --- a/pymode/libs/pylint/test/functional/non_iterator_returned.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Check non-iterators returned by __iter__ """ - -# pylint: disable=too-few-public-methods, missing-docstring, no-self-use - -import six - -class FirstGoodIterator(object): - """ yields in iterator. """ - - def __iter__(self): - for index in range(10): - yield index - -class SecondGoodIterator(object): - """ __iter__ and next """ - - def __iter__(self): - return self - - def __next__(self): - """ Infinite iterator, but still an iterator """ - return 1 - - def next(self): - """Same as __next__, but for Python 2.""" - return 1 - -class ThirdGoodIterator(object): - """ Returns other iterator, not the current instance """ - - def __iter__(self): - return SecondGoodIterator() - -class FourthGoodIterator(object): - """ __iter__ returns iter(...) """ - - def __iter__(self): - return iter(range(10)) - - -class IteratorMetaclass(type): - def __next__(cls): - return 1 - - def next(cls): - return 2 - - -@six.add_metaclass(IteratorMetaclass) -class IteratorClass(object): - """Iterable through the metaclass.""" - - -class FifthGoodIterator(object): - """__iter__ returns a class which uses an iterator-metaclass.""" - def __iter__(self): - return IteratorClass - -class FileBasedIterator(object): - def __init__(self, path): - self.path = path - self.file = None - - def __iter__(self): - if self.file is not None: - self.file.close() - self.file = open(self.path) - # self file has two infered values: None and - # we don't want to emit error in this case - return self.file - - -class FirstBadIterator(object): - """ __iter__ returns a list """ - - def __iter__(self): # [non-iterator-returned] - return [] - -class SecondBadIterator(object): - """ __iter__ without next """ - - def __iter__(self): # [non-iterator-returned] - return self - -class ThirdBadIterator(object): - """ __iter__ returns an instance of another non-iterator """ - - def __iter__(self): # [non-iterator-returned] - return SecondBadIterator() - -class FourthBadIterator(object): - """__iter__ returns a class.""" - - def __iter__(self): # [non-iterator-returned] - return ThirdBadIterator diff --git a/pymode/libs/pylint/test/functional/non_iterator_returned.txt b/pymode/libs/pylint/test/functional/non_iterator_returned.txt deleted file mode 100644 index fa1d5bec..00000000 --- a/pymode/libs/pylint/test/functional/non_iterator_returned.txt +++ /dev/null @@ -1,4 +0,0 @@ -non-iterator-returned:76:FirstBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:82:SecondBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:88:ThirdBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:94:FourthBadIterator.__iter__:__iter__ returns non-iterator diff --git a/pymode/libs/pylint/test/functional/nonexistent_operator.py b/pymode/libs/pylint/test/functional/nonexistent_operator.py deleted file mode 100644 index f05a6494..00000000 --- a/pymode/libs/pylint/test/functional/nonexistent_operator.py +++ /dev/null @@ -1,15 +0,0 @@ -"""check operator use""" -# pylint: disable=invalid-name, pointless-statement -a = 1 -a += 5 -a = +a -b = ++a # [nonexistent-operator] -++a # [nonexistent-operator] -c = (++a) * b # [nonexistent-operator] - -a = 1 -a -= 5 -b = --a # [nonexistent-operator] -b = a ---a # [nonexistent-operator] -c = (--a) * b # [nonexistent-operator] diff --git a/pymode/libs/pylint/test/functional/nonexistent_operator.txt b/pymode/libs/pylint/test/functional/nonexistent_operator.txt deleted file mode 100644 index da59f414..00000000 --- a/pymode/libs/pylint/test/functional/nonexistent_operator.txt +++ /dev/null @@ -1,6 +0,0 @@ -nonexistent-operator:6::"Use of the non-existent ++ operator" -nonexistent-operator:7::"Use of the non-existent ++ operator" -nonexistent-operator:8::"Use of the non-existent ++ operator" -nonexistent-operator:12::"Use of the non-existent -- operator" -nonexistent-operator:14::"Use of the non-existent -- operator" -nonexistent-operator:15::"Use of the non-existent -- operator" diff --git a/pymode/libs/pylint/test/functional/nonlocal_and_global.py b/pymode/libs/pylint/test/functional/nonlocal_and_global.py deleted file mode 100644 index 9c9cf86f..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_and_global.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Test that a name is both nonlocal and global in the same scope.""" -# pylint: disable=missing-docstring,global-variable-not-assigned,invalid-name,nonlocal-without-binding - -def bad(): # [nonlocal-and-global] - nonlocal missing - global missing - -def good(): - nonlocal missing - def test(): - global missing - return test diff --git a/pymode/libs/pylint/test/functional/nonlocal_and_global.rc b/pymode/libs/pylint/test/functional/nonlocal_and_global.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_and_global.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/nonlocal_and_global.txt b/pymode/libs/pylint/test/functional/nonlocal_and_global.txt deleted file mode 100644 index 46f0d0fe..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_and_global.txt +++ /dev/null @@ -1 +0,0 @@ -nonlocal-and-global:4:bad:"Name 'missing' is nonlocal and global" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/nonlocal_without_binding.py b/pymode/libs/pylint/test/functional/nonlocal_without_binding.py deleted file mode 100644 index 5b8040a7..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_without_binding.py +++ /dev/null @@ -1,28 +0,0 @@ -""" Checks that reversed() receive proper argument """ -# pylint: disable=missing-docstring,invalid-name,unused-variable -# pylint: disable=too-few-public-methods,no-self-use,no-absolute-import - -def test(): - def parent(): - a = 42 - def stuff(): - nonlocal a - - c = 24 - def parent2(): - a = 42 - def stuff(): - def other_stuff(): - nonlocal a - nonlocal c - -b = 42 -def func(): - def other_func(): - nonlocal b # [nonlocal-without-binding] - -class SomeClass(object): - nonlocal x # [nonlocal-without-binding] - - def func(self): - nonlocal some_attr # [nonlocal-without-binding] diff --git a/pymode/libs/pylint/test/functional/nonlocal_without_binding.rc b/pymode/libs/pylint/test/functional/nonlocal_without_binding.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_without_binding.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/nonlocal_without_binding.txt b/pymode/libs/pylint/test/functional/nonlocal_without_binding.txt deleted file mode 100644 index 4343d68a..00000000 --- a/pymode/libs/pylint/test/functional/nonlocal_without_binding.txt +++ /dev/null @@ -1,3 +0,0 @@ -nonlocal-without-binding:22:func.other_func:nonlocal name b found without binding -nonlocal-without-binding:25:SomeClass:nonlocal name x found without binding -nonlocal-without-binding:28:SomeClass.func:nonlocal name some_attr found without binding \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/not_async_context_manager.py b/pymode/libs/pylint/test/functional/not_async_context_manager.py deleted file mode 100644 index 07a6abb7..00000000 --- a/pymode/libs/pylint/test/functional/not_async_context_manager.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Test that an async context manager receives a proper object.""" -# pylint: disable=missing-docstring, import-error, too-few-public-methods -import contextlib - -from ala import Portocala - - -@contextlib.contextmanager -def ctx_manager(): - yield - - -class ContextManager(object): - def __enter__(self): - pass - def __exit__(self, *args): - pass - -class PartialAsyncContextManager(object): - def __aenter__(self): - pass - -class SecondPartialAsyncContextManager(object): - def __aexit__(self, *args): - pass - -class UnknownBases(Portocala): - def __aenter__(self): - pass - - -class AsyncManagerMixin(object): - pass - -class GoodAsyncManager(object): - def __aenter__(self): - pass - def __aexit__(self, *args): - pass - -class InheritExit(object): - def __aexit__(self, *args): - pass - -class SecondGoodAsyncManager(InheritExit): - def __aenter__(self): - pass - - -async def bad_coro(): - async with 42: # [not-async-context-manager] - pass - async with ctx_manager(): # [not-async-context-manager] - pass - async with ContextManager(): # [not-async-context-manager] - pass - async with PartialAsyncContextManager(): # [not-async-context-manager] - pass - async with SecondPartialAsyncContextManager(): # [not-async-context-manager] - pass - - -async def good_coro(): - async with UnknownBases(): - pass - async with AsyncManagerMixin(): - pass - async with GoodAsyncManager(): - pass - async with SecondGoodAsyncManager(): - pass diff --git a/pymode/libs/pylint/test/functional/not_async_context_manager.rc b/pymode/libs/pylint/test/functional/not_async_context_manager.rc deleted file mode 100644 index 03004f2c..00000000 --- a/pymode/libs/pylint/test/functional/not_async_context_manager.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/not_async_context_manager.txt b/pymode/libs/pylint/test/functional/not_async_context_manager.txt deleted file mode 100644 index ae9fad79..00000000 --- a/pymode/libs/pylint/test/functional/not_async_context_manager.txt +++ /dev/null @@ -1,5 +0,0 @@ -not-async-context-manager:51:bad_coro:Async context manager 'int' doesn't implement __aenter__ and __aexit__. -not-async-context-manager:53:bad_coro:Async context manager 'generator' doesn't implement __aenter__ and __aexit__. -not-async-context-manager:55:bad_coro:Async context manager 'ContextManager' doesn't implement __aenter__ and __aexit__. -not-async-context-manager:57:bad_coro:Async context manager 'PartialAsyncContextManager' doesn't implement __aenter__ and __aexit__. -not-async-context-manager:59:bad_coro:Async context manager 'SecondPartialAsyncContextManager' doesn't implement __aenter__ and __aexit__. diff --git a/pymode/libs/pylint/test/functional/not_callable.py b/pymode/libs/pylint/test/functional/not_callable.py deleted file mode 100644 index c2a3ab47..00000000 --- a/pymode/libs/pylint/test/functional/not_callable.py +++ /dev/null @@ -1,112 +0,0 @@ -# pylint: disable=missing-docstring,no-self-use,too-few-public-methods - -REVISION = None - -REVISION() # [not-callable] - -def correct(): - return 1 - -REVISION = correct() - -class Correct(object): - """callable object""" - -class MetaCorrect(object): - """callable object""" - def __call__(self): - return self - -INSTANCE = Correct() -CALLABLE_INSTANCE = MetaCorrect() -CORRECT = CALLABLE_INSTANCE() -INCORRECT = INSTANCE() # [not-callable] -LIST = [] -INCORRECT = LIST() # [not-callable] -DICT = {} -INCORRECT = DICT() # [not-callable] -TUPLE = () -INCORRECT = TUPLE() # [not-callable] -INT = 1 -INCORRECT = INT() # [not-callable] - -# Test calling properties. Pylint can detect when using only the -# getter, but it doesn't infer properly when having a getter -# and a setter. -class MyProperty(property): - """ test subclasses """ - -class PropertyTest(object): - """ class """ - - def __init__(self): - self.attr = 4 - - @property - def test(self): - """ Get the attribute """ - return self.attr - - @test.setter - def test(self, value): - """ Set the attribute """ - self.attr = value - - @MyProperty - def custom(self): - """ Get the attribute """ - return self.attr - - @custom.setter - def custom(self, value): - """ Set the attribute """ - self.attr = value - -PROP = PropertyTest() -PROP.test(40) # [not-callable] -PROP.custom() # [not-callable] - -# Safe from not-callable when using properties. - -class SafeProperty(object): - @property - def static(self): - return staticmethod - - @property - def klass(self): - return classmethod - - @property - def get_lambda(self): - return lambda: None - - @property - def other_function(self): - def function(arg): - return arg - return function - - @property - def dict_builtin(self): - return dict - - @property - def range_builtin(self): - return range - - @property - def instance(self): - class Empty(object): - def __call__(self): - return 42 - return Empty() - -PROP1 = SafeProperty() -PROP1.static(2) -PROP1.klass(2) -PROP1.get_lambda() -PROP1.other_function(4) -PROP1.dict_builtin() -PROP1.range_builtin(4) -PROP1.instance() diff --git a/pymode/libs/pylint/test/functional/not_callable.txt b/pymode/libs/pylint/test/functional/not_callable.txt deleted file mode 100644 index 4928c8c8..00000000 --- a/pymode/libs/pylint/test/functional/not_callable.txt +++ /dev/null @@ -1,8 +0,0 @@ -not-callable:5::REVISION is not callable -not-callable:23::INSTANCE is not callable -not-callable:25::LIST is not callable -not-callable:27::DICT is not callable -not-callable:29::TUPLE is not callable -not-callable:31::INT is not callable -not-callable:66::PROP.test is not callable -not-callable:67::PROP.custom is not callable \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/not_context_manager.py b/pymode/libs/pylint/test/functional/not_context_manager.py deleted file mode 100644 index 3d56b603..00000000 --- a/pymode/libs/pylint/test/functional/not_context_manager.py +++ /dev/null @@ -1,135 +0,0 @@ -"""Tests that onjects used in a with statement implement context manager protocol""" - -# pylint: disable=too-few-public-methods, invalid-name, import-error, missing-docstring -# pylint: disable=no-init,wrong-import-position -# Tests no messages for objects that implement the protocol -class Manager(object): - def __enter__(self): - pass - def __exit__(self, type_, value, traceback): - pass -with Manager(): - pass - -class AnotherManager(Manager): - pass -with AnotherManager(): - pass - - -# Tests message for class that doesn't implement the protocol -class NotAManager(object): - pass -with NotAManager(): #[not-context-manager] - pass - -# Tests contextlib.contextmanager usage is recognized as correct. -from contextlib import contextmanager -@contextmanager -def dec(): - yield -with dec(): # valid use - pass - - -# Tests a message is produced when a contextlib.contextmanager -# decorated function is used without being called. -with dec: # [not-context-manager] - pass - - -# Tests no messages about context manager protocol -# if the type can't be inferred. -from missing import Missing -with Missing(): - pass - -# Tests context managers as names. - -def penelopa(): - return 42 - -hopa = dec() -tropa = penelopa() - -with tropa: # [not-context-manager] - pass - -with hopa: - pass - - -# Tests that no messages are emitted for function calls -# which return managers - -def wrapper(): - return dec() - -with wrapper(): - pass - -# Tests for properties returning managers. - -class Property(object): - - @property - def ctx(self): - return dec() - - @property - def not_ctx(self): - return 42 - - -lala = Property() -with lala.ctx: - # Don't emit when the context manager is the - # result of accessing a property. - pass - -with lala.not_ctx: # [not-context-manager] - pass - - -class TestKnownBases(Missing): - pass - -with TestKnownBases(): - pass - -# Ignore mixins. -class ManagerMixin(object): - def test(self): - with self: - pass - -class FullContextManager(ManagerMixin): - def __enter__(self): - return self - def __exit__(self, *args): - pass - -# Test a false positive with returning a generator -# from a context manager. -def generator(): - yield 42 - -@contextmanager -def context_manager_returning_generator(): - return generator() - -with context_manager_returning_generator(): - pass - -FIRST = [context_manager_returning_generator()] -with FIRST[0]: - pass - -def other_indirect_func(): - return generator() - -def not_context_manager(): - return other_indirect_func() - -with not_context_manager(): # [not-context-manager] - pass diff --git a/pymode/libs/pylint/test/functional/not_context_manager.txt b/pymode/libs/pylint/test/functional/not_context_manager.txt deleted file mode 100644 index 7fad3af0..00000000 --- a/pymode/libs/pylint/test/functional/not_context_manager.txt +++ /dev/null @@ -1,5 +0,0 @@ -not-context-manager:23::Context manager 'NotAManager' doesn't implement __enter__ and __exit__. -not-context-manager:37::Context manager 'dec' doesn't implement __enter__ and __exit__. -not-context-manager:55::Context manager 'int' doesn't implement __enter__ and __exit__. -not-context-manager:90::Context manager 'int' doesn't implement __enter__ and __exit__. -not-context-manager:134::Context manager 'generator' doesn't implement __enter__ and __exit__. diff --git a/pymode/libs/pylint/test/functional/not_in_loop.py b/pymode/libs/pylint/test/functional/not_in_loop.py deleted file mode 100644 index e16fb20b..00000000 --- a/pymode/libs/pylint/test/functional/not_in_loop.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Test that not-in-loop is detected properly.""" -# pylint: disable=missing-docstring, invalid-name, too-few-public-methods -# pylint: disable=useless-else-on-loop, using-constant-test - -while True: - def ala(): - continue # [not-in-loop] - -while True: - pass -else: - continue # [not-in-loop] - -def lala(): - continue # [not-in-loop] - -while True: - class A(object): - continue # [not-in-loop] - -for _ in range(10): - pass -else: - continue # [not-in-loop] - -for _ in range(42): - pass -else: - break # [not-in-loop] - -if True: - continue # [not-in-loop] -else: - break # [not-in-loop] - -for _ in range(10): - for _ in range(20): - pass - else: - continue - -while True: - while True: - break - else: - break - break -else: - pass - -for _ in range(1): - continue -for _ in range(42): - break diff --git a/pymode/libs/pylint/test/functional/not_in_loop.txt b/pymode/libs/pylint/test/functional/not_in_loop.txt deleted file mode 100644 index 6730bfcc..00000000 --- a/pymode/libs/pylint/test/functional/not_in_loop.txt +++ /dev/null @@ -1,8 +0,0 @@ -not-in-loop:7:ala:'continue' not properly in loop -not-in-loop:12::'continue' not properly in loop -not-in-loop:15:lala:'continue' not properly in loop -not-in-loop:19:A:'continue' not properly in loop -not-in-loop:24::'continue' not properly in loop -not-in-loop:29::'break' not properly in loop -not-in-loop:32::'continue' not properly in loop -not-in-loop:34::'break' not properly in loop \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/old_division_manually.py b/pymode/libs/pylint/test/functional/old_division_manually.py deleted file mode 100644 index aab4bd4f..00000000 --- a/pymode/libs/pylint/test/functional/old_division_manually.py +++ /dev/null @@ -1,2 +0,0 @@ -from __future__ import division -print 1 / 3 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/old_division_manually.rc b/pymode/libs/pylint/test/functional/old_division_manually.rc deleted file mode 100644 index 11dbb8d0..00000000 --- a/pymode/libs/pylint/test/functional/old_division_manually.rc +++ /dev/null @@ -1,6 +0,0 @@ -[testoptions] -max_pyver=3.0 - -[Messages Control] -disable=all -enable=old-division \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/old_style_class_py27.py b/pymode/libs/pylint/test/functional/old_style_class_py27.py deleted file mode 100644 index 675dbc6b..00000000 --- a/pymode/libs/pylint/test/functional/old_style_class_py27.py +++ /dev/null @@ -1,18 +0,0 @@ -""" Tests for old style classes. """ -# pylint: disable=no-init, too-few-public-methods, invalid-name, metaclass-assignment - -class Old: # [old-style-class] - """ old style class """ - -class Child(Old): - """ Old style class, but don't emit for it. """ - -class NotOldStyle2: - """ Because I have a metaclass at class level. """ - __metaclass__ = type - -# pylint: disable=redefined-builtin -__metaclass__ = type - -class NotOldStyle: - """ Because I have a metaclass at global level. """ diff --git a/pymode/libs/pylint/test/functional/old_style_class_py27.rc b/pymode/libs/pylint/test/functional/old_style_class_py27.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/old_style_class_py27.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/old_style_class_py27.txt b/pymode/libs/pylint/test/functional/old_style_class_py27.txt deleted file mode 100644 index c46a7b61..00000000 --- a/pymode/libs/pylint/test/functional/old_style_class_py27.txt +++ /dev/null @@ -1,2 +0,0 @@ -old-style-class:4:Old:Old-style class defined. -old-style-class:7:Child:Old-style class defined. diff --git a/pymode/libs/pylint/test/functional/pygtk_enum_crash.py b/pymode/libs/pylint/test/functional/pygtk_enum_crash.py deleted file mode 100644 index a2b8d399..00000000 --- a/pymode/libs/pylint/test/functional/pygtk_enum_crash.py +++ /dev/null @@ -1,10 +0,0 @@ -# pylint: disable=C0121 -"""http://www.logilab.org/ticket/124337""" - -import gtk - -def print_some_constant(arg=gtk.BUTTONS_OK): - """crash because gtk.BUTTONS_OK, a gtk enum type, is returned by - astroid as a constant - """ - print arg diff --git a/pymode/libs/pylint/test/functional/pygtk_enum_crash.rc b/pymode/libs/pylint/test/functional/pygtk_enum_crash.rc deleted file mode 100644 index 7a6c0afb..00000000 --- a/pymode/libs/pylint/test/functional/pygtk_enum_crash.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -requires=gtk diff --git a/pymode/libs/pylint/test/functional/pygtk_import.py b/pymode/libs/pylint/test/functional/pygtk_import.py deleted file mode 100644 index 231885e8..00000000 --- a/pymode/libs/pylint/test/functional/pygtk_import.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Import PyGTK.""" -#pylint: disable=too-few-public-methods,too-many-public-methods - -from gtk import VBox -import gtk - -class FooButton(gtk.Button): - """extend gtk.Button""" - def extend(self): - """hop""" - print self - -print gtk.Button -print VBox diff --git a/pymode/libs/pylint/test/functional/pygtk_import.rc b/pymode/libs/pylint/test/functional/pygtk_import.rc deleted file mode 100644 index 7a6c0afb..00000000 --- a/pymode/libs/pylint/test/functional/pygtk_import.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -requires=gtk diff --git a/pymode/libs/pylint/test/functional/raising_non_exception_py3.py b/pymode/libs/pylint/test/functional/raising_non_exception_py3.py deleted file mode 100644 index f7013e24..00000000 --- a/pymode/libs/pylint/test/functional/raising_non_exception_py3.py +++ /dev/null @@ -1,13 +0,0 @@ -"""The following code should emit a raising-non-exception. - -Previously, it didn't, due to a bug in the check for bad-exception-context, -which prevented further checking on the Raise node. -""" -# pylint: disable=import-error, too-few-public-methods - -from missing_module import missing - -class Exc(object): - """Not an actual exception.""" - -raise Exc from missing # [raising-non-exception] diff --git a/pymode/libs/pylint/test/functional/raising_non_exception_py3.rc b/pymode/libs/pylint/test/functional/raising_non_exception_py3.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/raising_non_exception_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/raising_non_exception_py3.txt b/pymode/libs/pylint/test/functional/raising_non_exception_py3.txt deleted file mode 100644 index 12c88628..00000000 --- a/pymode/libs/pylint/test/functional/raising_non_exception_py3.txt +++ /dev/null @@ -1 +0,0 @@ -raising-non-exception:13::Raising a new style class which doesn't inherit from BaseException \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/redefined_builtin.py b/pymode/libs/pylint/test/functional/redefined_builtin.py deleted file mode 100644 index d6bca4b7..00000000 --- a/pymode/libs/pylint/test/functional/redefined_builtin.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Tests for redefining builtins.""" -from __future__ import print_function - -def function(): - """Redefined local.""" - type = 1 # [redefined-builtin] - print(type) - -# pylint:disable=invalid-name -map = {} # [redefined-builtin] diff --git a/pymode/libs/pylint/test/functional/redefined_builtin.txt b/pymode/libs/pylint/test/functional/redefined_builtin.txt deleted file mode 100644 index fb11cd3a..00000000 --- a/pymode/libs/pylint/test/functional/redefined_builtin.txt +++ /dev/null @@ -1,2 +0,0 @@ -redefined-builtin:6:function:Redefining built-in 'type' -redefined-builtin:10::Redefining built-in 'map' diff --git a/pymode/libs/pylint/test/functional/redefined_variable_type.py b/pymode/libs/pylint/test/functional/redefined_variable_type.py deleted file mode 100644 index a66043cd..00000000 --- a/pymode/libs/pylint/test/functional/redefined_variable_type.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Checks variable types aren't redefined within a method or a function""" - -# pylint: disable=too-few-public-methods, missing-docstring, unused-variable - -_OK = True - -class MyClass(object): - - class Klass(object): - def __init__(self): - self.var2 = 'var' - - def __init__(self): - self.var = True - self.var1 = 2 - self.var2 = 1. - self.var1 = 2. # [redefined-variable-type] - self.a_str = "hello" - a_str = False - (a_str, b_str) = (1, 2) # no support for inference on tuple assignment - a_str = 2.0 if self.var else 1.0 # no support for inference on ifexpr - - def _getter(self): - return self.a_str - def _setter(self, val): - self.a_str = val - var2 = property(_getter, _setter) - - def some_method(self): - def func(): - var = 1 - test = 'bar' - var = 'baz' # [redefined-variable-type] - self.var = 1 # the rule checks for redefinitions in the scope of a function or method - test = 'foo' - myint = 2 - myint = False # [redefined-variable-type] - -_OK = "This is OK" # [redefined-variable-type] - -if _OK: - SOME_FLOAT = 1. - -def dummy_function(): - return 2 - -def other_function(): - instance = MyClass() - instance = True # [redefined-variable-type] - -SOME_FLOAT = dummy_function() # [redefined-variable-type] - -A_GLOB = None -A_GLOB = [1, 2, 3] diff --git a/pymode/libs/pylint/test/functional/redefined_variable_type.txt b/pymode/libs/pylint/test/functional/redefined_variable_type.txt deleted file mode 100644 index 3646aeb9..00000000 --- a/pymode/libs/pylint/test/functional/redefined_variable_type.txt +++ /dev/null @@ -1,6 +0,0 @@ -redefined-variable-type:17:MyClass.__init__:Redefinition of self.var1 type from int to float -redefined-variable-type:33:MyClass.some_method.func:Redefinition of var type from int to str -redefined-variable-type:37:MyClass.some_method:Redefinition of myint type from int to bool -redefined-variable-type:39::Redefinition of _OK type from bool to str -redefined-variable-type:49:other_function:Redefinition of instance type from functional.redefined_variable_type.MyClass to bool -redefined-variable-type:51::Redefinition of SOME_FLOAT type from float to int diff --git a/pymode/libs/pylint/test/functional/redundant_unittest_assert.py b/pymode/libs/pylint/test/functional/redundant_unittest_assert.py deleted file mode 100644 index 2eb73e3d..00000000 --- a/pymode/libs/pylint/test/functional/redundant_unittest_assert.py +++ /dev/null @@ -1,38 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods -""" -http://www.logilab.org/ticket/355 -If you are using assertTrue or assertFalse and the first argument is a -constant(like a string), then the assert will always be true. Therefore, -it should emit a warning message. -""" - -import unittest - -@unittest.skip("don't run this") -class Tests(unittest.TestCase): - def test_something(self): - ''' Simple test ''' - some_var = 'It should be assertEqual' - # +1:[redundant-unittest-assert] - self.assertTrue('I meant assertEqual not assertTrue', some_var) - # +1:[redundant-unittest-assert] - self.assertFalse('I meant assertEqual not assertFalse', some_var) - # +1:[redundant-unittest-assert] - self.assertTrue(True, some_var) - # +1:[redundant-unittest-assert] - self.assertFalse(False, some_var) - # +1:[redundant-unittest-assert] - self.assertFalse(None, some_var) - # +1:[redundant-unittest-assert] - self.assertTrue(0, some_var) - - self.assertTrue('should be' in some_var, some_var) - self.assertTrue(some_var, some_var) - - -@unittest.skip("don't run this") -class RegressionWithArgs(unittest.TestCase): - '''Don't fail if the bound method doesn't have arguments.''' - - def test(self): - self.run() diff --git a/pymode/libs/pylint/test/functional/redundant_unittest_assert.txt b/pymode/libs/pylint/test/functional/redundant_unittest_assert.txt deleted file mode 100644 index 889d395c..00000000 --- a/pymode/libs/pylint/test/functional/redundant_unittest_assert.txt +++ /dev/null @@ -1,6 +0,0 @@ -redundant-unittest-assert:17:Tests.test_something:"Redundant use of assertTrue with constant value 'I meant assertEqual not assertTrue'" -redundant-unittest-assert:19:Tests.test_something:"Redundant use of assertFalse with constant value 'I meant assertEqual not assertFalse'" -redundant-unittest-assert:21:Tests.test_something:"Redundant use of assertTrue with constant value True" -redundant-unittest-assert:23:Tests.test_something:"Redundant use of assertFalse with constant value False" -redundant-unittest-assert:25:Tests.test_something:"Redundant use of assertFalse with constant value None" -redundant-unittest-assert:27:Tests.test_something:"Redundant use of assertTrue with constant value 0" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/regression_no_value_for_parameter.py b/pymode/libs/pylint/test/functional/regression_no_value_for_parameter.py deleted file mode 100644 index 30308e60..00000000 --- a/pymode/libs/pylint/test/functional/regression_no_value_for_parameter.py +++ /dev/null @@ -1,15 +0,0 @@ -# pylint: disable=missing-docstring,import-error -from Unknown import Unknown - -class ConfigManager(Unknown): - - - RENAMED_SECTIONS = { - 'permissions': 'content' - } - - def test(self): - self.RENAMED_SECTIONS.items() #@ - - def items(self, sectname, raw=True): - pass diff --git a/pymode/libs/pylint/test/functional/regression_no_value_for_parameter.txt b/pymode/libs/pylint/test/functional/regression_no_value_for_parameter.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/functional/reimported.py b/pymode/libs/pylint/test/functional/reimported.py deleted file mode 100644 index 4299c1e1..00000000 --- a/pymode/libs/pylint/test/functional/reimported.py +++ /dev/null @@ -1,16 +0,0 @@ -# pylint: disable=missing-docstring,unused-import,import-error, wildcard-import,unused-wildcard-import,redefined-builtin,no-name-in-module,ungrouped-imports,wrong-import-order - -from time import sleep, sleep # [reimported] -from lala import missing, missing # [reimported] - -import missing1 -import missing1 # [reimported] - -from collections import deque -from itertools import deque # [reimported] - -from collections import OrderedDict -from itertools import OrderedDict as NotOrderedDict - -from itertools import * -from os import * diff --git a/pymode/libs/pylint/test/functional/reimported.txt b/pymode/libs/pylint/test/functional/reimported.txt deleted file mode 100644 index b15625e2..00000000 --- a/pymode/libs/pylint/test/functional/reimported.txt +++ /dev/null @@ -1,4 +0,0 @@ -reimported:3::"Reimport 'sleep' (imported line 3)" -reimported:4::"Reimport 'missing' (imported line 4)" -reimported:7::"Reimport 'missing1' (imported line 6)" -reimported:10::"Reimport 'deque' (imported line 9)" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/repeated_keyword.py b/pymode/libs/pylint/test/functional/repeated_keyword.py deleted file mode 100644 index e6834719..00000000 --- a/pymode/libs/pylint/test/functional/repeated_keyword.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Check that a keyword is not repeated in a function call - -This is somehow related to redundant-keyword, but it's not the same. -""" - -# pylint: disable=missing-docstring, invalid-name - -def test(a, b): - return a, b - -test(1, 24) -test(1, b=24, **{}) -test(1, b=24, **{'b': 24}) # [repeated-keyword] diff --git a/pymode/libs/pylint/test/functional/repeated_keyword.txt b/pymode/libs/pylint/test/functional/repeated_keyword.txt deleted file mode 100644 index 1344b15b..00000000 --- a/pymode/libs/pylint/test/functional/repeated_keyword.txt +++ /dev/null @@ -1 +0,0 @@ -repeated-keyword:13::"Got multiple values for keyword argument 'b' in function call" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/return_in_init.py b/pymode/libs/pylint/test/functional/return_in_init.py deleted file mode 100644 index 35976d20..00000000 --- a/pymode/libs/pylint/test/functional/return_in_init.py +++ /dev/null @@ -1,25 +0,0 @@ -# pylint: disable=missing-docstring,too-few-public-methods - -class MyClass(object): - - def __init__(self): # [return-in-init] - return 1 - -class MyClass2(object): - """dummy class""" - - def __init__(self): - return - - -class MyClass3(object): - """dummy class""" - - def __init__(self): - return None - -class MyClass5(object): - """dummy class""" - - def __init__(self): - self.callable = lambda: (yield None) diff --git a/pymode/libs/pylint/test/functional/return_in_init.txt b/pymode/libs/pylint/test/functional/return_in_init.txt deleted file mode 100644 index 5e708d0d..00000000 --- a/pymode/libs/pylint/test/functional/return_in_init.txt +++ /dev/null @@ -1 +0,0 @@ -return-in-init:5:MyClass.__init__:Explicit return in __init__ \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/return_outside_function.py b/pymode/libs/pylint/test/functional/return_outside_function.py deleted file mode 100644 index 449dafd6..00000000 --- a/pymode/libs/pylint/test/functional/return_outside_function.py +++ /dev/null @@ -1,2 +0,0 @@ -"""This is gramatically correct, but it's still a SyntaxError""" -return # [return-outside-function] diff --git a/pymode/libs/pylint/test/functional/return_outside_function.txt b/pymode/libs/pylint/test/functional/return_outside_function.txt deleted file mode 100644 index 0c9aa569..00000000 --- a/pymode/libs/pylint/test/functional/return_outside_function.txt +++ /dev/null @@ -1 +0,0 @@ -return-outside-function:2::Return outside function \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/simplifiable_if_statement.py b/pymode/libs/pylint/test/functional/simplifiable_if_statement.py deleted file mode 100644 index f1c594c7..00000000 --- a/pymode/libs/pylint/test/functional/simplifiable_if_statement.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Test that some if statement tests can be simplified.""" - -# pylint: disable=missing-docstring, invalid-name - - -def test_simplifiable_1(arg): - # Simple test that can be replaced by bool(arg) - if arg: # [simplifiable-if-statement] - return True - else: - return False - - -def test_simplifiable_2(arg, arg2): - # Can be reduced to bool(arg and not arg2) - if arg and not arg2: # [simplifiable-if-statement] - return True - else: - return False - - -def test_simplifiable_3(arg, arg2): - # Can be reduced to bool(arg and not arg2) - if arg and not arg2: # [simplifiable-if-statement] - var = True - else: - var = False - return var - - -def test_simplifiable_4(arg): - if arg: - var = True - else: - if arg == "arg1": # [simplifiable-if-statement] - return True - else: - return False - return var - - -def test_not_necessarily_simplifiable_1(arg, arg2): - # Can be reduced to bool(not arg and not arg2) or to - # `not all(N)`, which is a bit harder to understand - # than `any(N)` when var should be False. - if arg or arg2: - var = False - else: - var = True - return var - - -def test_not_necessarily_simplifiabile_2(arg): - # This could theoretically be reduced to `not arg or arg > 3` - # but the net result is that now the condition is harder to understand, - # because it requires understanding of an extra clause: - # * first, there is the negation of truthness with `not arg` - # * the second clause is `arg > 3`, which occurs when arg has a - # a truth value, but it implies that `arg > 3` is equivalent - # with `arg and arg > 3`, which means that the user must - # think about this assumption when evaluating `arg > 3`. - # The original form is easier to grasp. - if arg and arg <= 3: - return False - else: - return True - - -def test_not_simplifiable_3(arg): - if arg: - test_not_necessarily_simplifiabile_2(arg) - test_not_necessarily_simplifiable_1(arg, arg) - return False - else: - if arg < 3: - test_simplifiable_3(arg, 42) - return True - - -def test_not_simplifiable_4(arg): - # Not interested in multiple elifs - if arg == "any": - return True - elif test_not_simplifiable_3(arg) == arg: - return True - else: - return False - - -def test_not_simplifiable_5(arg): - # Different actions in each branch - if arg == "any": - return True - else: - var = 42 - return var - - -def test_not_simplifiable_6(arg): - # Different actions in each branch - if arg == "any": - var = 42 - else: - return True - return var - -def test_not_simplifiable_7(arg): - # Returning something different - if arg == "any": - return 4 - else: - return 5 - - -def test_not_simplifiable_8(arg): - # Only one of the branch returns something boolean - if arg == "any": - return True - else: - return 0 diff --git a/pymode/libs/pylint/test/functional/simplifiable_if_statement.txt b/pymode/libs/pylint/test/functional/simplifiable_if_statement.txt deleted file mode 100644 index 1c511090..00000000 --- a/pymode/libs/pylint/test/functional/simplifiable_if_statement.txt +++ /dev/null @@ -1,4 +0,0 @@ -simplifiable-if-statement:8:test_simplifiable_1:The if statement can be replaced with 'return bool(test)' -simplifiable-if-statement:16:test_simplifiable_2:The if statement can be replaced with 'return bool(test)' -simplifiable-if-statement:24:test_simplifiable_3:The if statement can be replaced with 'var = bool(test)' -simplifiable-if-statement:35:test_simplifiable_4:The if statement can be replaced with 'return bool(test)' diff --git a/pymode/libs/pylint/test/functional/singleton_comparison.py b/pymode/libs/pylint/test/functional/singleton_comparison.py deleted file mode 100644 index 59738f83..00000000 --- a/pymode/libs/pylint/test/functional/singleton_comparison.py +++ /dev/null @@ -1,11 +0,0 @@ -# pylint: disable=missing-docstring, invalid-name, misplaced-comparison-constant -x = 42 -a = x is None -b = x == None # [singleton-comparison] -c = x == True # [singleton-comparison] -d = x == False # [singleton-comparison] -e = True == True # [singleton-comparison] -f = x is 1 -g = 123 is "123" -h = None is x -i = None == x # [singleton-comparison] diff --git a/pymode/libs/pylint/test/functional/singleton_comparison.txt b/pymode/libs/pylint/test/functional/singleton_comparison.txt deleted file mode 100644 index fd1fa988..00000000 --- a/pymode/libs/pylint/test/functional/singleton_comparison.txt +++ /dev/null @@ -1,5 +0,0 @@ -singleton-comparison:4::Comparison to None should be 'expr is None' -singleton-comparison:5::Comparison to True should be just 'expr' or 'expr is True' -singleton-comparison:6::Comparison to False should be 'not expr' or 'expr is False' -singleton-comparison:7::Comparison to True should be just 'expr' or 'expr is True' -singleton-comparison:11::Comparison to None should be 'expr is None' diff --git a/pymode/libs/pylint/test/functional/slots_checks.py b/pymode/libs/pylint/test/functional/slots_checks.py deleted file mode 100644 index 6cd818ca..00000000 --- a/pymode/libs/pylint/test/functional/slots_checks.py +++ /dev/null @@ -1,61 +0,0 @@ -""" Checks that classes uses valid __slots__ """ - -# pylint: disable=too-few-public-methods, missing-docstring, no-absolute-import -# pylint: disable=using-constant-test -from collections import deque - -def func(): - if True: - return ("a", "b", "c") - else: - return [str(var) for var in range(3)] - - -class NotIterable(object): - def __iter_(self): - """ do nothing """ - -class Good(object): - __slots__ = () - -class SecondGood(object): - __slots__ = [] - -class ThirdGood(object): - __slots__ = ['a'] - -class FourthGood(object): - __slots__ = ('a%s' % i for i in range(10)) - -class FifthGood(object): - __slots__ = "a" - -class SixthGood(object): - __slots__ = deque(["a", "b", "c"]) - -class SeventhGood(object): - __slots__ = {"a": "b", "c": "d"} - -class Bad(object): - __slots__ = list - -class SecondBad(object): # [invalid-slots] - __slots__ = 1 - -class ThirdBad(object): - __slots__ = ('a', 2) # [invalid-slots-object] - -class FourthBad(object): # [invalid-slots] - __slots__ = NotIterable() - -class FifthBad(object): - __slots__ = ("a", "b", "") # [invalid-slots-object] - -class PotentiallyGood(object): - __slots__ = func() - -class PotentiallySecondGood(object): - __slots__ = ('a', deque.__name__) - -class PotentiallyThirdGood(object): - __slots__ = deque.__name__ diff --git a/pymode/libs/pylint/test/functional/slots_checks.txt b/pymode/libs/pylint/test/functional/slots_checks.txt deleted file mode 100644 index 7e90a4a7..00000000 --- a/pymode/libs/pylint/test/functional/slots_checks.txt +++ /dev/null @@ -1,4 +0,0 @@ -invalid-slots:42:SecondBad:Invalid __slots__ object -invalid-slots-object:46:ThirdBad:Invalid object '2' in __slots__, must contain only non empty strings -invalid-slots:48:FourthBad:Invalid __slots__ object -invalid-slots-object:52:FifthBad:"Invalid object ""''"" in __slots__, must contain only non empty strings" diff --git a/pymode/libs/pylint/test/functional/socketerror_import.py b/pymode/libs/pylint/test/functional/socketerror_import.py deleted file mode 100644 index df5de295..00000000 --- a/pymode/libs/pylint/test/functional/socketerror_import.py +++ /dev/null @@ -1,6 +0,0 @@ -"""ds""" -from __future__ import absolute_import, print_function -from socket import error -__revision__ = '$Id: socketerror_import.py,v 1.2 2005-12-28 14:58:22 syt Exp $' - -print(error) diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target.py b/pymode/libs/pylint/test/functional/star_needs_assignment_target.py deleted file mode 100644 index dd505683..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Test for a = *b""" - -FIRST = *[1, 2] # [star-needs-assignment-target] -*THIRD, FOURTH = [1, 2, 3,] diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target.rc b/pymode/libs/pylint/test/functional/star_needs_assignment_target.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target.txt b/pymode/libs/pylint/test/functional/star_needs_assignment_target.txt deleted file mode 100644 index bd8e3243..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target.txt +++ /dev/null @@ -1 +0,0 @@ -star-needs-assignment-target:3::Can use starred expression only in assignment target diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.py b/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.py deleted file mode 100644 index 58e43dba..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Test PEP 0448 -- Additional Unpacking Generalizations -https://www.python.org/dev/peps/pep-0448/ -""" - -# pylint: disable=superfluous-parens - -UNPACK_TUPLE = (*range(4), 4) -UNPACK_LIST = [*range(4), 4] -UNPACK_SET = {*range(4), 4} -UNPACK_DICT = {'a': 1, **{'b': '2'}} -UNPACK_DICT2 = {**UNPACK_DICT, "x": 1, "y": 2} -UNPACK_DICT3 = {**{'a': 1}, 'a': 2, **{'a': 3}} - -UNPACK_IN_COMP = {elem for elem in (*range(10))} # [star-needs-assignment-target] diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.rc b/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.rc deleted file mode 100644 index 71de8b63..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 diff --git a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.txt b/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.txt deleted file mode 100644 index 07770523..00000000 --- a/pymode/libs/pylint/test/functional/star_needs_assignment_target_py35.txt +++ /dev/null @@ -1 +0,0 @@ -star-needs-assignment-target:15::Can use starred expression only in assignment target \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/statement_without_effect.py b/pymode/libs/pylint/test/functional/statement_without_effect.py deleted file mode 100644 index b1aaadf8..00000000 --- a/pymode/libs/pylint/test/functional/statement_without_effect.py +++ /dev/null @@ -1,65 +0,0 @@ -"""Test for statements without effects.""" -# pylint: disable=too-few-public-methods - -# +1:[pointless-string-statement] -"""inline doc string should use a separated message""" - -__revision__ = '' - -__revision__ # [pointless-statement] - -__revision__ <= 1 # [pointless-statement] - -__revision__.lower() - -[i for i in __revision__] # [pointless-statement] - -# +1:[pointless-string-statement] -"""inline doc string should use a separated message""" - - -__revision__.lower(); # [unnecessary-semicolon] - -list() and tuple() # [expression-not-assigned] - -def to_be(): - """return 42""" - return "42" - -ANSWER = to_be() # ok -ANSWER == to_be() # [expression-not-assigned] - -to_be() or not to_be() # [expression-not-assigned] -to_be().title # [expression-not-assigned] - -GOOD_ATTRIBUTE_DOCSTRING = 42 -"""Module level attribute docstring is fine. """ - -class ClassLevelAttributeTest(object): - """ test attribute docstrings. """ - - good_attribute_docstring = 24 - """ class level attribute docstring is fine either. """ - second_good_attribute_docstring = 42 - # Comments are good. - - # empty lines are good, too. - """ Still a valid class level attribute docstring. """ - - def __init__(self): - self.attr = 42 - """ Good attribute docstring """ - attr = 24 - """ Still a good __init__ level attribute docstring. """ - val = 0 - for val in range(42): - val += attr - # +1:[pointless-string-statement] - """ Invalid attribute docstring """ - self.val = val - - def test(self): - """ invalid attribute docstrings here. """ - self.val = 42 - # +1:[pointless-string-statement] - """ this is an invalid attribute docstring. """ diff --git a/pymode/libs/pylint/test/functional/statement_without_effect.txt b/pymode/libs/pylint/test/functional/statement_without_effect.txt deleted file mode 100644 index 81fc51bc..00000000 --- a/pymode/libs/pylint/test/functional/statement_without_effect.txt +++ /dev/null @@ -1,60 +0,0 @@ -pointless-string-statement:5::String statement has no effect -pointless-statement:6::"""Statement seems to have no effect -"" -" -pointless-statement:8::"""Statement seems to have no effect -"" -" -pointless-statement:9::Statement seems to have no effect -pointless-statement:11::Statement seems to have no effect -pointless-statement:12::"""Statement seems to have no effect -"" -" -pointless-statement:15::Statement seems to have no effect -pointless-string-statement:15::"""String statement has no effect -"" -" -unnecessary-semicolon:17::"""Unnecessary semicolon -"" -" -pointless-string-statement:18::String statement has no effect -unnecessary-semicolon:18::"""Unnecessary semicolon -"" -" -expression-not-assigned:19::"""Expression """"(list()) and (tuple())"""" is assigned to nothing -"" -" -expression-not-assigned:20::"""Expression """"(list()) and (tuple())"""" is assigned to nothing -"" -" -unnecessary-semicolon:21::Unnecessary semicolon -expression-not-assigned:23::"Expression ""(list()) and (tuple())"" is assigned to nothing" -expression-not-assigned:26::"""Expression """"ANSWER == to_be()"""" is assigned to nothing -"" -" -expression-not-assigned:27::"""Expression """"ANSWER == to_be()"""" is assigned to nothing -"" -" -expression-not-assigned:28::"""Expression """"(to_be()) or (not to_be())"""" is assigned to nothing -"" -" -expression-not-assigned:29::"""Expression """"(to_be()) or (not to_be())"""" is assigned to nothing -"" -" -expression-not-assigned:30::"Expression ""ANSWER == to_be()"" is assigned to nothing" -expression-not-assigned:32::"Expression ""(to_be()) or (not to_be())"" is assigned to nothing" -expression-not-assigned:33::"Expression ""to_be().title"" is assigned to nothing" -pointless-string-statement:54:ClassLevelAttributeTest.__init__:"""String statement has no effect -"" -" -pointless-string-statement:55:ClassLevelAttributeTest.__init__:"""String statement has no effect -"" -" -pointless-string-statement:58:ClassLevelAttributeTest.__init__:String statement has no effect -pointless-string-statement:61:ClassLevelAttributeTest.test:"""String statement has no effect -"" -" -pointless-string-statement:62:ClassLevelAttributeTest.test:"""String statement has no effect -"" -" -pointless-string-statement:65:ClassLevelAttributeTest.test:String statement has no effect diff --git a/pymode/libs/pylint/test/functional/string_formatting.py b/pymode/libs/pylint/test/functional/string_formatting.py deleted file mode 100644 index 33e0c26a..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting.py +++ /dev/null @@ -1,182 +0,0 @@ -"""test for Python 3 string formatting error -""" -# pylint: disable=too-few-public-methods, import-error, unused-argument, line-too-long, no-absolute-import -import os -from missing import Missing - -__revision__ = 1 - -class Custom(object): - """ Has a __getattr__ """ - def __getattr__(self, _): - return self - -class Test(object): - """ test format attribute access """ - custom = Custom() - ids = [1, 2, 3, [4, 5, 6]] - -class Getitem(object): - """ test custom getitem for lookup access """ - def __getitem__(self, index): - return 42 - -class ReturnYes(object): - """ can't be properly infered """ - missing = Missing() - -def log(message, message_type="error"): - """ Test """ - return message - -def print_good(): - """ Good format strings """ - "{0} {1}".format(1, 2) - "{0!r:20}".format("Hello") - "{!r:20}".format("Hello") - "{a!r:20}".format(a="Hello") - "{pid}".format(pid=os.getpid()) - str("{}").format(2) - "{0.missing.length}".format(ReturnYes()) - "{1.missing.length}".format(ReturnYes()) - "{a.ids[3][1]}".format(a=Test()) - "{a[0][0]}".format(a=[[1]]) - "{[0][0]}".format({0: {0: 1}}) - "{a.test}".format(a=Custom()) - "{a.__len__}".format(a=[]) - "{a.ids.__len__}".format(a=Test()) - "{a[0]}".format(a=Getitem()) - "{a[0][0]}".format(a=[Getitem()]) - "{[0][0]}".format(["test"]) - # these are skipped - "{0} {1}".format(*[1, 2]) - "{a} {b}".format(**{'a': 1, 'b': 2}) - "{a}".format(a=Missing()) - -def pprint_bad(): - """Test string format """ - "{{}}".format(1) # [too-many-format-args] - "{} {".format() # [bad-format-string] - "{} }".format() # [bad-format-string] - "{0} {}".format(1, 2) # [format-combined-specification] - # +1: [missing-format-argument-key, unused-format-string-argument] - "{a} {b}".format(a=1, c=2) - "{} {a}".format(1, 2) # [missing-format-argument-key] - "{} {}".format(1) # [too-few-format-args] - "{} {}".format(1, 2, 3) # [too-many-format-args] - # +1: [missing-format-argument-key,missing-format-argument-key,missing-format-argument-key] - "{a} {b} {c}".format() - "{} {}".format(a=1, b=2) # [too-few-format-args] - # +1: [missing-format-argument-key, missing-format-argument-key] - "{a} {b}".format(1, 2) - "{0} {1} {a}".format(1, 2, 3) # [missing-format-argument-key] - # +1: [missing-format-attribute] - "{a.ids.__len__.length}".format(a=Test()) - "{a.ids[3][400]}".format(a=Test()) # [invalid-format-index] - "{a.ids[3]['string']}".format(a=Test()) # [invalid-format-index] - "{[0][1]}".format(["a"]) # [invalid-format-index] - "{[0][0]}".format(((1, ))) # [invalid-format-index] - # +1: [missing-format-argument-key, unused-format-string-argument] - "{b[0]}".format(a=23) - "{a[0]}".format(a=object) # [invalid-format-index] - log("{}".format(2, "info")) # [too-many-format-args] - "{0.missing}".format(2) # [missing-format-attribute] - "{0} {1} {2}".format(1, 2) # [too-few-format-args] - "{0} {1}".format(1, 2, 3) # [too-many-format-args] - "{0} {a}".format(a=4) # [too-few-format-args] - "{[0]} {}".format([4]) # [too-few-format-args] - "{[0]} {}".format([4], 5, 6) # [too-many-format-args] - -def good_issue288(*args, **kwargs): - """ Test that using kwargs does not emit a false - positive. - """ - 'Hello John Doe {0[0]}'.format(args) - 'Hello {0[name]}'.format(kwargs) - -def good_issue287(): - """ Test that the string format checker skips - format nodes which don't have a string as a parent - (but a subscript, name etc). - """ - name = 'qwerty' - ret = {'comment': ''} - ret['comment'] = 'MySQL grant {0} is set to be revoked' - ret['comment'] = ret['comment'].format(name) - return ret, name - -def nested_issue294(): - """ Test nested format fields. """ - '{0:>{1}}'.format(42, 24) - '{0:{a[1]}} {a}'.format(1, a=[1, 2]) - '{:>{}}'.format(42, 24) - '{0:>{1}}'.format(42) # [too-few-format-args] - '{0:>{1}}'.format(42, 24, 54) # [too-many-format-args] - '{0:{a[1]}}'.format(1) # [missing-format-argument-key] - '{0:{a.x}}'.format(1, a=2) # [missing-format-attribute] - -def issue310(): - """ Test a regression using duplicate manual position arguments. """ - '{0} {1} {0}'.format(1, 2) - '{0} {1} {0}'.format(1) # [too-few-format-args] - -def issue322(): - """ Test a regression using mixed manual position arguments - and attribute access arguments. - """ - '{0}{1[FOO]}'.format(123, {'FOO': 456}) - '{0}{1[FOO]}'.format(123, {'FOO': 456}, 321) # [too-many-format-args] - '{0}{1[FOO]}'.format(123) # [too-few-format-args] - -def issue338(): - """ - Check that using a namedtuple subclass doesn't crash when - trying to infer EmptyNodes (resulted after mocking the - members of namedtuples). - """ - from collections import namedtuple - - class Crash(namedtuple("C", "foo bar")): - """ Looking for attributes in __str__ will crash, - because EmptyNodes can't be infered. - """ - def __str__(self): - return "{0.foo}: {0.bar}".format(self) - return Crash - -def issue351(): - """ - Check that the format method can be assigned to a variable, ie: - """ - fmt = 'test {} {}'.format - fmt('arg1') # [too-few-format-args] - fmt('arg1', 'arg2') - fmt('arg1', 'arg2', 'arg3') # [too-many-format-args] - -def issue373(): - """ - Ignore any object coming from an argument. - """ - class SomeClass(object): - """ empty docstring. """ - def __init__(self, opts=None): - self.opts = opts - - def dunc(self, arg): - """Don't try to analyze this.""" - return "A{0}{1}".format(arg, self.opts) - - def func(self): - """Don't try to analyze the following string.""" - return 'AAA{0[iface]}BBB{0[port]}'.format(self.opts) - - return SomeClass - -def issue_463(): - """ - Mix positional arguments, `{0}`, with positional - arguments with attribute access, `{0.__x__}`. - """ - data = "{0.__class__.__name__}: {0}".format(42) - data2 = "{0[0]}: {0}".format([1]) - return (data, data2) diff --git a/pymode/libs/pylint/test/functional/string_formatting.txt b/pymode/libs/pylint/test/functional/string_formatting.txt deleted file mode 100644 index b2f18498..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting.txt +++ /dev/null @@ -1,40 +0,0 @@ -too-many-format-args:58:pprint_bad:Too many arguments for format string -bad-format-string:59:pprint_bad:Invalid format string -bad-format-string:60:pprint_bad:Invalid format string -format-combined-specification:61:pprint_bad:Format string contains both automatic field numbering and manual field specification -missing-format-argument-key:63:pprint_bad:Missing keyword argument 'b' for format string -unused-format-string-argument:63:pprint_bad:Unused format argument 'c' -missing-format-argument-key:64:pprint_bad:Missing keyword argument 'a' for format string -too-few-format-args:65:pprint_bad:Not enough arguments for format string -too-many-format-args:66:pprint_bad:Too many arguments for format string -missing-format-argument-key:68:pprint_bad:Missing keyword argument 'a' for format string -missing-format-argument-key:68:pprint_bad:Missing keyword argument 'b' for format string -missing-format-argument-key:68:pprint_bad:Missing keyword argument 'c' for format string -too-few-format-args:69:pprint_bad:Not enough arguments for format string -missing-format-argument-key:71:pprint_bad:Missing keyword argument 'a' for format string -missing-format-argument-key:71:pprint_bad:Missing keyword argument 'b' for format string -missing-format-argument-key:72:pprint_bad:Missing keyword argument 'a' for format string -missing-format-attribute:74:pprint_bad:Missing format attribute 'length' in format specifier 'a.ids.__len__.length' -invalid-format-index:75:pprint_bad:Using invalid lookup key 400 in format specifier 'a.ids[3][400]' -invalid-format-index:76:pprint_bad:"Using invalid lookup key ""'string'"" in format specifier 'a.ids[3][""\'string\'""]'" -invalid-format-index:77:pprint_bad:Using invalid lookup key 1 in format specifier '0[0][1]' -invalid-format-index:78:pprint_bad:Using invalid lookup key 0 in format specifier '0[0][0]' -missing-format-argument-key:80:pprint_bad:Missing keyword argument 'b' for format string -unused-format-string-argument:80:pprint_bad:Unused format argument 'a' -invalid-format-index:81:pprint_bad:Using invalid lookup key 0 in format specifier 'a[0]' -too-many-format-args:82:pprint_bad:Too many arguments for format string -missing-format-attribute:83:pprint_bad:Missing format attribute 'missing' in format specifier '0.missing' -too-few-format-args:84:pprint_bad:Not enough arguments for format string -too-many-format-args:85:pprint_bad:Too many arguments for format string -too-few-format-args:86:pprint_bad:Not enough arguments for format string -too-few-format-args:87:pprint_bad:Not enough arguments for format string -too-many-format-args:88:pprint_bad:Too many arguments for format string -too-few-format-args:113:nested_issue294:Not enough arguments for format string -too-many-format-args:114:nested_issue294:Too many arguments for format string -missing-format-argument-key:115:nested_issue294:Missing keyword argument 'a' for format string -missing-format-attribute:116:nested_issue294:Missing format attribute 'x' in format specifier 'a.x' -too-few-format-args:121:issue310:Not enough arguments for format string -too-many-format-args:128:issue322:Too many arguments for format string -too-few-format-args:129:issue322:Not enough arguments for format string -too-few-format-args:152:issue351:Not enough arguments for format string -too-many-format-args:154:issue351:Too many arguments for format string diff --git a/pymode/libs/pylint/test/functional/string_formatting_disable.py b/pymode/libs/pylint/test/functional/string_formatting_disable.py deleted file mode 100644 index 096c8473..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_disable.py +++ /dev/null @@ -1 +0,0 @@ -"a {} {".format(1) # [bad-format-string] \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/string_formatting_disable.rc b/pymode/libs/pylint/test/functional/string_formatting_disable.rc deleted file mode 100644 index 0193339d..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_disable.rc +++ /dev/null @@ -1,3 +0,0 @@ -[Messages Control] -disable=all -enable=bad-format-string diff --git a/pymode/libs/pylint/test/functional/string_formatting_disable.txt b/pymode/libs/pylint/test/functional/string_formatting_disable.txt deleted file mode 100644 index 2c8f6db5..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_disable.txt +++ /dev/null @@ -1 +0,0 @@ -bad-format-string:1::Invalid format string \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/string_formatting_failed_inference.py b/pymode/libs/pylint/test/functional/string_formatting_failed_inference.py deleted file mode 100644 index aa8d24ae..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_failed_inference.py +++ /dev/null @@ -1,4 +0,0 @@ -""" Testing string format with a failed inference. This should not crash. """ - -import collections -"{dict[0]}".format(dict=collections.defaultdict(int)) diff --git a/pymode/libs/pylint/test/functional/string_formatting_py27.py b/pymode/libs/pylint/test/functional/string_formatting_py27.py deleted file mode 100644 index b3de433d..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_py27.py +++ /dev/null @@ -1,22 +0,0 @@ -"""test for Python 2 string formatting error -""" -from __future__ import unicode_literals -# pylint: disable=line-too-long -__revision__ = 1 - -def pprint_bad(): - """Test string format """ - "{{}}".format(1) # [too-many-format-args] - "{} {".format() # [bad-format-string] - "{} }".format() # [bad-format-string] - "{0} {}".format(1, 2) # [format-combined-specification] - # +1: [missing-format-argument-key, unused-format-string-argument] - "{a} {b}".format(a=1, c=2) - "{} {a}".format(1, 2) # [missing-format-argument-key] - "{} {}".format(1) # [too-few-format-args] - "{} {}".format(1, 2, 3) # [too-many-format-args] - # +1: [missing-format-argument-key,missing-format-argument-key,missing-format-argument-key] - "{a} {b} {c}".format() - "{} {}".format(a=1, b=2) # [too-few-format-args] - # +1: [missing-format-argument-key, missing-format-argument-key] - "{a} {b}".format(1, 2) diff --git a/pymode/libs/pylint/test/functional/string_formatting_py27.rc b/pymode/libs/pylint/test/functional/string_formatting_py27.rc deleted file mode 100644 index c4f2e664..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_py27.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -min_pyver=2.7 -max_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/string_formatting_py27.txt b/pymode/libs/pylint/test/functional/string_formatting_py27.txt deleted file mode 100644 index 47f21ded..00000000 --- a/pymode/libs/pylint/test/functional/string_formatting_py27.txt +++ /dev/null @@ -1,15 +0,0 @@ -too-many-format-args:9:pprint_bad:Too many arguments for format string -bad-format-string:10:pprint_bad:Invalid format string -bad-format-string:11:pprint_bad:Invalid format string -format-combined-specification:12:pprint_bad:Format string contains both automatic field numbering and manual field specification -missing-format-argument-key:14:pprint_bad:Missing keyword argument u'b' for format string -unused-format-string-argument:14:pprint_bad:Unused format argument 'c' -missing-format-argument-key:15:pprint_bad:Missing keyword argument u'a' for format string -too-few-format-args:16:pprint_bad:Not enough arguments for format string -too-many-format-args:17:pprint_bad:Too many arguments for format string -missing-format-argument-key:19:pprint_bad:Missing keyword argument u'a' for format string -missing-format-argument-key:19:pprint_bad:Missing keyword argument u'b' for format string -missing-format-argument-key:19:pprint_bad:Missing keyword argument u'c' for format string -too-few-format-args:20:pprint_bad:Not enough arguments for format string -missing-format-argument-key:22:pprint_bad:Missing keyword argument u'a' for format string -missing-format-argument-key:22:pprint_bad:Missing keyword argument u'b' for format string diff --git a/pymode/libs/pylint/test/functional/super_checks.py b/pymode/libs/pylint/test/functional/super_checks.py deleted file mode 100644 index 42a93338..00000000 --- a/pymode/libs/pylint/test/functional/super_checks.py +++ /dev/null @@ -1,114 +0,0 @@ -# pylint: disable=too-few-public-methods,import-error, no-absolute-import,missing-docstring, wrong-import-position,invalid-name, wrong-import-order -"""check use of super""" - -from unknown import Missing - -class Aaaa: # <3.0:[old-style-class] - """old style""" - def hop(self): # <3.0:[super-on-old-class] - """hop""" - super(Aaaa, self).hop() # >=3.0:[no-member] - - def __init__(self): # <3.0:[super-on-old-class] - super(Aaaa, self).__init__() - -class NewAaaa(object): - """old style""" - def hop(self): - """hop""" - super(NewAaaa, self).hop() # [no-member] - - def __init__(self): - super(Aaaa, self).__init__() # [bad-super-call] - -class Py3kAaaa(NewAaaa): - """new style""" - def __init__(self): - super().__init__() # <3.0:[missing-super-argument] - -class Py3kWrongSuper(Py3kAaaa): - """new style""" - def __init__(self): - super(NewAaaa, self).__init__() # [bad-super-call] - -class WrongNameRegression(Py3kAaaa): - """ test a regression with the message """ - def __init__(self): - super(Missing, self).__init__() # [bad-super-call] - -class Getattr(object): - """ crash """ - name = NewAaaa - -class CrashSuper(object): - """ test a crash with this checker """ - def __init__(self): - super(Getattr.name, self).__init__() # [bad-super-call] - -class Empty(object): - """Just an empty class.""" - -class SuperDifferentScope(object): - """Don'emit bad-super-call when the super call is in another scope. - For reference, see https://bitbucket.org/logilab/pylint/issue/403. - """ - @staticmethod - def test(): - """Test that a bad-super-call is not emitted for this case.""" - class FalsePositive(Empty): - """The following super is in another scope than `test`.""" - def __init__(self, arg): - super(FalsePositive, self).__init__(arg) - super(object, 1).__init__() # [bad-super-call] - - -class UnknownBases(Missing): - """Don't emit if we don't know all the bases.""" - def __init__(self): - super(UnknownBases, self).__init__() - super(UnknownBases, self).test() - super(Missing, self).test() # [bad-super-call] - - -# Test that we are detecting proper super errors. - -class BaseClass(object): - - not_a_method = 42 - - def function(self, param): - return param + self.not_a_method - - def __getattr__(self, attr): - return attr - - -class InvalidSuperChecks(BaseClass): - - def __init__(self): - super(InvalidSuperChecks, self).not_a_method() # [not-callable] - super(InvalidSuperChecks, self).attribute_error() # [no-member] - super(InvalidSuperChecks, self).function(42) - super(InvalidSuperChecks, self).function() # [no-value-for-parameter] - super(InvalidSuperChecks, self).function(42, 24, 24) # [too-many-function-args] - # +1: [unexpected-keyword-arg,no-value-for-parameter] - super(InvalidSuperChecks, self).function(lala=42) - # Even though BaseClass has a __getattr__, that won't - # be called. - super(InvalidSuperChecks, self).attribute_error() # [no-member] - - - -# Regression for PyCQA/pylint/issues/773 -import subprocess - -# The problem was related to astroid not filtering statements -# at scope level properly, basically not doing strong updates. -try: - TimeoutExpired = subprocess.TimeoutExpired -except AttributeError: - class TimeoutExpired(subprocess.CalledProcessError): - def __init__(self): - returncode = -1 - self.timeout = -1 - super(TimeoutExpired, self).__init__(returncode) diff --git a/pymode/libs/pylint/test/functional/super_checks.txt b/pymode/libs/pylint/test/functional/super_checks.txt deleted file mode 100644 index ea1d67be..00000000 --- a/pymode/libs/pylint/test/functional/super_checks.txt +++ /dev/null @@ -1,19 +0,0 @@ -old-style-class:6:Aaaa:Old-style class defined. -super-on-old-class:8:Aaaa.hop:Use of super on an old style class -no-member:10:Aaaa.hop:Super of 'Aaaa' has no 'hop' member:INFERENCE -super-on-old-class:12:Aaaa.__init__:Use of super on an old style class -no-member:19:NewAaaa.hop:Super of 'NewAaaa' has no 'hop' member:INFERENCE -bad-super-call:22:NewAaaa.__init__:Bad first argument 'Aaaa' given to super() -missing-super-argument:27:Py3kAaaa.__init__:Missing argument to super() -bad-super-call:32:Py3kWrongSuper.__init__:Bad first argument 'NewAaaa' given to super() -bad-super-call:37:WrongNameRegression.__init__:Bad first argument 'Missing' given to super() -bad-super-call:46:CrashSuper.__init__:Bad first argument 'NewAaaa' given to super() -bad-super-call:62:SuperDifferentScope.test:Bad first argument 'object' given to super() -bad-super-call:70:UnknownBases.__init__:Bad first argument 'Missing' given to super() -not-callable:89:InvalidSuperChecks.__init__:super(InvalidSuperChecks, self).not_a_method is not callable -no-member:90:InvalidSuperChecks.__init__:Super of 'InvalidSuperChecks' has no 'attribute_error' member:INFERENCE -no-value-for-parameter:92:InvalidSuperChecks.__init__:No value for argument 'param' in method call -too-many-function-args:93:InvalidSuperChecks.__init__:Too many positional arguments for method call -no-value-for-parameter:95:InvalidSuperChecks.__init__:No value for argument 'param' in method call -unexpected-keyword-arg:95:InvalidSuperChecks.__init__:Unexpected keyword argument 'lala' in method call -no-member:98:InvalidSuperChecks.__init__:Super of 'InvalidSuperChecks' has no 'attribute_error' member:INFERENCE \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/superfluous_parens.py b/pymode/libs/pylint/test/functional/superfluous_parens.py deleted file mode 100644 index 13418cd7..00000000 --- a/pymode/libs/pylint/test/functional/superfluous_parens.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Test the superfluous-parens warning.""" -from __future__ import print_function -# pylint: disable=unneeded-not -i = 3 -if (i == 5): # [superfluous-parens] - pass -if not (i == 5): # [superfluous-parens] - pass -if not (3 or 5): - pass -for (x) in (1, 2, 3): # [superfluous-parens] - print(x) -if (1) in (1, 2, 3): # [superfluous-parens] - pass -if (1, 2) in (1, 2, 3): - pass -DICT = {'a': 1, 'b': 2} -del(DICT['b']) # [superfluous-parens] -del DICT['a'] diff --git a/pymode/libs/pylint/test/functional/superfluous_parens.txt b/pymode/libs/pylint/test/functional/superfluous_parens.txt deleted file mode 100644 index 57e1019c..00000000 --- a/pymode/libs/pylint/test/functional/superfluous_parens.txt +++ /dev/null @@ -1,5 +0,0 @@ -superfluous-parens:5::Unnecessary parens after 'if' keyword -superfluous-parens:7::Unnecessary parens after 'not' keyword -superfluous-parens:11::Unnecessary parens after 'for' keyword -superfluous-parens:13::Unnecessary parens after 'if' keyword -superfluous-parens:18::Unnecessary parens after 'del' keyword diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.py b/pymode/libs/pylint/test/functional/suspicious_str_strip_call.py deleted file mode 100644 index e859f25f..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Suspicious str.strip calls.""" -__revision__ = 1 - -''.strip('yo') -''.strip() - -u''.strip('http://') # [bad-str-strip-call] -u''.lstrip('http://') # [bad-str-strip-call] -b''.rstrip('http://') # [bad-str-strip-call] diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.rc b/pymode/libs/pylint/test/functional/suspicious_str_strip_call.rc deleted file mode 100644 index a6502339..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.txt b/pymode/libs/pylint/test/functional/suspicious_str_strip_call.txt deleted file mode 100644 index ad714cc6..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call.txt +++ /dev/null @@ -1,3 +0,0 @@ -bad-str-strip-call:7::Suspicious argument in unicode.strip call -bad-str-strip-call:8::Suspicious argument in unicode.lstrip call -bad-str-strip-call:9::Suspicious argument in str.rstrip call diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.py b/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.py deleted file mode 100644 index e859f25f..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Suspicious str.strip calls.""" -__revision__ = 1 - -''.strip('yo') -''.strip() - -u''.strip('http://') # [bad-str-strip-call] -u''.lstrip('http://') # [bad-str-strip-call] -b''.rstrip('http://') # [bad-str-strip-call] diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.rc b/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.txt b/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.txt deleted file mode 100644 index 81f32cf4..00000000 --- a/pymode/libs/pylint/test/functional/suspicious_str_strip_call_py3.txt +++ /dev/null @@ -1,3 +0,0 @@ -bad-str-strip-call:7::Suspicious argument in str.strip call -bad-str-strip-call:8::Suspicious argument in str.lstrip call -bad-str-strip-call:9::Suspicious argument in bytes.rstrip call diff --git a/pymode/libs/pylint/test/functional/syntax_error.py b/pymode/libs/pylint/test/functional/syntax_error.py deleted file mode 100644 index c93df6b0..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error.py +++ /dev/null @@ -1 +0,0 @@ -def toto # [syntax-error] diff --git a/pymode/libs/pylint/test/functional/syntax_error.rc b/pymode/libs/pylint/test/functional/syntax_error.rc deleted file mode 100644 index d86678f7..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -except_implementations=Jython diff --git a/pymode/libs/pylint/test/functional/syntax_error.txt b/pymode/libs/pylint/test/functional/syntax_error.txt deleted file mode 100644 index b57bc72b..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error.txt +++ /dev/null @@ -1 +0,0 @@ -syntax-error:1::invalid syntax \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/syntax_error_jython.py b/pymode/libs/pylint/test/functional/syntax_error_jython.py deleted file mode 100644 index c93df6b0..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error_jython.py +++ /dev/null @@ -1 +0,0 @@ -def toto # [syntax-error] diff --git a/pymode/libs/pylint/test/functional/syntax_error_jython.rc b/pymode/libs/pylint/test/functional/syntax_error_jython.rc deleted file mode 100644 index 29bd3fac..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error_jython.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -except_implementations=CPython, PyPy diff --git a/pymode/libs/pylint/test/functional/syntax_error_jython.txt b/pymode/libs/pylint/test/functional/syntax_error_jython.txt deleted file mode 100644 index e532aece..00000000 --- a/pymode/libs/pylint/test/functional/syntax_error_jython.txt +++ /dev/null @@ -1 +0,0 @@ -syntax-error:1::"mismatched input '\n\n\n\n' expecting LPAREN" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/tokenize_error.py b/pymode/libs/pylint/test/functional/tokenize_error.py deleted file mode 100644 index 323950d9..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error.py +++ /dev/null @@ -1,6 +0,0 @@ -"""A module that is accepted by Python but rejected by tokenize. - -The problem is the trailing line continuation at the end of the line, -which produces a TokenError.""" -# +2: [syntax-error] -""\ diff --git a/pymode/libs/pylint/test/functional/tokenize_error.rc b/pymode/libs/pylint/test/functional/tokenize_error.rc deleted file mode 100644 index eb52949d..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -except_implementations=Jython \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/tokenize_error.txt b/pymode/libs/pylint/test/functional/tokenize_error.txt deleted file mode 100644 index 4e65f712..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error.txt +++ /dev/null @@ -1 +0,0 @@ -syntax-error:7::EOF in multi-line statement diff --git a/pymode/libs/pylint/test/functional/tokenize_error_jython.py b/pymode/libs/pylint/test/functional/tokenize_error_jython.py deleted file mode 100644 index 205f5fc6..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error_jython.py +++ /dev/null @@ -1,7 +0,0 @@ -# [syntax-error] -"""A module that is accepted by Python but rejected by tokenize. - -The problem is the trailing line continuation at the end of the line, -which produces a TokenError.""" - -""\ diff --git a/pymode/libs/pylint/test/functional/tokenize_error_jython.rc b/pymode/libs/pylint/test/functional/tokenize_error_jython.rc deleted file mode 100644 index 79ffac09..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error_jython.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -except_implementations=CPython,PyPy,IronPython \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/tokenize_error_jython.txt b/pymode/libs/pylint/test/functional/tokenize_error_jython.txt deleted file mode 100644 index 82e662eb..00000000 --- a/pymode/libs/pylint/test/functional/tokenize_error_jython.txt +++ /dev/null @@ -1 +0,0 @@ -syntax-error:1::unexpected character after line continuation character \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_few_public_methods.py b/pymode/libs/pylint/test/functional/too_few_public_methods.py deleted file mode 100644 index a5b2f94f..00000000 --- a/pymode/libs/pylint/test/functional/too_few_public_methods.py +++ /dev/null @@ -1,28 +0,0 @@ -# pylint: disable=missing-docstring -from __future__ import print_function - -class Aaaa(object): # [too-few-public-methods] - - def __init__(self): - pass - - def meth1(self): - print(self) - - def _dontcount(self): - print(self) - - -# Don't emit for these cases. -class Klass(object): - """docstring""" - - def meth1(self): - """first""" - - def meth2(self): - """second""" - - -class EnoughPublicMethods(Klass): - """We shouldn't emit too-few-public-methods for this.""" diff --git a/pymode/libs/pylint/test/functional/too_few_public_methods.txt b/pymode/libs/pylint/test/functional/too_few_public_methods.txt deleted file mode 100644 index be0e73ef..00000000 --- a/pymode/libs/pylint/test/functional/too_few_public_methods.txt +++ /dev/null @@ -1 +0,0 @@ -too-few-public-methods:4:Aaaa:Too few public methods (1/2) diff --git a/pymode/libs/pylint/test/functional/too_many_ancestors.py b/pymode/libs/pylint/test/functional/too_many_ancestors.py deleted file mode 100644 index 38d68bbc..00000000 --- a/pymode/libs/pylint/test/functional/too_many_ancestors.py +++ /dev/null @@ -1,24 +0,0 @@ -# pylint: disable=missing-docstring, too-few-public-methods - -class Aaaa(object): - pass -class Bbbb(object): - pass -class Cccc(object): - pass -class Dddd(object): - pass -class Eeee(object): - pass -class Ffff(object): - pass -class Gggg(object): - pass -class Hhhh(object): - pass - -class Iiii(Aaaa, Bbbb, Cccc, Dddd, Eeee, Ffff, Gggg, Hhhh): # [too-many-ancestors] - pass - -class Jjjj(Iiii): # [too-many-ancestors] - pass diff --git a/pymode/libs/pylint/test/functional/too_many_ancestors.txt b/pymode/libs/pylint/test/functional/too_many_ancestors.txt deleted file mode 100644 index e9f0841c..00000000 --- a/pymode/libs/pylint/test/functional/too_many_ancestors.txt +++ /dev/null @@ -1,2 +0,0 @@ -too-many-ancestors:20:Iiii:Too many ancestors (9/7) -too-many-ancestors:23:Jjjj:Too many ancestors (10/7) \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_many_arguments.py b/pymode/libs/pylint/test/functional/too_many_arguments.py deleted file mode 100644 index 99f4e78f..00000000 --- a/pymode/libs/pylint/test/functional/too_many_arguments.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=missing-docstring - -def stupid_function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9): # [too-many-arguments] - return arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 diff --git a/pymode/libs/pylint/test/functional/too_many_arguments.txt b/pymode/libs/pylint/test/functional/too_many_arguments.txt deleted file mode 100644 index 8f99a462..00000000 --- a/pymode/libs/pylint/test/functional/too_many_arguments.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-arguments:3:stupid_function:Too many arguments (9/5) diff --git a/pymode/libs/pylint/test/functional/too_many_boolean_expressions.py b/pymode/libs/pylint/test/functional/too_many_boolean_expressions.py deleted file mode 100644 index b3dc2387..00000000 --- a/pymode/libs/pylint/test/functional/too_many_boolean_expressions.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Checks for if statements containing too many boolean expressions""" - -# pylint: disable=invalid-name - -x = y = z = 5 -if x > -5 and x < 5 and y > -5 and y < 5 and z > -5 and z < 5: # [too-many-boolean-expressions] - pass -elif True and False and 1 and 2 and 3: - pass -elif True and False and 1 and 2 and 3 and 4 and 5: # [too-many-boolean-expressions] - pass -elif True and (True and True) and (x == 5 or True or True): # [too-many-boolean-expressions] - pass -elif True and (True or (x > -5 and x < 5 and (z > -5 or z < 5))): # [too-many-boolean-expressions] - pass -elif True == True == True == True == True == True: - pass - -if True and False and 1 and 2 and 3: - pass diff --git a/pymode/libs/pylint/test/functional/too_many_boolean_expressions.txt b/pymode/libs/pylint/test/functional/too_many_boolean_expressions.txt deleted file mode 100644 index 0bb0086c..00000000 --- a/pymode/libs/pylint/test/functional/too_many_boolean_expressions.txt +++ /dev/null @@ -1,4 +0,0 @@ -too-many-boolean-expressions:6::Too many boolean expressions in if statement (6/5) -too-many-boolean-expressions:10::Too many boolean expressions in if statement (7/5) -too-many-boolean-expressions:12::Too many boolean expressions in if statement (6/5) -too-many-boolean-expressions:14::Too many boolean expressions in if statement (6/5) diff --git a/pymode/libs/pylint/test/functional/too_many_branches.py b/pymode/libs/pylint/test/functional/too_many_branches.py deleted file mode 100644 index 023d8ee7..00000000 --- a/pymode/libs/pylint/test/functional/too_many_branches.py +++ /dev/null @@ -1,69 +0,0 @@ -""" Test for too many branches. """ -# pylint: disable=using-constant-test -def wrong(): # [too-many-branches] - """ Has too many branches. """ - if 1: - pass - elif 1: - pass - elif 1: - pass - elif 1: - pass - elif 1: - pass - elif 1: - pass - try: - pass - finally: - pass - if 2: - pass - while True: - pass - if 1: - pass - elif 2: - pass - elif 3: - pass - -def good(): - """ Too many branches only if we take - into consideration the nested functions. - """ - def nested_1(): - """ empty """ - if 1: - pass - elif 2: - pass - elif 3: - pass - elif 4: - pass - - nested_1() - try: - pass - finally: - pass - try: - pass - finally: - pass - if 1: - pass - elif 2: - pass - elif 3: - pass - elif 4: - pass - elif 5: - pass - elif 6: - pass - elif 7: - pass diff --git a/pymode/libs/pylint/test/functional/too_many_branches.txt b/pymode/libs/pylint/test/functional/too_many_branches.txt deleted file mode 100644 index fbc82ccc..00000000 --- a/pymode/libs/pylint/test/functional/too_many_branches.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-branches:3:wrong:Too many branches (13/12) diff --git a/pymode/libs/pylint/test/functional/too_many_instance_attributes.py b/pymode/libs/pylint/test/functional/too_many_instance_attributes.py deleted file mode 100644 index b77efdb7..00000000 --- a/pymode/libs/pylint/test/functional/too_many_instance_attributes.py +++ /dev/null @@ -1,26 +0,0 @@ -# pylint: disable=missing-docstring, too-few-public-methods - -class Aaaa(object): # [too-many-instance-attributes] - - def __init__(self): - self.aaaa = 1 - self.bbbb = 2 - self.cccc = 3 - self.dddd = 4 - self.eeee = 5 - self.ffff = 6 - self.gggg = 7 - self.hhhh = 8 - self.iiii = 9 - self.jjjj = 10 - self._aaaa = 1 - self._bbbb = 2 - self._cccc = 3 - self._dddd = 4 - self._eeee = 5 - self._ffff = 6 - self._gggg = 7 - self._hhhh = 8 - self._iiii = 9 - self._jjjj = 10 - self.tomuch = None diff --git a/pymode/libs/pylint/test/functional/too_many_instance_attributes.txt b/pymode/libs/pylint/test/functional/too_many_instance_attributes.txt deleted file mode 100644 index 652ccea3..00000000 --- a/pymode/libs/pylint/test/functional/too_many_instance_attributes.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-instance-attributes:3:Aaaa:Too many instance attributes (21/7) diff --git a/pymode/libs/pylint/test/functional/too_many_lines.py b/pymode/libs/pylint/test/functional/too_many_lines.py deleted file mode 100644 index 78e568c2..00000000 --- a/pymode/libs/pylint/test/functional/too_many_lines.py +++ /dev/null @@ -1,1015 +0,0 @@ -# pylint: disable=missing-docstring -# -1: [too-many-lines] -__revision__ = 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ZERFZAER = 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -HEHEHE = 2 diff --git a/pymode/libs/pylint/test/functional/too_many_lines.txt b/pymode/libs/pylint/test/functional/too_many_lines.txt deleted file mode 100644 index 0374f0c0..00000000 --- a/pymode/libs/pylint/test/functional/too_many_lines.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-lines:1::Too many lines in module (1015/1000) \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_many_lines_disabled.py b/pymode/libs/pylint/test/functional/too_many_lines_disabled.py deleted file mode 100644 index 1b0866db..00000000 --- a/pymode/libs/pylint/test/functional/too_many_lines_disabled.py +++ /dev/null @@ -1,1018 +0,0 @@ -"""Test that disabling too-many-lines on any line works.""" - - - -# pylint: disable=too-many-lines -__revision__ = 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ZERFZAER = 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -HEHEHE = 2 diff --git a/pymode/libs/pylint/test/functional/too_many_locals.py b/pymode/libs/pylint/test/functional/too_many_locals.py deleted file mode 100644 index ac38a9e0..00000000 --- a/pymode/libs/pylint/test/functional/too_many_locals.py +++ /dev/null @@ -1,60 +0,0 @@ -# pylint: disable=missing-docstring -from __future__ import print_function - -def function(arg1, arg2, arg3, arg4, arg5): # [too-many-locals] - arg6, arg7, arg8, arg9 = arg1, arg2, arg3, arg4 - print(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) - loc1, loc2, loc3, loc4, loc5, loc6, loc7 = arg1, arg2, arg3, arg4, arg5, \ - arg6, arg7 - print(loc1, loc2, loc3, loc4, loc5, loc6, loc7) - - -def too_many_locals_function(): # [too-many-locals] - """pylint will complains about too many local variables""" - args0 = 0 - args1 = args0 * 1 - args2 = args1 * 2 - args3 = args2 * 3 - args4 = args3 * 4 - args5 = args4 * 5 - args6 = args5 * 6 - args7 = args6 * 7 - args8 = args7 * 8 - args9 = args8 * 9 - args10 = args9 * 10 - args11 = args10 * 11 - args12 = args11 * 12 - args13 = args12 * 13 - args14 = args13 * 14 - args15 = args14 * 15 - return args15 - -def too_many_arguments_function(arga, argu, argi, arge, argt, args): # [too-many-arguments] - """pylint will complains about too many arguments.""" - arga = argu - arga += argi - arga += arge - arga += argt - arga += args - return arga - -def ignored_arguments_function(arga, argu, argi, - _arge=0, _argt=1, _args=None): - """pylint will ignore _arge, _argt, _args. - - Consequently pylint will only coun 13 arguments. - """ - arg0 = 0 - arg1 = arg0 * 1 + arga - arg2 = arg1 * 2 + argu - arg3 = arg2 * 3 + argi - arg4 = arg3 * 4 + _arge - arg5 = arg4 * 5 + _argt - arg6 = arg5 * 6 - arg7 = arg6 * 7 - arg8 = arg7 * 8 - arg9 = arg8 * 9 - arg9 += arg0 - if _args: - arg9 += sum(_args) - return arg9 diff --git a/pymode/libs/pylint/test/functional/too_many_locals.txt b/pymode/libs/pylint/test/functional/too_many_locals.txt deleted file mode 100644 index cce2332c..00000000 --- a/pymode/libs/pylint/test/functional/too_many_locals.txt +++ /dev/null @@ -1,3 +0,0 @@ -too-many-locals:4:function:Too many local variables (16/15) -too-many-locals:12:too_many_locals_function:Too many local variables (16/15) -too-many-arguments:32:too_many_arguments_function:Too many arguments (6/5) \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_many_nested_blocks.py b/pymode/libs/pylint/test/functional/too_many_nested_blocks.py deleted file mode 100644 index 47dbf441..00000000 --- a/pymode/libs/pylint/test/functional/too_many_nested_blocks.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Checks the maximum block level is smaller than 6 in function definitions""" - -#pylint: disable=using-constant-test, missing-docstring, too-many-return-statements - -def my_function(): - if 1: # [too-many-nested-blocks] - for i in range(10): - if i == 2: - while True: - try: - if True: - i += 1 - except IOError: - pass - - if 1: - for i in range(10): - if i == 2: - while True: - try: - i += 1 - except IOError: - pass - - def nested_func(): - if True: - for i in range(10): - while True: - if True: - if True: - yield i - - nested_func() - -def more_complex_function(): - attr1 = attr2 = attr3 = [1, 2, 3] - if attr1: - for i in attr1: - if attr2: - return i - else: - return 'duh' - elif attr2: - for i in attr2: - if attr2: - return i - else: - return 'duh' - else: - for i in range(15): - if attr3: - return i - else: - return 'doh' - return None - -def elif_function(): - arg = None - if arg == 1: - return 1 - elif arg == 2: - return 2 - elif arg == 3: - return 3 - elif arg == 4: - return 4 - elif arg == 5: - return 5 - elif arg == 6: - return 6 - elif arg == 7: - return 7 - -def else_if_function(): - arg = None - if arg == 1: # [too-many-nested-blocks] - return 1 - else: - if arg == 2: - return 2 - else: - if arg == 3: - return 3 - else: - if arg == 4: - return 4 - else: - if arg == 5: - return 5 - else: - if arg == 6: - return 6 - else: - if arg == 7: - return 7 diff --git a/pymode/libs/pylint/test/functional/too_many_nested_blocks.txt b/pymode/libs/pylint/test/functional/too_many_nested_blocks.txt deleted file mode 100644 index dcee9d2a..00000000 --- a/pymode/libs/pylint/test/functional/too_many_nested_blocks.txt +++ /dev/null @@ -1,2 +0,0 @@ -too-many-nested-blocks:6:my_function:Too many nested blocks (6/5) -too-many-nested-blocks:76:else_if_function:Too many nested blocks (7/5) diff --git a/pymode/libs/pylint/test/functional/too_many_public_methods.py b/pymode/libs/pylint/test/functional/too_many_public_methods.py deleted file mode 100644 index df6134f3..00000000 --- a/pymode/libs/pylint/test/functional/too_many_public_methods.py +++ /dev/null @@ -1,79 +0,0 @@ -# pylint: disable=missing-docstring - -class Aaaa(object): # [too-many-public-methods] - - def __init__(self): - pass - - def meth1(self): - """hehehe""" - - def meth2(self): - """hehehe""" - - def meth3(self): - """hehehe""" - - def meth4(self): - """hehehe""" - - def meth5(self): - """hehehe""" - - def meth6(self): - """hehehe""" - - def meth7(self): - """hehehe""" - - def meth8(self): - """hehehe""" - - def meth9(self): - """hehehe""" - - def meth10(self): - """hehehe""" - - def meth11(self): - """hehehe""" - - def meth12(self): - """hehehe""" - - def meth13(self): - """hehehe""" - - def meth14(self): - """hehehe""" - - def meth15(self): - """hehehe""" - - def meth16(self): - """hehehe""" - - def meth17(self): - """hehehe""" - - def meth18(self): - """hehehe""" - - def meth19(self): - """hehehe""" - - def meth20(self): - """hehehe""" - - def meth21(self): - """hehehe""" - - def _dontcount(self): - """not public""" - -class BBB(Aaaa): - """Don't emit for methods defined in the parent.""" - def meth1(self): - """trop""" - def meth2(self): - """tzop""" diff --git a/pymode/libs/pylint/test/functional/too_many_public_methods.txt b/pymode/libs/pylint/test/functional/too_many_public_methods.txt deleted file mode 100644 index 1b5a2501..00000000 --- a/pymode/libs/pylint/test/functional/too_many_public_methods.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-public-methods:3:Aaaa:Too many public methods (21/20) diff --git a/pymode/libs/pylint/test/functional/too_many_return_statements.py b/pymode/libs/pylint/test/functional/too_many_return_statements.py deleted file mode 100644 index 7ae61a9c..00000000 --- a/pymode/libs/pylint/test/functional/too_many_return_statements.py +++ /dev/null @@ -1,24 +0,0 @@ -# pylint: disable=missing-docstring - -def stupid_function(arg): # [too-many-return-statements] - if arg == 1: - return 1 - elif arg == 2: - return 2 - elif arg == 3: - return 3 - elif arg == 4: - return 4 - elif arg == 5: - return 5 - elif arg == 6: - return 6 - elif arg == 7: - return 7 - elif arg == 8: - return 8 - elif arg == 9: - return 9 - elif arg == 10: - return 10 - return None diff --git a/pymode/libs/pylint/test/functional/too_many_return_statements.txt b/pymode/libs/pylint/test/functional/too_many_return_statements.txt deleted file mode 100644 index 4f65db22..00000000 --- a/pymode/libs/pylint/test/functional/too_many_return_statements.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-return-statements:3:stupid_function:Too many return statements (11/6) \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_many_star_expressions.py b/pymode/libs/pylint/test/functional/too_many_star_expressions.py deleted file mode 100644 index 309069ea..00000000 --- a/pymode/libs/pylint/test/functional/too_many_star_expressions.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Test for too-many-star-expressions.""" - -*FIRST, *SECOND = [1, 2, 3] # [too-many-star-expressions] -*FIRST_1, SECOND = (1, 2, 3) diff --git a/pymode/libs/pylint/test/functional/too_many_star_expressions.rc b/pymode/libs/pylint/test/functional/too_many_star_expressions.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/too_many_star_expressions.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/too_many_star_expressions.txt b/pymode/libs/pylint/test/functional/too_many_star_expressions.txt deleted file mode 100644 index c9b8b4f8..00000000 --- a/pymode/libs/pylint/test/functional/too_many_star_expressions.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-star-expressions:3::More than one starred expression in assignment \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/too_many_statements.py b/pymode/libs/pylint/test/functional/too_many_statements.py deleted file mode 100644 index 305db807..00000000 --- a/pymode/libs/pylint/test/functional/too_many_statements.py +++ /dev/null @@ -1,60 +0,0 @@ -# pylint: disable=missing-docstring - -from __future__ import print_function - -def stupid_function(arg): # [too-many-statements] - if arg == 1: - print(1) - elif arg == 2: - print(1) - elif arg == 3: - print(1) - elif arg == 4: - print(1) - elif arg == 5: - print(1) - elif arg == 6: - print(1) - elif arg == 7: - print(1) - elif arg == 8: - print(1) - elif arg == 9: - print(1) - elif arg == 10: - print(1) - elif arg < 1: - print(1) - print(1) - arg = 0 - for _ in range(arg): - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) - print(1) diff --git a/pymode/libs/pylint/test/functional/too_many_statements.txt b/pymode/libs/pylint/test/functional/too_many_statements.txt deleted file mode 100644 index 255e97ee..00000000 --- a/pymode/libs/pylint/test/functional/too_many_statements.txt +++ /dev/null @@ -1 +0,0 @@ -too-many-statements:5:stupid_function:Too many statements (55/50) diff --git a/pymode/libs/pylint/test/functional/trailing_newlines.py b/pymode/libs/pylint/test/functional/trailing_newlines.py deleted file mode 100644 index 8fbadbb3..00000000 --- a/pymode/libs/pylint/test/functional/trailing_newlines.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Regression test for trailing-newlines (C0304).""" -# +1: [trailing-newlines] - diff --git a/pymode/libs/pylint/test/functional/trailing_newlines.txt b/pymode/libs/pylint/test/functional/trailing_newlines.txt deleted file mode 100644 index 254f49d9..00000000 --- a/pymode/libs/pylint/test/functional/trailing_newlines.txt +++ /dev/null @@ -1 +0,0 @@ -trailing-newlines:3::Trailing newlines diff --git a/pymode/libs/pylint/test/functional/trailing_whitespaces.py b/pymode/libs/pylint/test/functional/trailing_whitespaces.py deleted file mode 100644 index 0e7a1163..00000000 --- a/pymode/libs/pylint/test/functional/trailing_whitespaces.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Regression test for trailing-whitespace (C0303).""" -# pylint: disable=mixed-line-endings -from __future__ import print_function - -# +1: [trailing-whitespace] -print('some trailing whitespace') -# +1: [trailing-whitespace] -print('trailing whitespace does not count towards the line length limit') -print('windows line ends are ok') -# +1: [trailing-whitespace] -print('but trailing whitespace on win is not') diff --git a/pymode/libs/pylint/test/functional/trailing_whitespaces.txt b/pymode/libs/pylint/test/functional/trailing_whitespaces.txt deleted file mode 100644 index 38fc2c32..00000000 --- a/pymode/libs/pylint/test/functional/trailing_whitespaces.txt +++ /dev/null @@ -1,3 +0,0 @@ -trailing-whitespace:6::Trailing whitespace -trailing-whitespace:8::Trailing whitespace -trailing-whitespace:11::Trailing whitespace diff --git a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.py b/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.py deleted file mode 100644 index 98f56408..00000000 --- a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Check possible unbalanced tuple unpacking """ -from __future__ import absolute_import -from functional.unpacking import unpack - -# pylint: disable=using-constant-test - -def do_stuff(): - """This is not right.""" - first, second = 1, 2, 3 # [unbalanced-tuple-unpacking] - return first + second - -def do_stuff1(): - """This is not right.""" - first, second = [1, 2, 3] # [unbalanced-tuple-unpacking] - return first + second - -def do_stuff2(): - """This is not right.""" - (first, second) = 1, 2, 3 # [unbalanced-tuple-unpacking] - return first + second - -def do_stuff3(): - """This is not right.""" - first, second = range(100) - return first + second - -def do_stuff4(): - """ This is right """ - first, second = 1, 2 - return first + second - -def do_stuff5(): - """ This is also right """ - first, second = (1, 2) - return first + second - -def do_stuff6(): - """ This is right """ - (first, second) = (1, 2) - return first + second - -def temp(): - """ This is not weird """ - if True: - return [1, 2] - return [2, 3, 4] - -def do_stuff7(): - """ This is not right, but we're not sure """ - first, second = temp() - return first + second - -def temp2(): - """ This is weird, but correct """ - if True: - return (1, 2) - else: - if True: - return (2, 3) - return (4, 5) - -def do_stuff8(): - """ This is correct """ - first, second = temp2() - return first + second - -def do_stuff9(): - """ This is not correct """ - first, second = unpack() # [unbalanced-tuple-unpacking] - return first + second - -class UnbalancedUnpacking(object): - """ Test unbalanced tuple unpacking in instance attributes. """ - # pylint: disable=attribute-defined-outside-init, invalid-name, too-few-public-methods - def test(self): - """ unpacking in instance attributes """ - # we're not sure if temp() returns two or three values - # so we shouldn't emit an error - self.a, self.b = temp() - self.a, self.b = temp2() - self.a, self.b = unpack() # [unbalanced-tuple-unpacking] - - -def issue329(*args): - """ Don't emit unbalanced tuple unpacking if the - rhs of the assignment is a variable-length argument, - because we don't know the actual length of the tuple. - """ - first, second, third = args - return first, second, third - - -def test_decimal(): - """Test a false positive with decimal.Decimal.as_tuple - - See astroid https://bitbucket.org/logilab/astroid/issues/92/ - """ - from decimal import Decimal - dec = Decimal(2) - first, second, third = dec.as_tuple() - return first, second, third - - -def test_issue_559(): - """Test that we don't have a false positive wrt to issue #559.""" - from ctypes import c_int - root_x, root_y, win_x, win_y = [c_int()] * 4 - return root_x, root_y, win_x, win_y diff --git a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.txt b/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.txt deleted file mode 100644 index e904209e..00000000 --- a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking.txt +++ /dev/null @@ -1,6 +0,0 @@ -unbalanced-tuple-unpacking:9:do_stuff:"Possible unbalanced tuple unpacking with sequence (1, 2, 3): left side has 2 label(s), right side has 3 value(s)" -unbalanced-tuple-unpacking:14:do_stuff1:"Possible unbalanced tuple unpacking with sequence [1, 2, 3]: left side has 2 label(s), right side has 3 value(s)" -unbalanced-tuple-unpacking:19:do_stuff2:"Possible unbalanced tuple unpacking with sequence (1, 2, 3): left side has 2 label(s), right side has 3 value(s)" -unbalanced-tuple-unpacking:24:do_stuff3:"Possible unbalanced tuple unpacking with sequence (1, 2, 3): left side has 2 label(s), right side has 3 value(s)" -unbalanced-tuple-unpacking:69:do_stuff9:"Possible unbalanced tuple unpacking with sequence defined at line 7 of functional.unpacking: left side has 2 label(s), right side has 3 value(s)" -unbalanced-tuple-unpacking:81:UnbalancedUnpacking.test:"Possible unbalanced tuple unpacking with sequence defined at line 7 of functional.unpacking: left side has 2 label(s), right side has 3 value(s)" diff --git a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.py b/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.py deleted file mode 100644 index 68f5fb79..00000000 --- a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.py +++ /dev/null @@ -1,11 +0,0 @@ -""" Test that using starred nodes in unpacking -does not trigger a false positive on Python 3. -""" - -__revision__ = 1 - -def test(): - """ Test that starred expressions don't give false positives. """ - first, second, *last = (1, 2, 3, 4) - *last, = (1, 2) - return (first, second, last) diff --git a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.rc b/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.rc deleted file mode 100644 index a2ab06c5..00000000 --- a/pymode/libs/pylint/test/functional/unbalanced_tuple_unpacking_py30.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/undefined_variable.py b/pymode/libs/pylint/test/functional/undefined_variable.py deleted file mode 100644 index 94969e28..00000000 --- a/pymode/libs/pylint/test/functional/undefined_variable.py +++ /dev/null @@ -1,177 +0,0 @@ -# pylint: disable=missing-docstring, multiple-statements, redefined-variable-type -# pylint: disable=too-few-public-methods, no-init, no-self-use, old-style-class,bare-except,broad-except -from __future__ import print_function -DEFINED = 1 - -if DEFINED != 1: - if DEFINED in (unknown, DEFINED): # [undefined-variable] - DEFINED += 1 - - -def in_method(var): - """method doc""" - var = nomoreknown # [undefined-variable] - assert var - -DEFINED = {DEFINED:__revision__} # [undefined-variable] -# +1:[undefined-variable] -DEFINED[__revision__] = OTHER = 'move this is astroid test' - -OTHER += '$' - -def bad_default(var, default=unknown2): # [undefined-variable] - """function with defaut arg's value set to an unexistant name""" - print(var, default) - print(xxxx) # [undefined-variable] - augvar += 1 # [undefined-variable] - del vardel # [undefined-variable] - -LMBD = lambda x, y=doesnotexist: x+y # [undefined-variable] -LMBD2 = lambda x, y: x+z # [undefined-variable] - -try: - POUET # don't catch me -except NameError: - POUET = 'something' - -try: - POUETT # don't catch me -except Exception: # pylint:disable = broad-except - POUETT = 'something' - -try: - POUETTT # don't catch me -except: # pylint:disable = bare-except - POUETTT = 'something' - -print(POUET, POUETT, POUETTT) - - -try: - PLOUF # [used-before-assignment] -except ValueError: - PLOUF = 'something' - -print(PLOUF) - -def if_branch_test(something): - """hop""" - if something == 0: - if xxx == 1: # [used-before-assignment] - pass - else: - print(xxx) - xxx = 3 - - -def decorator(arg): - """Decorator with one argument.""" - return lambda: list(arg) - - -@decorator(arg=[i * 2 for i in range(15)]) -def func1(): - """A function with a decorator that contains a listcomp.""" - -@decorator(arg=(i * 2 for i in range(15))) -def func2(): - """A function with a decorator that contains a genexpr.""" - -@decorator(lambda x: x > 0) -def main(): - """A function with a decorator that contains a lambda.""" - -# Test shared scope. - -def test_arguments(arg=TestClass): # [used-before-assignment] - """ TestClass isn't defined yet. """ - return arg - -class TestClass(Ancestor): # [used-before-assignment] - """ contains another class, which uses an undefined ancestor. """ - - class MissingAncestor(Ancestor1): # [used-before-assignment] - """ no op """ - - def test1(self): - """ It should trigger here, because the two classes - have the same scope. - """ - class UsingBeforeDefinition(Empty): # [used-before-assignment] - """ uses Empty before definition """ - class Empty(object): - """ no op """ - return UsingBeforeDefinition - - def test(self): - """ Ancestor isn't defined yet, but we don't care. """ - class MissingAncestor1(Ancestor): - """ no op """ - return MissingAncestor1 - -class Self(object): - """ Detect when using the same name inside the class scope. """ - obj = Self # [undefined-variable] - -class Self1(object): - """ No error should be raised here. """ - - def test(self): - """ empty """ - return Self1 - - -class Ancestor(object): - """ No op """ - -class Ancestor1(object): - """ No op """ - -NANA = BAT # [undefined-variable] -del BAT - - -class KeywordArgument(object): - """Test keyword arguments.""" - - enable = True - def test(self, is_enabled=enable): - """do nothing.""" - - def test1(self, is_enabled=enabled): # [used-before-assignment] - """enabled is undefined at this point, but it is used before assignment.""" - - def test2(self, is_disabled=disabled): # [undefined-variable] - """disabled is undefined""" - - enabled = True - - func = lambda arg=arg: arg * arg # [undefined-variable] - - arg2 = 0 - func2 = lambda arg2=arg2: arg2 * arg2 - -# Don't emit if the code is protected by NameError -try: - unicode_1 -except NameError: - pass - -try: - unicode_2 # [undefined-variable] -except Exception: - pass - -try: - unicode_3 # [undefined-variable] -except: - pass - -try: - unicode_4 # [undefined-variable] -except ValueError: - pass - -# See https://bitbucket.org/logilab/pylint/issue/111/ -try: raise IOError(1, "a") -except IOError as err: print(err) diff --git a/pymode/libs/pylint/test/functional/undefined_variable.txt b/pymode/libs/pylint/test/functional/undefined_variable.txt deleted file mode 100644 index 98c6bbed..00000000 --- a/pymode/libs/pylint/test/functional/undefined_variable.txt +++ /dev/null @@ -1,24 +0,0 @@ -undefined-variable:7::Undefined variable 'unknown' -undefined-variable:13:in_method:Undefined variable 'nomoreknown' -undefined-variable:16::Undefined variable '__revision__' -undefined-variable:18::Undefined variable '__revision__' -undefined-variable:22:bad_default:Undefined variable 'unknown2' -undefined-variable:25:bad_default:Undefined variable 'xxxx' -undefined-variable:26:bad_default:Undefined variable 'augvar' -undefined-variable:27:bad_default:Undefined variable 'vardel' -undefined-variable:29::Undefined variable 'doesnotexist' -undefined-variable:30::Undefined variable 'z' -used-before-assignment:51::Using variable 'PLOUF' before assignment -used-before-assignment:60:if_branch_test:Using variable 'xxx' before assignment -used-before-assignment:86:test_arguments:Using variable 'TestClass' before assignment -used-before-assignment:90:TestClass:Using variable 'Ancestor' before assignment -used-before-assignment:93:TestClass.MissingAncestor:Using variable 'Ancestor1' before assignment -used-before-assignment:100:TestClass.test1.UsingBeforeDefinition:Using variable 'Empty' before assignment -undefined-variable:114:Self:Undefined variable 'Self' -undefined-variable:130::Undefined variable 'BAT' -used-before-assignment:141:KeywordArgument.test1:Using variable 'enabled' before assignment -undefined-variable:144:KeywordArgument.test2:Undefined variable 'disabled' -undefined-variable:149:KeywordArgument.:Undefined variable 'arg' -undefined-variable:161::Undefined variable 'unicode_2' -undefined-variable:166::Undefined variable 'unicode_3' -undefined-variable:171::Undefined variable 'unicode_4' \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/undefined_variable_py30.py b/pymode/libs/pylint/test/functional/undefined_variable_py30.py deleted file mode 100644 index 3695cf14..00000000 --- a/pymode/libs/pylint/test/functional/undefined_variable_py30.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Test warnings about access to undefined variables -for various Python 3 constructs. """ -# pylint: disable=too-few-public-methods, no-init, no-self-use -# pylint: disable=wrong-import-position -class Undefined: - """ test various annotation problems. """ - - def test(self)->Undefined: # [undefined-variable] - """ used Undefined, which is Undefined in this scope. """ - - Undefined = True - - def test1(self)->Undefined: - """ This Undefined exists at local scope. """ - - def test2(self): - """ This should not emit. """ - def func()->Undefined: - """ empty """ - return - return func - - -class Undefined1: - """ Other annotation problems. """ - - Undef = 42 - ABC = 42 - - class InnerScope: - """ Test inner scope definition. """ - - def test_undefined(self)->Undef: # [undefined-variable] - """ Looking at a higher scope is impossible. """ - - def test1(self)->ABC: # [undefined-variable] - """ Triggers undefined-variable. """ - - -class FalsePositive342(object): - # pylint: disable=line-too-long - """ Fix some false positives found in - https://bitbucket.org/logilab/pylint/issue/342/spurious-undefined-variable-for-class - """ - - top = 42 - - def test_good(self, bac: top): - """ top is defined at this moment. """ - - def test_bad(self, bac: trop): # [undefined-variable] - """ trop is undefined at this moment. """ - - def test_bad1(self, *args: trop1): # [undefined-variable] - """ trop1 is undefined at this moment. """ - - def test_bad2(self, **bac: trop2): # [undefined-variable] - """ trop2 is undefined at this moment. """ - -from abc import ABCMeta - -class Bad(metaclass=ABCMet): # [undefined-variable] - """ Notice the typo """ - -class SecondBad(metaclass=ab.ABCMeta): # [undefined-variable] - """ Notice the `ab` module. """ - -class Good(metaclass=int): - """ int is not a proper metaclass, but it is defined. """ - -class SecondGood(metaclass=Good): - """ empty """ - -class ThirdGood(metaclass=ABCMeta): - """ empty """ - -class FourthGood(ThirdGood): - """ This should not trigger anything. """ diff --git a/pymode/libs/pylint/test/functional/undefined_variable_py30.rc b/pymode/libs/pylint/test/functional/undefined_variable_py30.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/undefined_variable_py30.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/undefined_variable_py30.txt b/pymode/libs/pylint/test/functional/undefined_variable_py30.txt deleted file mode 100644 index 61ae5652..00000000 --- a/pymode/libs/pylint/test/functional/undefined_variable_py30.txt +++ /dev/null @@ -1,8 +0,0 @@ -undefined-variable:8:Undefined.test:Undefined variable 'Undefined' -undefined-variable:33:Undefined1.InnerScope.test_undefined:Undefined variable 'Undef' -undefined-variable:36:Undefined1.InnerScope.test1:Undefined variable 'ABC' -undefined-variable:51:FalsePositive342.test_bad:Undefined variable 'trop' -undefined-variable:54:FalsePositive342.test_bad1:Undefined variable 'trop1' -undefined-variable:57:FalsePositive342.test_bad2:Undefined variable 'trop2' -undefined-variable:62:Bad:Undefined variable 'ABCMet' -undefined-variable:65:SecondBad:Undefined variable 'ab.ABCMeta' \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unexpected_special_method_signature.py b/pymode/libs/pylint/test/functional/unexpected_special_method_signature.py deleted file mode 100644 index aed367e5..00000000 --- a/pymode/libs/pylint/test/functional/unexpected_special_method_signature.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Test for special methods implemented incorrectly.""" - -# pylint: disable=missing-docstring, unused-argument, too-few-public-methods -# pylint: disable=invalid-name,too-many-arguments,bad-staticmethod-argument - -class Invalid(object): - - def __enter__(self, other): # [unexpected-special-method-signature] - pass - - def __del__(self, other): # [unexpected-special-method-signature] - pass - - def __format__(self, other, other2): # [unexpected-special-method-signature] - pass - - def __setattr__(self): # [unexpected-special-method-signature] - pass - - def __round__(self, invalid, args): # [unexpected-special-method-signature] - pass - - def __deepcopy__(self, memo, other): # [unexpected-special-method-signature] - pass - - def __iter__(): # [no-method-argument] - pass - - @staticmethod - def __getattr__(self, nanana): # [unexpected-special-method-signature] - pass - - -class FirstBadContextManager(object): - def __enter__(self): - return self - def __exit__(self, exc_type): # [unexpected-special-method-signature] - pass - -class SecondBadContextManager(object): - def __enter__(self): - return self - def __exit__(self, exc_type, value, tb, stack): # [unexpected-special-method-signature] - pass - -class ThirdBadContextManager(object): - def __enter__(self): - return self - - # +1: [unexpected-special-method-signature] - def __exit__(self, exc_type, value, tb, stack, *args): - pass - - -class Async(object): - - def __aiter__(self, extra): # [unexpected-special-method-signature] - pass - def __anext__(self, extra, argument): # [unexpected-special-method-signature] - pass - def __await__(self, param): # [unexpected-special-method-signature] - pass - def __aenter__(self, first): # [unexpected-special-method-signature] - pass - def __aexit__(self): # [unexpected-special-method-signature] - pass - - -class Valid(object): - - def __new__(cls, test, multiple, args): - pass - - def __init__(self, this, can, have, multiple, args, as_well): - pass - - def __call__(self, also, trv, for_this): - pass - - def __round__(self, n): - pass - - def __index__(self, n=42): - """Expects 0 args, but we are taking in account arguments with defaults.""" - - def __deepcopy__(self, memo): - pass - - def __format__(self, format_specification=''): - pass - - def __copy__(self, this=None, is_not=None, necessary=None): - pass - - @staticmethod - def __enter__(): - pass - - @staticmethod - def __getitem__(index): - pass - - -class FirstGoodContextManager(object): - def __enter__(self): - return self - def __exit__(self, exc_type, value, tb): - pass - -class SecondGoodContextManager(object): - def __enter__(self): - return self - def __exit__(self, exc_type=None, value=None, tb=None): - pass - -class ThirdGoodContextManager(object): - def __enter__(self): - return self - def __exit__(self, exc_type, *args): - pass diff --git a/pymode/libs/pylint/test/functional/unexpected_special_method_signature.txt b/pymode/libs/pylint/test/functional/unexpected_special_method_signature.txt deleted file mode 100644 index 4fb52df6..00000000 --- a/pymode/libs/pylint/test/functional/unexpected_special_method_signature.txt +++ /dev/null @@ -1,16 +0,0 @@ -unexpected-special-method-signature:8:Invalid.__enter__:The special method '__enter__' expects 0 param(s), 1 was given -unexpected-special-method-signature:11:Invalid.__del__:The special method '__del__' expects 0 param(s), 1 was given -unexpected-special-method-signature:14:Invalid.__format__:The special method '__format__' expects 1 param(s), 2 were given -unexpected-special-method-signature:17:Invalid.__setattr__:The special method '__setattr__' expects 2 param(s), 0 was given -unexpected-special-method-signature:20:Invalid.__round__:The special method '__round__' expects between 0 or 1 param(s), 2 were given -unexpected-special-method-signature:23:Invalid.__deepcopy__:The special method '__deepcopy__' expects 1 param(s), 2 were given -no-method-argument:26:Invalid.__iter__:Method has no argument -unexpected-special-method-signature:30:Invalid.__getattr__:The special method '__getattr__' expects 1 param(s), 2 were given -unexpected-special-method-signature:37:FirstBadContextManager.__exit__:The special method '__exit__' expects 3 param(s), 1 was given -unexpected-special-method-signature:43:SecondBadContextManager.__exit__:The special method '__exit__' expects 3 param(s), 4 were given -unexpected-special-method-signature:51:ThirdBadContextManager.__exit__:The special method '__exit__' expects 3 param(s), 4 were given -unexpected-special-method-signature:57:Async.__aiter__:The special method '__aiter__' expects 0 param(s), 1 was given -unexpected-special-method-signature:59:Async.__anext__:The special method '__anext__' expects 0 param(s), 2 were given -unexpected-special-method-signature:61:Async.__await__:The special method '__await__' expects 0 param(s), 1 was given -unexpected-special-method-signature:63:Async.__aenter__:The special method '__aenter__' expects 0 param(s), 1 was given -unexpected-special-method-signature:65:Async.__aexit__:The special method '__aexit__' expects 3 param(s), 0 was given \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/ungrouped_imports.py b/pymode/libs/pylint/test/functional/ungrouped_imports.py deleted file mode 100644 index e631e60b..00000000 --- a/pymode/libs/pylint/test/functional/ungrouped_imports.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Checks import order rule""" -# pylint: disable=unused-import,relative-import,wrong-import-position,wrong-import-order,using-constant-test -# pylint: disable=import-error -import six -import logging.config -import os.path -from astroid import are_exclusive -import logging # [ungrouped-imports] -import unused_import -try: - import os # [ungrouped-imports] -except ImportError: - pass -from os import pardir -import scipy -from os import sep -import astroid # [ungrouped-imports] -if True: - import logging.handlers # [ungrouped-imports] -from os.path import join # [ungrouped-imports] diff --git a/pymode/libs/pylint/test/functional/ungrouped_imports.txt b/pymode/libs/pylint/test/functional/ungrouped_imports.txt deleted file mode 100644 index c29bb181..00000000 --- a/pymode/libs/pylint/test/functional/ungrouped_imports.txt +++ /dev/null @@ -1,5 +0,0 @@ -ungrouped-imports:8::Imports from package logging are not grouped -ungrouped-imports:11::Imports from package os are not grouped -ungrouped-imports:17::Imports from package astroid are not grouped -ungrouped-imports:19::Imports from package logging are not grouped -ungrouped-imports:20::Imports from package os are not grouped diff --git a/pymode/libs/pylint/test/functional/unidiomatic_typecheck.py b/pymode/libs/pylint/test/functional/unidiomatic_typecheck.py deleted file mode 100644 index 008456b1..00000000 --- a/pymode/libs/pylint/test/functional/unidiomatic_typecheck.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Warnings for using type(x) == Y or type(x) is Y instead of isinstance(x, Y).""" -# pylint: disable=missing-docstring,expression-not-assigned,redefined-builtin,invalid-name - -def simple_positives(): - type(42) is int # [unidiomatic-typecheck] - type(42) is not int # [unidiomatic-typecheck] - type(42) == int # [unidiomatic-typecheck] - type(42) != int # [unidiomatic-typecheck] - type(42) in [int] # [unidiomatic-typecheck] - type(42) not in [int] # [unidiomatic-typecheck] - -def simple_inference_positives(): - alias = type - alias(42) is int # [unidiomatic-typecheck] - alias(42) is not int # [unidiomatic-typecheck] - alias(42) == int # [unidiomatic-typecheck] - alias(42) != int # [unidiomatic-typecheck] - alias(42) in [int] # [unidiomatic-typecheck] - alias(42) not in [int] # [unidiomatic-typecheck] - -def type_creation_negatives(): - type('Q', (object,), dict(a=1)) is int - type('Q', (object,), dict(a=1)) is not int - type('Q', (object,), dict(a=1)) == int - type('Q', (object,), dict(a=1)) != int - type('Q', (object,), dict(a=1)) in [int] - type('Q', (object,), dict(a=1)) not in [int] - -def invalid_type_call_negatives(**kwargs): - type(bad=7) is int - type(bad=7) is not int - type(bad=7) == int - type(bad=7) != int - type(bad=7) in [int] - type(bad=7) not in [int] - type('bad', 7) is int - type('bad', 7) is not int - type('bad', 7) == int - type('bad', 7) != int - type('bad', 7) in [int] - type('bad', 7) not in [int] - type(**kwargs) is int - type(**kwargs) is not int - type(**kwargs) == int - type(**kwargs) != int - type(**kwargs) in [int] - type(**kwargs) not in [int] - -def local_var_shadowing_inference_negatives(): - type = lambda dummy: 7 - type(42) is int - type(42) is not int - type(42) == int - type(42) != int - type(42) in [int] - type(42) not in [int] - -def parameter_shadowing_inference_negatives(type): - type(42) is int - type(42) is not int - type(42) == int - type(42) != int - type(42) in [int] - type(42) not in [int] - -def deliberate_subclass_check_negatives(b): - type(42) is type(b) - type(42) is not type(b) - -def type_of_literals_positives(a): - type(a) is type([]) # [unidiomatic-typecheck] - type(a) is not type([]) # [unidiomatic-typecheck] - type(a) is type({}) # [unidiomatic-typecheck] - type(a) is not type({}) # [unidiomatic-typecheck] - type(a) is type("") # [unidiomatic-typecheck] - type(a) is not type("") # [unidiomatic-typecheck] diff --git a/pymode/libs/pylint/test/functional/unidiomatic_typecheck.txt b/pymode/libs/pylint/test/functional/unidiomatic_typecheck.txt deleted file mode 100644 index 23c0f6f2..00000000 --- a/pymode/libs/pylint/test/functional/unidiomatic_typecheck.txt +++ /dev/null @@ -1,18 +0,0 @@ -unidiomatic-typecheck:5:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:6:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:7:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:8:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:9:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:10:simple_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:14:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:15:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:16:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:17:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:18:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:19:simple_inference_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:71:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:72:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:73:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:74:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:75:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. -unidiomatic-typecheck:76:type_of_literals_positives:Using type() instead of isinstance() for a typecheck. \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/uninferable_all_object.py b/pymode/libs/pylint/test/functional/uninferable_all_object.py deleted file mode 100644 index 3e565f9e..00000000 --- a/pymode/libs/pylint/test/functional/uninferable_all_object.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Test that non-inferable __all__ variables do not make Pylint crash.""" - -__all__ = sorted([ - 'Dummy', - 'NonExistant', - 'path', - 'func', - 'inner', - 'InnerKlass']) diff --git a/pymode/libs/pylint/test/functional/unnecessary_lambda.py b/pymode/libs/pylint/test/functional/unnecessary_lambda.py deleted file mode 100644 index eacb33d9..00000000 --- a/pymode/libs/pylint/test/functional/unnecessary_lambda.py +++ /dev/null @@ -1,51 +0,0 @@ -# pylint: disable=undefined-variable -"""test suspicious lambda expressions -""" - -__revision__ = '' - -# Some simple examples of the most commonly encountered forms. -# +1: [unnecessary-lambda] -_ = lambda: list() # replaceable with "list" -# +1: [unnecessary-lambda] -_ = lambda x: hash(x) # replaceable with "hash" -# +1: [unnecessary-lambda] -_ = lambda x, y: min(x, y) # replaceable with "min" - -# A function that can take any arguments given to it. -_ANYARGS = lambda *args, **kwargs: 'completely arbitrary return value' - -# Some more complex forms of unnecessary lambda expressions. -# +1: [unnecessary-lambda] -_ = lambda *args: _ANYARGS(*args) -# +1: [unnecessary-lambda] -_ = lambda **kwargs: _ANYARGS(**kwargs) -# +1: [unnecessary-lambda] -_ = lambda *args, **kwargs: _ANYARGS(*args, **kwargs) -# +1: [unnecessary-lambda] -_ = lambda x, y, z, *args, **kwargs: _ANYARGS(x, y, z, *args, **kwargs) - -# Lambdas that are *not* unnecessary and should *not* trigger warnings. -_ = lambda x: x -_ = lambda x: x() -_ = lambda x=4: hash(x) -_ = lambda x, y: list(range(y, x)) -_ = lambda x: list(range(5, x)) -_ = lambda x, y: list(range(x, 5)) -_ = lambda x, y, z: x.y(z) -_ = lambda: 5 -_ = lambda **kwargs: _ANYARGS() -_ = lambda **kwargs: _ANYARGS(**dict([('three', 3)])) -_ = lambda **kwargs: _ANYARGS(**{'three': 3}) -_ = lambda dict_arg, **kwargs: _ANYARGS(kwargs, **dict_arg) -_ = lambda *args: _ANYARGS() -_ = lambda *args: _ANYARGS(*list([3, 4])) -_ = lambda *args: _ANYARGS(*[3, 4]) -_ = lambda list_arg, *args: _ANYARGS(args, *list_arg) -_ = lambda: _ANYARGS(*[3]) -_ = lambda: _ANYARGS(**{'three': 3}) -_ = lambda: _ANYARGS(*[3], **{'three': 3}) -_ = lambda: _ANYARGS(func=42) - -# Don't warn about this. -_ = lambda: code().analysis() diff --git a/pymode/libs/pylint/test/functional/unnecessary_lambda.txt b/pymode/libs/pylint/test/functional/unnecessary_lambda.txt deleted file mode 100644 index de13882a..00000000 --- a/pymode/libs/pylint/test/functional/unnecessary_lambda.txt +++ /dev/null @@ -1,7 +0,0 @@ -unnecessary-lambda:9::Lambda may not be necessary -unnecessary-lambda:11::Lambda may not be necessary -unnecessary-lambda:13::Lambda may not be necessary -unnecessary-lambda:20::Lambda may not be necessary -unnecessary-lambda:22::Lambda may not be necessary -unnecessary-lambda:24::Lambda may not be necessary -unnecessary-lambda:26::Lambda may not be necessary diff --git a/pymode/libs/pylint/test/functional/unnecessary_pass.py b/pymode/libs/pylint/test/functional/unnecessary_pass.py deleted file mode 100644 index 5bf7e8ba..00000000 --- a/pymode/libs/pylint/test/functional/unnecessary_pass.py +++ /dev/null @@ -1,7 +0,0 @@ -# pylint: disable=missing-docstring - -try: - A = 2 -except ValueError: - A = 24 - pass # [unnecessary-pass] diff --git a/pymode/libs/pylint/test/functional/unnecessary_pass.txt b/pymode/libs/pylint/test/functional/unnecessary_pass.txt deleted file mode 100644 index e3a74488..00000000 --- a/pymode/libs/pylint/test/functional/unnecessary_pass.txt +++ /dev/null @@ -1 +0,0 @@ -unnecessary-pass:7::Unnecessary pass statement diff --git a/pymode/libs/pylint/test/functional/unneeded_not.py b/pymode/libs/pylint/test/functional/unneeded_not.py deleted file mode 100644 index de48c0fb..00000000 --- a/pymode/libs/pylint/test/functional/unneeded_not.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Check exceeding negations in boolean expressions trigger warnings""" - -# pylint: disable=singleton-comparison,too-many-branches,too-few-public-methods,undefined-variable - -def unneeded_not(): - """This is not ok - """ - bool_var = True - someint = 2 - if not not bool_var: # [unneeded-not] - pass - if not someint == 1: # [unneeded-not] - pass - if not someint != 1: # [unneeded-not] - pass - if not someint < 1: # [unneeded-not] - pass - if not someint > 1: # [unneeded-not] - pass - if not someint <= 1: # [unneeded-not] - pass - if not someint >= 1: # [unneeded-not] - pass - if not not someint: # [unneeded-not] - pass - if not bool_var == True: # [unneeded-not] - pass - if not bool_var == False: # [unneeded-not] - pass - if not bool_var != True: # [unneeded-not] - pass - if not True == True: # [unneeded-not] - pass - if not 2 in [3, 4]: # [unneeded-not] - pass - if not someint is 'test': # [unneeded-not] - pass - - -def tolerated_statements(): - """This is ok""" - bool_var = True - someint = 2 - if not(bool_var == False and someint == 1): - pass - if 2 not in [3, 4]: - pass - if not someint == bool_var == 2: - pass - if not 2 <= someint < 3 < 4: - pass - if not set('bar') <= set('foobaz'): - pass - if not set(something) <= 3: - pass - if not frozenset(something) <= 3: - pass - - -class Klass(object): - """This is also ok""" - def __ne__(self, other): - return not self == other diff --git a/pymode/libs/pylint/test/functional/unneeded_not.txt b/pymode/libs/pylint/test/functional/unneeded_not.txt deleted file mode 100644 index 13b35129..00000000 --- a/pymode/libs/pylint/test/functional/unneeded_not.txt +++ /dev/null @@ -1,14 +0,0 @@ -unneeded-not:10:unneeded_not:Consider changing "not not bool_var" to "bool_var" -unneeded-not:12:unneeded_not:Consider changing "not someint == 1" to "someint != 1" -unneeded-not:14:unneeded_not:Consider changing "not someint != 1" to "someint == 1" -unneeded-not:16:unneeded_not:Consider changing "not someint < 1" to "someint >= 1" -unneeded-not:18:unneeded_not:Consider changing "not someint > 1" to "someint <= 1" -unneeded-not:20:unneeded_not:Consider changing "not someint <= 1" to "someint > 1" -unneeded-not:22:unneeded_not:Consider changing "not someint >= 1" to "someint < 1" -unneeded-not:24:unneeded_not:Consider changing "not not someint" to "someint" -unneeded-not:26:unneeded_not:Consider changing "not bool_var == True" to "bool_var != True" -unneeded-not:28:unneeded_not:Consider changing "not bool_var == False" to "bool_var != False" -unneeded-not:30:unneeded_not:Consider changing "not bool_var != True" to "bool_var == True" -unneeded-not:32:unneeded_not:Consider changing "not True == True" to "True != True" -unneeded-not:34:unneeded_not:Consider changing "not 2 in [3, 4]" to "2 not in [3, 4]" -unneeded-not:36:unneeded_not:Consider changing "not someint is 'test'" to "someint is not 'test'" diff --git a/pymode/libs/pylint/test/functional/unpacked_exceptions.py b/pymode/libs/pylint/test/functional/unpacked_exceptions.py deleted file mode 100644 index ec3599c3..00000000 --- a/pymode/libs/pylint/test/functional/unpacked_exceptions.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Test for redefine-in-handler, overwriting names in exception handlers.""" - -def new_style(): - """Some exceptions can be unpacked.""" - try: - pass - except IOError, (errno, message): # [unpacking-in-except] - print errno, message # pylint: disable=print-statement - # +1: [redefine-in-handler,redefine-in-handler,unpacking-in-except] - except IOError, (new_style, tuple): # pylint: disable=duplicate-except - print new_style, tuple # pylint: disable=print-statement diff --git a/pymode/libs/pylint/test/functional/unpacked_exceptions.rc b/pymode/libs/pylint/test/functional/unpacked_exceptions.rc deleted file mode 100644 index 9540bc95..00000000 --- a/pymode/libs/pylint/test/functional/unpacked_exceptions.rc +++ /dev/null @@ -1,5 +0,0 @@ -[testoptions] -max_pyver=3.0 - -[Messages Control] -enable=python3 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unpacked_exceptions.txt b/pymode/libs/pylint/test/functional/unpacked_exceptions.txt deleted file mode 100644 index 1a1b0342..00000000 --- a/pymode/libs/pylint/test/functional/unpacked_exceptions.txt +++ /dev/null @@ -1,4 +0,0 @@ -unpacking-in-except:7:new_style:Implicit unpacking of exceptions is not supported in Python 3 -redefine-in-handler:10:new_style:Redefining name 'new_style' from outer scope (line 3) in exception handler -redefine-in-handler:10:new_style:Redefining name 'tuple' from builtins in exception handler -unpacking-in-except:10:new_style:Implicit unpacking of exceptions is not supported in Python 3 diff --git a/pymode/libs/pylint/test/functional/unpacking.py b/pymode/libs/pylint/test/functional/unpacking.py deleted file mode 100644 index 920caaac..00000000 --- a/pymode/libs/pylint/test/functional/unpacking.py +++ /dev/null @@ -1,11 +0,0 @@ -""" Code for checking the display of the module -for unbalanced-tuple-unpacking and unpacking-non-sequence -""" - -def unpack(): - """ Return something""" - return (1, 2, 3) - -def nonseq(): - """ Return non sequence """ - return 1 diff --git a/pymode/libs/pylint/test/functional/unpacking_generalizations.py b/pymode/libs/pylint/test/functional/unpacking_generalizations.py deleted file mode 100644 index 3a9d8176..00000000 --- a/pymode/libs/pylint/test/functional/unpacking_generalizations.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Various tests for unpacking generalizations added in Python 3.5""" - -# pylint: disable=missing-docstring, invalid-name - -def func_variadic_args(*args): - return args - - -def func_variadic_positional_args(a, b, *args): - return a, b, args - -def func_positional_args(a, b, c, d): - return a, b, c, d - - -func_variadic_args(*(2, 3), *(3, 4), *(4, 5)) -func_variadic_args(1, 2, *(2, 3), 2, 3, *(4, 5)) -func_variadic_positional_args(1, 2, *(4, 5), *(5, 6)) -func_variadic_positional_args(*(2, 3), *(4, 5), *(5, 6)) -func_variadic_positional_args(*(2, 3)) -func_variadic_positional_args(*(2, 3, 4)) -func_variadic_positional_args(1, 2, 3, *(3, 4)) - -func_positional_args(*(2, 3, 4), *(2, 3)) # [too-many-function-args] -func_positional_args(*(1, 2), 3) # [no-value-for-parameter] -func_positional_args(1, *(2, ), 3, *(4, 5)) # [too-many-function-args] -func_positional_args(1, 2, c=24, d=32, **{'d': 32}) # [repeated-keyword] -# +1: [repeated-keyword,repeated-keyword] -func_positional_args(1, 2, c=24, **{'c': 34, 'd': 33}, **{'d': 24}) diff --git a/pymode/libs/pylint/test/functional/unpacking_generalizations.rc b/pymode/libs/pylint/test/functional/unpacking_generalizations.rc deleted file mode 100644 index 03004f2c..00000000 --- a/pymode/libs/pylint/test/functional/unpacking_generalizations.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unpacking_generalizations.txt b/pymode/libs/pylint/test/functional/unpacking_generalizations.txt deleted file mode 100644 index d92fcc91..00000000 --- a/pymode/libs/pylint/test/functional/unpacking_generalizations.txt +++ /dev/null @@ -1,6 +0,0 @@ -too-many-function-args:24::Too many positional arguments for function call -no-value-for-parameter:25::"No value for argument 'd' in function call" -too-many-function-args:26::Too many positional arguments for function call -repeated-keyword:27::Got multiple values for keyword argument 'd' in function call -repeated-keyword:29::Got multiple values for keyword argument 'c' in function call -repeated-keyword:29::Got multiple values for keyword argument 'd' in function call \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unpacking_non_sequence.py b/pymode/libs/pylint/test/functional/unpacking_non_sequence.py deleted file mode 100644 index c03b63dd..00000000 --- a/pymode/libs/pylint/test/functional/unpacking_non_sequence.py +++ /dev/null @@ -1,119 +0,0 @@ -"""Check unpacking non-sequences in assignments. """ - -# pylint: disable=too-few-public-methods, invalid-name, attribute-defined-outside-init, unused-variable, no-absolute-import -# pylint: disable=using-constant-test, no-init -from os import rename as nonseq_func -from six import with_metaclass -from functional.unpacking import nonseq - -__revision__ = 0 - -# Working - -class Seq(object): - """ sequence """ - def __init__(self): - self.items = range(2) - - def __getitem__(self, item): - return self.items[item] - - def __len__(self): - return len(self.items) - -class Iter(object): - """ Iterator """ - def __iter__(self): - for number in range(2): - yield number - -def good_unpacking(): - """ returns should be unpackable """ - if True: - return [1, 2] - else: - return (3, 4) - -def good_unpacking2(): - """ returns should be unpackable """ - return good_unpacking() - -class MetaIter(type): - "metaclass that makes classes that use it iterables" - def __iter__(cls): - return iter((1, 2)) - -class IterClass(with_metaclass(MetaIter)): - "class that is iterable (and unpackable)" - -class AbstrClass(object): - "abstract class" - pair = None - - def setup_pair(self): - "abstract method" - raise NotImplementedError - - def __init__(self): - "error should not be emitted because setup_pair is abstract" - self.setup_pair() - x, y = self.pair - -a, b = [1, 2] -a, b = (1, 2) -a, b = set([1, 2]) -a, b = {1: 2, 2: 3} -a, b = "xy" -a, b = Seq() -a, b = Iter() -a, b = (number for number in range(2)) -a, b = good_unpacking() -a, b = good_unpacking2() -a, b = IterClass - -# Not working -class NonSeq(object): - """ does nothing """ - -a, b = NonSeq() # [unpacking-non-sequence] -a, b = ValueError # [unpacking-non-sequence] -a, b = None # [unpacking-non-sequence] -a, b = 1 # [unpacking-non-sequence] -a, b = nonseq # [unpacking-non-sequence] -a, b = nonseq() # [unpacking-non-sequence] -a, b = nonseq_func # [unpacking-non-sequence] - -class ClassUnpacking(object): - """ Check unpacking as instance attributes. """ - - def test(self): - """ test unpacking in instance attributes. """ - - self.a, self.b = 1, 2 - self.a, self.b = {1: 2, 2: 3} - self.a, self.b = "xy" - self.a, c = "xy" - c, self.a = good_unpacking() - self.a, self.b = Iter() - - self.a, self.b = NonSeq() # [unpacking-non-sequence] - self.a, self.b = ValueError # [unpacking-non-sequence] - self.a, c = nonseq_func # [unpacking-non-sequence] - -class TestBase(object): - 'base class with `test` method implementation' - @staticmethod - def test(data): - 'default implementation' - return data - -class Test(TestBase): - 'child class that overrides `test` method' - def __init__(self): - # no error should be emitted here as `test` is overriden in this class - (self.aaa, self.bbb, self.ccc) = self.test(None) - - @staticmethod - def test(data): - 'overridden implementation' - return (1, 2, 3) diff --git a/pymode/libs/pylint/test/functional/unpacking_non_sequence.txt b/pymode/libs/pylint/test/functional/unpacking_non_sequence.txt deleted file mode 100644 index 0a21fab4..00000000 --- a/pymode/libs/pylint/test/functional/unpacking_non_sequence.txt +++ /dev/null @@ -1,10 +0,0 @@ -unpacking-non-sequence:78::Attempting to unpack a non-sequence defined at line 75 -unpacking-non-sequence:79::Attempting to unpack a non-sequence -unpacking-non-sequence:80::Attempting to unpack a non-sequence None -unpacking-non-sequence:81::Attempting to unpack a non-sequence 1 -unpacking-non-sequence:82::Attempting to unpack a non-sequence defined at line 9 of functional.unpacking -unpacking-non-sequence:83::Attempting to unpack a non-sequence defined at line 11 of functional.unpacking -unpacking-non-sequence:84::Attempting to unpack a non-sequence -unpacking-non-sequence:99:ClassUnpacking.test:Attempting to unpack a non-sequence defined at line 75 -unpacking-non-sequence:100:ClassUnpacking.test:Attempting to unpack a non-sequence -unpacking-non-sequence:101:ClassUnpacking.test:Attempting to unpack a non-sequence diff --git a/pymode/libs/pylint/test/functional/unreachable.py b/pymode/libs/pylint/test/functional/unreachable.py deleted file mode 100644 index b03dec88..00000000 --- a/pymode/libs/pylint/test/functional/unreachable.py +++ /dev/null @@ -1,22 +0,0 @@ -# pylint: disable=missing-docstring - -from __future__ import print_function - -def func1(): - return 1 - print('unreachable') # [unreachable] - -def func2(): - while 1: - break - print('unreachable') # [unreachable] - -def func3(): - for i in (1, 2, 3): - print(i) - continue - print('unreachable') # [unreachable] - -def func4(): - raise Exception - return 1 / 0 # [unreachable] diff --git a/pymode/libs/pylint/test/functional/unreachable.txt b/pymode/libs/pylint/test/functional/unreachable.txt deleted file mode 100644 index 469cd01f..00000000 --- a/pymode/libs/pylint/test/functional/unreachable.txt +++ /dev/null @@ -1,4 +0,0 @@ -unreachable:7:func1:Unreachable code -unreachable:12:func2:Unreachable code -unreachable:18:func3:Unreachable code -unreachable:22:func4:Unreachable code \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unrecognized_inline_option.py b/pymode/libs/pylint/test/functional/unrecognized_inline_option.py deleted file mode 100644 index 1d7ec26b..00000000 --- a/pymode/libs/pylint/test/functional/unrecognized_inline_option.py +++ /dev/null @@ -1,3 +0,0 @@ -# +1: [unrecognized-inline-option] -# pylint:bouboule=1 -"""Check unknown option""" diff --git a/pymode/libs/pylint/test/functional/unrecognized_inline_option.txt b/pymode/libs/pylint/test/functional/unrecognized_inline_option.txt deleted file mode 100644 index 922cc927..00000000 --- a/pymode/libs/pylint/test/functional/unrecognized_inline_option.txt +++ /dev/null @@ -1 +0,0 @@ -unrecognized-inline-option:2::"Unrecognized file option 'bouboule'" diff --git a/pymode/libs/pylint/test/functional/unsubscriptable_value.py b/pymode/libs/pylint/test/functional/unsubscriptable_value.py deleted file mode 100644 index 4f1848a5..00000000 --- a/pymode/libs/pylint/test/functional/unsubscriptable_value.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Checks that value used in a subscript supports subscription -(i.e. defines __getitem__ method). -""" -# pylint: disable=missing-docstring,pointless-statement,expression-not-assigned,wrong-import-position -# pylint: disable=too-few-public-methods,import-error,invalid-name,wrong-import-order -import six - -# primitives -numbers = [1, 2, 3] -numbers[0] -"123"[0] -u"123"[0] -b"123"[0] -bytearray(b"123")[0] -dict(a=1, b=2)['a'] -(1, 2, 3)[0] - -# list/dict comprehensions are fine -[x for x in range(10)][0] -{x: 10 - x for x in range(10)}[0] - - -# instances -class NonSubscriptable(object): - pass - -class Subscriptable(object): - def __getitem__(self, key): - return key + key - -NonSubscriptable()[0] # [unsubscriptable-object] -NonSubscriptable[0] # [unsubscriptable-object] -Subscriptable()[0] -Subscriptable[0] # [unsubscriptable-object] - -# generators are not subscriptable -def powers_of_two(): - k = 0 - while k < 10: - yield 2 ** k - k += 1 - -powers_of_two()[0] # [unsubscriptable-object] -powers_of_two[0] # [unsubscriptable-object] - - -# check that primitive non subscriptable types are catched -True[0] # [unsubscriptable-object] -None[0] # [unsubscriptable-object] -8.5[0] # [unsubscriptable-object] -10[0] # [unsubscriptable-object] - -# sets are not subscriptable -{x ** 2 for x in range(10)}[0] # [unsubscriptable-object] -set(numbers)[0] # [unsubscriptable-object] -frozenset(numbers)[0] # [unsubscriptable-object] - -# skip instances with unknown base classes -from some_missing_module import LibSubscriptable - -class MaybeSubscriptable(LibSubscriptable): - pass - -MaybeSubscriptable()[0] - -# subscriptable classes (through metaclasses) - -class MetaSubscriptable(type): - def __getitem__(cls, key): - return key + key - -class SubscriptableClass(six.with_metaclass(MetaSubscriptable, object)): - pass - -SubscriptableClass[0] -SubscriptableClass()[0] # [unsubscriptable-object] - -# functions are not subscriptable -def test(*args, **kwargs): - return args, kwargs - -test()[0] -test[0] # [unsubscriptable-object] - -# deque -from collections import deque -deq = deque(maxlen=10) -deq.append(42) -deq[0] - - -class AbstractClass(object): - - def __init__(self): - self.ala = {i for i in range(10)} - self.bala = [i for i in range(10)] - self.portocala = None - - def test_unsubscriptable(self): - self.bala[0] - self.portocala[0] - - -class ClassMixin(object): - - def __init__(self): - self.ala = {i for i in range(10)} - self.bala = [i for i in range(10)] - self.portocala = None - - def test_unsubscriptable(self): - self.bala[0] - self.portocala[0] - \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unsubscriptable_value.txt b/pymode/libs/pylint/test/functional/unsubscriptable_value.txt deleted file mode 100644 index 64ea3c79..00000000 --- a/pymode/libs/pylint/test/functional/unsubscriptable_value.txt +++ /dev/null @@ -1,14 +0,0 @@ -unsubscriptable-object:32::Value 'NonSubscriptable()' is unsubscriptable -unsubscriptable-object:33::Value 'NonSubscriptable' is unsubscriptable -unsubscriptable-object:35::Value 'Subscriptable' is unsubscriptable -unsubscriptable-object:44::Value 'powers_of_two()' is unsubscriptable -unsubscriptable-object:45::Value 'powers_of_two' is unsubscriptable -unsubscriptable-object:49::Value 'True' is unsubscriptable -unsubscriptable-object:50::Value 'None' is unsubscriptable -unsubscriptable-object:51::Value '8.5' is unsubscriptable -unsubscriptable-object:52::Value '10' is unsubscriptable -unsubscriptable-object:55::Value '{(x) ** (2) for x in range(10)}' is unsubscriptable -unsubscriptable-object:56::Value 'set(numbers)' is unsubscriptable -unsubscriptable-object:57::Value 'frozenset(numbers)' is unsubscriptable -unsubscriptable-object:77::Value 'SubscriptableClass()' is unsubscriptable -unsubscriptable-object:84::Value 'test' is unsubscriptable diff --git a/pymode/libs/pylint/test/functional/unsubscriptable_value_35.py b/pymode/libs/pylint/test/functional/unsubscriptable_value_35.py deleted file mode 100644 index c92b826b..00000000 --- a/pymode/libs/pylint/test/functional/unsubscriptable_value_35.py +++ /dev/null @@ -1,5 +0,0 @@ -# pylint: disable=missing-docstring, invalid-name - -import typing - -val = typing.Sequence[int] diff --git a/pymode/libs/pylint/test/functional/unsubscriptable_value_35.rc b/pymode/libs/pylint/test/functional/unsubscriptable_value_35.rc deleted file mode 100644 index 71de8b63..00000000 --- a/pymode/libs/pylint/test/functional/unsubscriptable_value_35.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 diff --git a/pymode/libs/pylint/test/functional/unsupported_binary_operation.py b/pymode/libs/pylint/test/functional/unsupported_binary_operation.py deleted file mode 100644 index fce27479..00000000 --- a/pymode/libs/pylint/test/functional/unsupported_binary_operation.py +++ /dev/null @@ -1,59 +0,0 @@ -"""Test for unsupported-binary-operation.""" -# pylint: disable=missing-docstring,too-few-public-methods,pointless-statement -# pylint: disable=expression-not-assigned, invalid-name - - -import collections - - -1 + "a" # [unsupported-binary-operation] -1 - [] # [unsupported-binary-operation] -1 * {} # [unsupported-binary-operation] -1 / collections # [unsupported-binary-operation] -1 ** (lambda x: x) # [unsupported-binary-operation] -{} * {} # [unsupported-binary-operation] -{} - {} # [unsupported-binary-operation] -{} | {} # [unsupported-binary-operation] -{} >> {} # [unsupported-binary-operation] -[] + () # [unsupported-binary-operation] -() + [] # [unsupported-binary-operation] -[] * 2.0 # [unsupported-binary-operation] -() * 2.0 # [unsupported-binary-operation] -2.0 >> 2.0 # [unsupported-binary-operation] -class A(object): - pass -class B(object): - pass -A() + B() # [unsupported-binary-operation] -class A1(object): - def __add__(self, other): - return NotImplemented - -A1() + A1() # [unsupported-binary-operation] - -class A2(object): - def __add__(self, other): - return NotImplemented -class B2(object): - def __radd__(self, other): - return NotImplemented -A2() + B2() # [unsupported-binary-operation] - -class Parent(object): - pass -class Child(Parent): - def __add__(self, other): - return NotImplemented -Child() + Parent() # [unsupported-binary-operation] -class A3(object): - def __add__(self, other): - return NotImplemented -class B3(A3): - def __radd__(self, other): - return NotImplemented -A3() + B3() # [unsupported-binary-operation] -# Augmented -FFF = 1 -FFF += A() # [unsupported-binary-operation] -TTT = 1 -TTT += [] # [unsupported-binary-operation] diff --git a/pymode/libs/pylint/test/functional/unsupported_binary_operation.rc b/pymode/libs/pylint/test/functional/unsupported_binary_operation.rc deleted file mode 100644 index 401ccfe2..00000000 --- a/pymode/libs/pylint/test/functional/unsupported_binary_operation.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=4.0 diff --git a/pymode/libs/pylint/test/functional/unsupported_binary_operation.txt b/pymode/libs/pylint/test/functional/unsupported_binary_operation.txt deleted file mode 100644 index 8f232f77..00000000 --- a/pymode/libs/pylint/test/functional/unsupported_binary_operation.txt +++ /dev/null @@ -1,21 +0,0 @@ -unsupported-binary-operation:9::"unsupported operand type(s) for +: 'int' and 'str'" -unsupported-binary-operation:10::"unsupported operand type(s) for -: 'int' and 'list'" -unsupported-binary-operation:11::"unsupported operand type(s) for *: 'int' and 'dict'" -unsupported-binary-operation:12::"unsupported operand type(s) for /: 'int' and 'module'" -unsupported-binary-operation:13::"unsupported operand type(s) for **: 'int' and 'function'" -unsupported-binary-operation:14::"unsupported operand type(s) for *: 'dict' and 'dict'" -unsupported-binary-operation:15::"unsupported operand type(s) for -: 'dict' and 'dict'" -unsupported-binary-operation:16::"unsupported operand type(s) for |: 'dict' and 'dict'" -unsupported-binary-operation:17::"unsupported operand type(s) for >>: 'dict' and 'dict'" -unsupported-binary-operation:18::"unsupported operand type(s) for +: 'list' and 'tuple'" -unsupported-binary-operation:19::"unsupported operand type(s) for +: 'tuple' and 'list'" -unsupported-binary-operation:20::"unsupported operand type(s) for *: 'list' and 'float'" -unsupported-binary-operation:21::"unsupported operand type(s) for *: 'tuple' and 'float'" -unsupported-binary-operation:22::"unsupported operand type(s) for >>: 'float' and 'float'" -unsupported-binary-operation:27::"unsupported operand type(s) for +: 'A' and 'B'" -unsupported-binary-operation:32::"unsupported operand type(s) for +: 'A1' and 'A1'" -unsupported-binary-operation:40::"unsupported operand type(s) for +: 'A2' and 'B2'" -unsupported-binary-operation:47::"unsupported operand type(s) for +: 'Child' and 'Parent'" -unsupported-binary-operation:54::"unsupported operand type(s) for +: 'A3' and 'B3'" -unsupported-binary-operation:57::"unsupported operand type(s) for +=: 'int' and 'A'" -unsupported-binary-operation:59::"unsupported operand type(s) for +=: 'int' and 'list'" \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/unused_import.py b/pymode/libs/pylint/test/functional/unused_import.py deleted file mode 100644 index d1a4c6b1..00000000 --- a/pymode/libs/pylint/test/functional/unused_import.py +++ /dev/null @@ -1,18 +0,0 @@ -"""unused import""" -# pylint: disable=undefined-all-variable, import-error, no-absolute-import, too-few-public-methods, missing-docstring,wrong-import-position -import xml.etree # [unused-import] -import xml.sax # [unused-import] -import os.path as test # [unused-import] -from sys import argv as test2 # [unused-import] -from sys import flags # [unused-import] -# +1:[unused-import,unused-import] -from collections import deque, OrderedDict, Counter -DATA = Counter() - -from fake import SomeName, SomeOtherName # [unused-import] -class SomeClass(object): - SomeName = SomeName # https://bitbucket.org/logilab/pylint/issue/475 - SomeOtherName = 1 - SomeOtherName = SomeOtherName - -from never import __all__ diff --git a/pymode/libs/pylint/test/functional/unused_import.txt b/pymode/libs/pylint/test/functional/unused_import.txt deleted file mode 100644 index 9d6497f9..00000000 --- a/pymode/libs/pylint/test/functional/unused_import.txt +++ /dev/null @@ -1,8 +0,0 @@ -unused-import:3::Unused import xml.etree -unused-import:4::Unused import xml.sax -unused-import:5::Unused os.path imported as test -unused-import:6::Unused argv imported from sys as test2 -unused-import:7::Unused flags imported from sys -unused-import:9::Unused OrderedDict imported from collections -unused-import:9::Unused deque imported from collections -unused-import:12::Unused SomeOtherName imported from fake diff --git a/pymode/libs/pylint/test/functional/unused_variable.py b/pymode/libs/pylint/test/functional/unused_variable.py deleted file mode 100644 index 09dd448f..00000000 --- a/pymode/libs/pylint/test/functional/unused_variable.py +++ /dev/null @@ -1,16 +0,0 @@ -# pylint: disable=missing-docstring, invalid-name - -def test_regression_737(): - import xml # [unused-variable] - -def test_regression_923(): - import unittest.case # [unused-variable] - import xml as sql # [unused-variable] - -def test_unused_with_prepended_underscore(): - _foo = 42 - _ = 24 - __a = 24 - dummy = 24 - _a_ = 42 # [unused-variable] - __a__ = 24 # [unused-variable] diff --git a/pymode/libs/pylint/test/functional/unused_variable.txt b/pymode/libs/pylint/test/functional/unused_variable.txt deleted file mode 100644 index ddd5a399..00000000 --- a/pymode/libs/pylint/test/functional/unused_variable.txt +++ /dev/null @@ -1,5 +0,0 @@ -unused-variable:4:test_regression_737:Unused variable 'xml' -unused-variable:7:test_regression_923:Unused variable 'unittest.case' -unused-variable:8:test_regression_923:Unused variable 'sql' -unused-variable:15:test_unused_with_prepended_underscore:Unused variable '_a_' -unused-variable:16:test_unused_with_prepended_underscore:Unused variable '__a__' \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.py b/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.py deleted file mode 100644 index 32bb10a3..00000000 --- a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.py +++ /dev/null @@ -1,47 +0,0 @@ -"""Check for nonlocal and used-before-assignment""" -# pylint: disable=missing-docstring, unused-variable, no-init, too-few-public-methods - -__revision__ = 0 - -def test_ok(): - """ uses nonlocal """ - cnt = 1 - def wrap(): - nonlocal cnt - cnt = cnt + 1 - wrap() - -def test_fail(): - """ doesn't use nonlocal """ - cnt = 1 - def wrap(): - cnt = cnt + 1 # [used-before-assignment] - wrap() - -def test_fail2(): - """ use nonlocal, but for other variable """ - cnt = 1 - count = 1 - def wrap(): - nonlocal count - cnt = cnt + 1 # [used-before-assignment] - wrap() - -def test_fail3(arg: test_fail4): # [used-before-assignment] - """ Depends on `test_fail4`, in argument annotation. """ - return arg -# +1: [used-before-assignment, used-before-assignment] -def test_fail4(*args: test_fail5, **kwargs: undefined): - """ Depends on `test_fail5` and `undefined` in - variable and named arguments annotations. - """ - return args, kwargs - -def test_fail5()->undefined1: # [used-before-assignment] - """ Depends on `undefined1` in function return annotation. """ - -def undefined(): - """ no op """ - -def undefined1(): - """ no op """ diff --git a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.rc b/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.rc deleted file mode 100644 index c093be20..00000000 --- a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.0 diff --git a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.txt b/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.txt deleted file mode 100644 index 7c51b1c4..00000000 --- a/pymode/libs/pylint/test/functional/used_before_assignment_nonlocal.txt +++ /dev/null @@ -1,6 +0,0 @@ -used-before-assignment:18:test_fail.wrap:Using variable 'cnt' before assignment -used-before-assignment:27:test_fail2.wrap:Using variable 'cnt' before assignment -used-before-assignment:30:test_fail3:Using variable 'test_fail4' before assignment -used-before-assignment:34:test_fail4:Using variable 'test_fail5' before assignment -used-before-assignment:34:test_fail4:Using variable 'undefined' before assignment -used-before-assignment:40:test_fail5:Using variable 'undefined1' before assignment \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/useless_else_on_loop.py b/pymode/libs/pylint/test/functional/useless_else_on_loop.py deleted file mode 100644 index 2fcde8b3..00000000 --- a/pymode/libs/pylint/test/functional/useless_else_on_loop.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Check for else branches on loops with break an return only.""" -from __future__ import print_function -__revision__ = 0 - -def test_return_for(): - """else + return is not accetable.""" - for i in range(10): - if i % 2: - return i - else: # [useless-else-on-loop] - print('math is broken') - -def test_return_while(): - """else + return is not accetable.""" - while True: - return 1 - else: # [useless-else-on-loop] - print('math is broken') - - -while True: - def short_fun(): - """A function with a loop.""" - for _ in range(10): - break -else: # [useless-else-on-loop] - print('or else!') - - -while True: - while False: - break -else: # [useless-else-on-loop] - print('or else!') - -for j in range(10): - pass -else: # [useless-else-on-loop] - print('fat chance') - for j in range(10): - break - -def test_return_for2(): - """no false positive for break in else - - https://bitbucket.org/logilab/pylint/issue/117/useless-else-on-loop-false-positives - """ - for i in range(10): - for i in range(i): - if i % 2: - break - else: - break - else: - print('great math') diff --git a/pymode/libs/pylint/test/functional/useless_else_on_loop.txt b/pymode/libs/pylint/test/functional/useless_else_on_loop.txt deleted file mode 100644 index 93309b6e..00000000 --- a/pymode/libs/pylint/test/functional/useless_else_on_loop.txt +++ /dev/null @@ -1,5 +0,0 @@ -useless-else-on-loop:10:test_return_for:Else clause on loop without a break statement -useless-else-on-loop:17:test_return_while:Else clause on loop without a break statement -useless-else-on-loop:26::Else clause on loop without a break statement -useless-else-on-loop:33::Else clause on loop without a break statement -useless-else-on-loop:38::Else clause on loop without a break statement diff --git a/pymode/libs/pylint/test/functional/using_constant_test.py b/pymode/libs/pylint/test/functional/using_constant_test.py deleted file mode 100644 index dc2d68ac..00000000 --- a/pymode/libs/pylint/test/functional/using_constant_test.py +++ /dev/null @@ -1,140 +0,0 @@ -"""Verify if constant tests are used inside if statements.""" -# pylint: disable=invalid-name, missing-docstring,too-few-public-methods -# pylint: disable=no-init,expression-not-assigned - - -import collections - - -def function(): - yield - - -class Class(object): - - def method(self): - pass - - -instance = Class() - -if collections: # [using-constant-test] - pass - -# GenExpr -if (node for node in range(10)): # [using-constant-test] - pass - -if lambda: None: # [using-constant-test] - pass - -if function: # [using-constant-test] - pass - -if Class: # [using-constant-test] - pass - -if 2: # [using-constant-test] - pass - -if True: # [using-constant-test] - pass - -if '': # [using-constant-test] - pass - -if b'': # [using-constant-test] - pass - -if 2.0: # [using-constant-test] - pass - -if {}: # [using-constant-test] - pass - -if {1, 2, 3}: # [using-constant-test] - pass - -if (1, 2, 3): # [using-constant-test] - pass - -if (): # [using-constant-test] - pass - -# Generator -generator = function() -if generator: # [using-constant-test] - pass - -if 1 if 2 else 3: # [using-constant-test] - pass - -def test_comprehensions(): - [data for data in range(100) if len] # [using-constant-test] - [data for data in range(100) if 1] # [using-constant-test] - (data for data in range(100) if len) # [using-constant-test] - (data for data in range(100) if 1) # [using-constant-test] - {data for data in range(100) if len} # [using-constant-test] - {data: 1 for data in range(100) if len} # [using-constant-test] - - - -# For these, we require to do inference, even though the result can be a -# constant value. For some of them, we could determine that the test -# is constant, such as 2 + 3, but the components of the BinOp -# can be anything else (2 + somefunccall). - -name = 42 -if name: - pass - -# UnboundMethod / Function -if Class.method: - pass - -# BoundMethod -if instance.method: - pass - -if 3 + 4: - pass - -if 3 and 4: - pass - -if not 3: - pass - -if instance.method(): - pass - -# pylint: disable=misplaced-comparison-constant -if 2 < 3: - pass - -if tuple((1, 2, 3)): - pass - -if dict(): - pass - -if tuple(): - pass - -if [1, 2, 3][:1]: - pass - -def test(*args): - if args: - return 42 - -def test_good_comprehension_checks(): - [data for data in range(100)] - [data for data in range(100) if data] - [data for data in range(100) if len(data)] - (data for data in range(100) if data) - (data for data in range(100) if len(data)) - {data for data in range(100) if data} - {data for data in range(100) if len(data)} - {data: 1 for data in range(100) if data} - {data: 1 for data in range(100)} diff --git a/pymode/libs/pylint/test/functional/using_constant_test.txt b/pymode/libs/pylint/test/functional/using_constant_test.txt deleted file mode 100644 index b1c54847..00000000 --- a/pymode/libs/pylint/test/functional/using_constant_test.txt +++ /dev/null @@ -1,22 +0,0 @@ -using-constant-test:21::Using a conditional statement with a constant value -using-constant-test:25::Using a conditional statement with a constant value -using-constant-test:28::Using a conditional statement with a constant value -using-constant-test:31::Using a conditional statement with a constant value -using-constant-test:34::Using a conditional statement with a constant value -using-constant-test:37::Using a conditional statement with a constant value -using-constant-test:40::Using a conditional statement with a constant value -using-constant-test:43::Using a conditional statement with a constant value -using-constant-test:46::Using a conditional statement with a constant value -using-constant-test:49::Using a conditional statement with a constant value -using-constant-test:52::Using a conditional statement with a constant value -using-constant-test:55::Using a conditional statement with a constant value -using-constant-test:58::Using a conditional statement with a constant value -using-constant-test:61::Using a conditional statement with a constant value -using-constant-test:66::Using a conditional statement with a constant value -using-constant-test:69::Using a conditional statement with a constant value -using-constant-test:73:test_comprehensions:Using a conditional statement with a constant value -using-constant-test:74:test_comprehensions:Using a conditional statement with a constant value -using-constant-test:75:test_comprehensions:Using a conditional statement with a constant value -using-constant-test:76:test_comprehensions:Using a conditional statement with a constant value -using-constant-test:77:test_comprehensions:Using a conditional statement with a constant value -using-constant-test:78:test_comprehensions:Using a conditional statement with a constant value diff --git a/pymode/libs/pylint/test/functional/wildcard_import.py b/pymode/libs/pylint/test/functional/wildcard_import.py deleted file mode 100644 index 66ae63d9..00000000 --- a/pymode/libs/pylint/test/functional/wildcard_import.py +++ /dev/null @@ -1,5 +0,0 @@ -# pylint: disable=no-absolute-import,missing-docstring,import-error,unused-wildcard-import -from indirect1 import * # [wildcard-import] -# This is an unresolved import which still generates the wildcard-import -# warning. -from unknown.package import * # [wildcard-import] diff --git a/pymode/libs/pylint/test/functional/wildcard_import.txt b/pymode/libs/pylint/test/functional/wildcard_import.txt deleted file mode 100644 index 643d818b..00000000 --- a/pymode/libs/pylint/test/functional/wildcard_import.txt +++ /dev/null @@ -1,2 +0,0 @@ -wildcard-import:2::Wildcard import indirect1 -wildcard-import:5::Wildcard import unknown.package diff --git a/pymode/libs/pylint/test/functional/with_used_before_assign.py b/pymode/libs/pylint/test/functional/with_used_before_assign.py deleted file mode 100644 index 64a475af..00000000 --- a/pymode/libs/pylint/test/functional/with_used_before_assign.py +++ /dev/null @@ -1,11 +0,0 @@ -''' -Regression test for -https://bitbucket.org/logilab/pylint/issue/128/attributeerror-when-parsing -''' -from __future__ import with_statement - -def do_nothing(): - """ empty """ - with open("") as ctx.obj: # [undefined-variable] - context.do() # [used-before-assignment] - context = None diff --git a/pymode/libs/pylint/test/functional/with_used_before_assign.txt b/pymode/libs/pylint/test/functional/with_used_before_assign.txt deleted file mode 100644 index 783ae732..00000000 --- a/pymode/libs/pylint/test/functional/with_used_before_assign.txt +++ /dev/null @@ -1,2 +0,0 @@ -undefined-variable:9:do_nothing:Undefined variable 'ctx' -used-before-assignment:10:do_nothing:Using variable 'context' before assignment diff --git a/pymode/libs/pylint/test/functional/with_using_generator.py b/pymode/libs/pylint/test/functional/with_using_generator.py deleted file mode 100644 index 25c6b377..00000000 --- a/pymode/libs/pylint/test/functional/with_using_generator.py +++ /dev/null @@ -1,14 +0,0 @@ -""" Testing with statements that use generators. This should not crash. """ - -class Base(object): - """ Base class. """ - val = 0 - - def gen(self): - """ A generator. """ - yield self.val - - def fun(self): - """ With statement using a generator. """ - with self.gen(): # [not-context-manager] - pass diff --git a/pymode/libs/pylint/test/functional/with_using_generator.txt b/pymode/libs/pylint/test/functional/with_using_generator.txt deleted file mode 100644 index 276b05c2..00000000 --- a/pymode/libs/pylint/test/functional/with_using_generator.txt +++ /dev/null @@ -1 +0,0 @@ -not-context-manager:13:Base.fun:Context manager 'generator' doesn't implement __enter__ and __exit__. diff --git a/pymode/libs/pylint/test/functional/wrong_import_order.py b/pymode/libs/pylint/test/functional/wrong_import_order.py deleted file mode 100644 index 0713cac9..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_order.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Checks import order rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -try: - from six.moves import configparser -except ImportError: - import configparser - -import logging - -import six -import os.path # [wrong-import-order] -from astroid import are_exclusive -import sys # [wrong-import-order] -import datetime # [wrong-import-order] -import unused_import -from .package import Class -import totally_missing # [wrong-import-order] -from . import package -import astroid # [wrong-import-order] -from . import package2 -from .package2 import Class2 -from ..package3 import Class3 - - -LOGGER = logging.getLogger(__name__) - - -if LOGGER: - # imports nested skipped - from . import package4 - import pprint - from pprint import PrettyPrinter - - -try: - # imports nested skipped - from . import package4 - import random - from random import division -except ImportError: - LOGGER.info('A useful message here') diff --git a/pymode/libs/pylint/test/functional/wrong_import_order.txt b/pymode/libs/pylint/test/functional/wrong_import_order.txt deleted file mode 100644 index a9a3e898..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_order.txt +++ /dev/null @@ -1,5 +0,0 @@ -wrong-import-order:11::standard import "import os.path" comes before "import six" -wrong-import-order:13::standard import "import sys" comes before "import six" -wrong-import-order:14::standard import "import datetime" comes before "import six" -wrong-import-order:17::external import "import totally_missing" comes before "from .package import Class" -wrong-import-order:19::external import "import astroid" comes before "from .package import Class" diff --git a/pymode/libs/pylint/test/functional/wrong_import_order2.py b/pymode/libs/pylint/test/functional/wrong_import_order2.py deleted file mode 100644 index f8d1e0e6..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_order2.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Checks import order rule in a right case""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module - - -# Standard imports -import os -from sys import argv - -# external imports -import lxml - -from six import moves - -# local_imports -from . import my_package -from .my_package import myClass diff --git a/pymode/libs/pylint/test/functional/wrong_import_position.py b/pymode/libs/pylint/test/functional/wrong_import_position.py deleted file mode 100644 index 0f8a92e8..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Checks import order rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,wrong-import-order,using-constant-test -# pylint: disable=import-error, too-few-public-methods, missing-docstring -import os.path - -if True: - from astroid import are_exclusive -try: - import sys -except ImportError: - class Myclass(object): - """docstring""" - -if sys.version_info[0] == 3: - from collections import OrderedDict -else: - class OrderedDict(object): - """Nothing to see here.""" - def some_func(self): - pass - -import six # [wrong-import-position] - -CONSTANT = True - -import datetime # [wrong-import-position] - -VAR = 0 -for i in range(10): - VAR += i - -import scipy # [wrong-import-position] -import astroid # [wrong-import-position] diff --git a/pymode/libs/pylint/test/functional/wrong_import_position.txt b/pymode/libs/pylint/test/functional/wrong_import_position.txt deleted file mode 100644 index e734ac5e..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position.txt +++ /dev/null @@ -1,4 +0,0 @@ -wrong-import-position:22::Import "import six" should be placed at the top of the module -wrong-import-position:26::Import "import datetime" should be placed at the top of the module -wrong-import-position:32::Import "import scipy" should be placed at the top of the module -wrong-import-position:33::Import "import astroid" should be placed at the top of the module diff --git a/pymode/libs/pylint/test/functional/wrong_import_position10.py b/pymode/libs/pylint/test/functional/wrong_import_position10.py deleted file mode 100644 index 1dbbf4f9..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position10.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,wrong-import-order,using-constant-test -# pylint: disable=import-error, too-few-public-methods,missing-docstring - -import os - -try: - import ast -except ImportError: - def method(items): - """docstring""" - value = 0 - for item in items: - value += item - return value - -import sys diff --git a/pymode/libs/pylint/test/functional/wrong_import_position11.py b/pymode/libs/pylint/test/functional/wrong_import_position11.py deleted file mode 100644 index 37404d06..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position11.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -A = 1 -import os # [wrong-import-position] diff --git a/pymode/libs/pylint/test/functional/wrong_import_position11.txt b/pymode/libs/pylint/test/functional/wrong_import_position11.txt deleted file mode 100644 index 01bb5842..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position11.txt +++ /dev/null @@ -1 +0,0 @@ -wrong-import-position:4::Import "import os" should be placed at the top of the module diff --git a/pymode/libs/pylint/test/functional/wrong_import_position12.py b/pymode/libs/pylint/test/functional/wrong_import_position12.py deleted file mode 100644 index c62bb02b..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position12.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module,pointless-string-statement -"Two string" - -import os # [wrong-import-position] diff --git a/pymode/libs/pylint/test/functional/wrong_import_position12.txt b/pymode/libs/pylint/test/functional/wrong_import_position12.txt deleted file mode 100644 index 6d560822..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position12.txt +++ /dev/null @@ -1 +0,0 @@ -wrong-import-position:5::Import "import os" should be placed at the top of the module diff --git a/pymode/libs/pylint/test/functional/wrong_import_position13.py b/pymode/libs/pylint/test/functional/wrong_import_position13.py deleted file mode 100644 index 7a6a6b72..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position13.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -A = 1 -from sys import x # [wrong-import-position] diff --git a/pymode/libs/pylint/test/functional/wrong_import_position13.txt b/pymode/libs/pylint/test/functional/wrong_import_position13.txt deleted file mode 100644 index f3def190..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position13.txt +++ /dev/null @@ -1 +0,0 @@ -wrong-import-position:4::Import "from sys import x" should be placed at the top of the module diff --git a/pymode/libs/pylint/test/functional/wrong_import_position14.py b/pymode/libs/pylint/test/functional/wrong_import_position14.py deleted file mode 100644 index 85124ace..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position14.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module,undefined-variable -if x: - import os -import y # [wrong-import-position] diff --git a/pymode/libs/pylint/test/functional/wrong_import_position14.txt b/pymode/libs/pylint/test/functional/wrong_import_position14.txt deleted file mode 100644 index 9fcdac50..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position14.txt +++ /dev/null @@ -1 +0,0 @@ -wrong-import-position:5::Import "import y" should be placed at the top of the module diff --git a/pymode/libs/pylint/test/functional/wrong_import_position15.py b/pymode/libs/pylint/test/functional/wrong_import_position15.py deleted file mode 100644 index 58a19b66..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position15.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Checks import position rule with pep-0008""" -# pylint: disable=unused-import - -__author__ = 'some author' -__email__ = 'some.author@some_email' -__copyright__ = 'Some copyright' - - -import sys diff --git a/pymode/libs/pylint/test/functional/wrong_import_position2.py b/pymode/libs/pylint/test/functional/wrong_import_position2.py deleted file mode 100644 index e5eec580..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position2.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Checks import order rule with nested non_import sentence""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -try: - from sys import argv -except ImportError: - pass -else: - pass - -import os diff --git a/pymode/libs/pylint/test/functional/wrong_import_position3.py b/pymode/libs/pylint/test/functional/wrong_import_position3.py deleted file mode 100644 index 1683e6d8..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position3.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -import os diff --git a/pymode/libs/pylint/test/functional/wrong_import_position4.py b/pymode/libs/pylint/test/functional/wrong_import_position4.py deleted file mode 100644 index 596be234..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position4.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module,unused-variable -def method1(): - """Method 1""" - import x diff --git a/pymode/libs/pylint/test/functional/wrong_import_position5.py b/pymode/libs/pylint/test/functional/wrong_import_position5.py deleted file mode 100644 index 4f9b7693..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position5.py +++ /dev/null @@ -1,4 +0,0 @@ -r"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module - -import os diff --git a/pymode/libs/pylint/test/functional/wrong_import_position6.py b/pymode/libs/pylint/test/functional/wrong_import_position6.py deleted file mode 100644 index d48cfaeb..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position6.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module,undefined-variable - -import y - -if x: - import os diff --git a/pymode/libs/pylint/test/functional/wrong_import_position7.py b/pymode/libs/pylint/test/functional/wrong_import_position7.py deleted file mode 100644 index 9b2248f2..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position7.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -try: - import x -except ImportError: - pass -finally: - pass -import y diff --git a/pymode/libs/pylint/test/functional/wrong_import_position8.py b/pymode/libs/pylint/test/functional/wrong_import_position8.py deleted file mode 100644 index 503ce718..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position8.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module,undefined-variable -if x: - import os diff --git a/pymode/libs/pylint/test/functional/wrong_import_position9.py b/pymode/libs/pylint/test/functional/wrong_import_position9.py deleted file mode 100644 index c132b352..00000000 --- a/pymode/libs/pylint/test/functional/wrong_import_position9.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Checks import position rule""" -# pylint: disable=unused-import,relative-import,ungrouped-imports,import-error,no-name-in-module -import y -try: - import x -except ImportError: - pass -else: - pass diff --git a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.py b/pymode/libs/pylint/test/functional/yield_from_iterable_py33.py deleted file mode 100644 index 7803936d..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -Check that `yield from`-statement takes an iterable. -""" -# pylint: disable=missing-docstring - -def to_ten(): - yield from 10 # [not-an-iterable] diff --git a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.rc b/pymode/libs/pylint/test/functional/yield_from_iterable_py33.rc deleted file mode 100644 index 3330edda..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.3 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.txt b/pymode/libs/pylint/test/functional/yield_from_iterable_py33.txt deleted file mode 100644 index 8dec6d2d..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_iterable_py33.txt +++ /dev/null @@ -1 +0,0 @@ -not-an-iterable:7:to_ten:Non-iterable value 10 is used in an iterating context diff --git a/pymode/libs/pylint/test/functional/yield_from_outside_func.py b/pymode/libs/pylint/test/functional/yield_from_outside_func.py deleted file mode 100644 index e2db90c9..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_outside_func.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This is gramatically correct, but it's still a SyntaxError""" -yield from [1, 2] # [yield-outside-function] - -LAMBDA_WITH_YIELD = lambda: (yield from [1, 2]) diff --git a/pymode/libs/pylint/test/functional/yield_from_outside_func.rc b/pymode/libs/pylint/test/functional/yield_from_outside_func.rc deleted file mode 100644 index 28c99bc2..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_outside_func.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.3 diff --git a/pymode/libs/pylint/test/functional/yield_from_outside_func.txt b/pymode/libs/pylint/test/functional/yield_from_outside_func.txt deleted file mode 100644 index fa3a7fc4..00000000 --- a/pymode/libs/pylint/test/functional/yield_from_outside_func.txt +++ /dev/null @@ -1 +0,0 @@ -yield-outside-function:2::Yield outside function diff --git a/pymode/libs/pylint/test/functional/yield_inside_async_function.py b/pymode/libs/pylint/test/functional/yield_inside_async_function.py deleted file mode 100644 index a0d67f8a..00000000 --- a/pymode/libs/pylint/test/functional/yield_inside_async_function.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Test that `yield` or `yield from` can't be used inside an async function.""" -# pylint: disable=missing-docstring, unused-variable - -async def good_coro(): - def _inner(): - yield 42 - yield from [1, 2, 3] - - -async def bad_coro(): - yield 42 # [yield-inside-async-function] - yield from [1, 2, 3] # [yield-inside-async-function] diff --git a/pymode/libs/pylint/test/functional/yield_inside_async_function.rc b/pymode/libs/pylint/test/functional/yield_inside_async_function.rc deleted file mode 100644 index 03004f2c..00000000 --- a/pymode/libs/pylint/test/functional/yield_inside_async_function.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -min_pyver=3.5 \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/yield_inside_async_function.txt b/pymode/libs/pylint/test/functional/yield_inside_async_function.txt deleted file mode 100644 index ae97cae4..00000000 --- a/pymode/libs/pylint/test/functional/yield_inside_async_function.txt +++ /dev/null @@ -1,2 +0,0 @@ -yield-inside-async-function:11:bad_coro:Yield inside async function -yield-inside-async-function:12:bad_coro:Yield inside async function \ No newline at end of file diff --git a/pymode/libs/pylint/test/functional/yield_outside_func.py b/pymode/libs/pylint/test/functional/yield_outside_func.py deleted file mode 100644 index 5824bc0c..00000000 --- a/pymode/libs/pylint/test/functional/yield_outside_func.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This is gramatically correct, but it's still a SyntaxError""" -yield 1 # [yield-outside-function] - -LAMBDA_WITH_YIELD = lambda: (yield) diff --git a/pymode/libs/pylint/test/functional/yield_outside_func.txt b/pymode/libs/pylint/test/functional/yield_outside_func.txt deleted file mode 100644 index fa3a7fc4..00000000 --- a/pymode/libs/pylint/test/functional/yield_outside_func.txt +++ /dev/null @@ -1 +0,0 @@ -yield-outside-function:2::Yield outside function diff --git a/pymode/libs/pylint/test/input/__init__.py b/pymode/libs/pylint/test/input/__init__.py deleted file mode 100644 index 60e92b76..00000000 --- a/pymode/libs/pylint/test/input/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""test""" diff --git a/pymode/libs/pylint/test/input/func_3k_removed_stuff_py_30.py b/pymode/libs/pylint/test/input/func_3k_removed_stuff_py_30.py deleted file mode 100644 index 54ad935b..00000000 --- a/pymode/libs/pylint/test/input/func_3k_removed_stuff_py_30.py +++ /dev/null @@ -1,13 +0,0 @@ -"""test relative import""" -# pylint: disable=no-absolute-import -from __future__ import print_function -import func_w0401 -__revision__ = filter(None, map(str, (1, 2, 3))) - - -def function(): - """something""" - print(func_w0401) - unic = u"unicode" - low = unic.looower - return low diff --git a/pymode/libs/pylint/test/input/func_bad_assigment_to_exception_var.py b/pymode/libs/pylint/test/input/func_bad_assigment_to_exception_var.py deleted file mode 100644 index 93d06445..00000000 --- a/pymode/libs/pylint/test/input/func_bad_assigment_to_exception_var.py +++ /dev/null @@ -1,30 +0,0 @@ -# pylint:disable=C0103, print-statement, no-absolute-import -"""ho ho ho""" -from __future__ import print_function -import sys -__revision__ = 'toto' - -e = 1 -e2 = 'yo' -e3 = None -try: - raise e -except Exception as ex: - print(ex) - _, _, tb = sys.exc_info() - - - -def func(): - """bla bla bla""" - raise e3 - -def reraise(): - """reraise a catched exception instance""" - try: - raise Exception() - except Exception as exc: - print(exc) - raise exc - -raise e3 diff --git a/pymode/libs/pylint/test/input/func_bad_cont_dictcomp_py27.py b/pymode/libs/pylint/test/input/func_bad_cont_dictcomp_py27.py deleted file mode 100644 index a5527107..00000000 --- a/pymode/libs/pylint/test/input/func_bad_cont_dictcomp_py27.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Bad continuations in dictionary comprehensions.""" - -__revision__ = 0 - -# Dictionary comprehensions should not require extra indentation when breaking -# before the 'for', which is not part of the value -C1 = {'key{}'.format(x): 'value{}'.format(x) - for x in range(3)} - -C2 = {'key{}'.format(x): 'value{}'.format(x) for x in - range(3)} - -# Dictionary comprehensions with multiple loops broken in different places -C3 = {x*y: (x, y) for x in range(3) for y in range(3)} - -C4 = {x*y: (x, y) - for x in range(3) for y in range(3)} - -C5 = {x*y: (x, y) for x - in range(3) for y in range(3)} - -C6 = {x*y: (x, y) for x in range(3) - for y in range(3)} - -C7 = {key: - key ** 2 - for key in range(10)} - -C8 = { - key: key ** 2 - for key in range(10)} - -# Misaligned cases for dict comprehensions -C9 = {'key{}'.format(x): 'value{}'.format(x) - for x in range(3)} # [bad-continuation] - -C9 = {'key{}'.format(x): 'value{}'.format(x) - for x in range(3)} # [bad-continuation] diff --git a/pymode/libs/pylint/test/input/func_block_disable_msg.py b/pymode/libs/pylint/test/input/func_block_disable_msg.py deleted file mode 100644 index 5ed690eb..00000000 --- a/pymode/libs/pylint/test/input/func_block_disable_msg.py +++ /dev/null @@ -1,1026 +0,0 @@ -# pylint: disable=C0302,bare-except,print-statement -"""pylint option block-disable""" -from __future__ import print_function - -class Foo(object): - """block-disable test""" - - def __init__(self): - self._test = "42" - - def meth1(self, arg): - """this issues a message""" - print(self) - - def meth2(self, arg): - """and this one not""" - # pylint: disable=W0613 - print(self._test\ - + "foo") - - def meth3(self): - """test one line disabling""" - # no error - print(self.bla) # pylint: disable=E1101 - # error - print(self.blop) - - def meth4(self): - """test re-enabling""" - # pylint: disable=E1101 - # no error - print(self.bla) - print(self.blop) - # pylint: enable=E1101 - # error - print(self.blip) - - def meth5(self): - """test IF sub-block re-enabling""" - # pylint: disable=E1101 - # no error - print(self.bla) - if self.blop: - # pylint: enable=E1101 - # error - print(self.blip) - else: - # no error - print(self.blip) - # no error - print(self.blip) - - def meth6(self): - """test TRY/EXCEPT sub-block re-enabling""" - # pylint: disable=E1101 - # no error - print(self.bla) - try: - # pylint: enable=E1101 - # error - print(self.blip) - except UndefinedName: # pylint: disable=E0602 - # no error - print(self.blip) - # no error - print(self.blip) - - def meth7(self): - """test one line block opening disabling""" - if self.blop: # pylint: disable=E1101 - # error - print(self.blip) - else: - # error - print(self.blip) - # error - print(self.blip) - - - def meth8(self): - """test late disabling""" - # error - print(self.blip) - # pylint: disable=E1101 - # no error - print(self.bla) - print(self.blop) - - def meth9(self): - """test re-enabling right after a block with whitespace""" - eris = 5 - - if eris: # pylint: disable=using-constant-test - print("In block") - - # pylint: disable=E1101 - # no error - print(self.bla) - print(self.blu) - # pylint: enable=E1101 - # error - print(self.blip) - - def meth10(self): - """Test double disable""" - # pylint: disable=E1101 - # no error - print(self.bla) - # pylint: disable=E1101 - print(self.blu) - - -class ClassLevelMessage(object): - """shouldn't display to much attributes/not enough methods messages - """ - # pylint: disable=R0902,R0903 - - def __init__(self): - self.attr1 = 1 - self.attr2 = 1 - self.attr3 = 1 - self.attr4 = 1 - self.attr5 = 1 - self.attr6 = 1 - self.attr7 = 1 - self.attr8 = 1 - self.attr9 = 1 - self.attr0 = 1 - - def too_complex_but_thats_ok(self, attr1, attr2): - """THIS Method has too much branches and returns but i don't care - """ - # pylint: disable=R0912,R0911 - try: - attr3 = attr1+attr2 - except ValueError: - attr3 = None - except: - return 'duh', self - if attr1: - for i in attr1: - if attr2: - return i - else: - return 'duh' - elif attr2: - for i in attr2: - if attr2: - return i - else: - return 'duh' - else: - for i in range(15): - if attr3: - return i - else: - return 'doh' - return None - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -print('hop, too many lines but i don\'t care') diff --git a/pymode/libs/pylint/test/input/func_break_or_return_in_try_finally.py b/pymode/libs/pylint/test/input/func_break_or_return_in_try_finally.py deleted file mode 100644 index f880926b..00000000 --- a/pymode/libs/pylint/test/input/func_break_or_return_in_try_finally.py +++ /dev/null @@ -1,44 +0,0 @@ -'Exeptions may be silently swallowed' -from __future__ import print_function -__revision__ = None -# pylint: disable=using-constant-test -def insidious_break_and_return(): - """I found you !""" - for i in range(0, -5, -1): - my_var = 0 - print(i) - try: - my_var += 1.0/i - if i < -3: - break # :D - else: - return my_var # :D - finally: - if i > -2: - break # :( - else: - return my_var # :( - return None - -def break_and_return(): - """I found you !""" - for i in range(0, -5, -1): - my_var = 0 - if i: - break # :D - try: - my_var += 1.0/i - finally: - for i in range(2): - if True: - break # :D - else: - def strange(): - """why not ?""" - if True: - return my_var # :D - strange() - if i: - break # :D - else: - return # :D diff --git a/pymode/libs/pylint/test/input/func_bug113231.py b/pymode/libs/pylint/test/input/func_bug113231.py deleted file mode 100644 index 70602e21..00000000 --- a/pymode/libs/pylint/test/input/func_bug113231.py +++ /dev/null @@ -1,24 +0,0 @@ -# pylint: disable=E1101 -# pylint: disable=C0103 -# pylint: disable=R0903 -"""test bugfix for #113231 in logging checker -""" -from __future__ import absolute_import -# Muck up the names in an effort to confuse... -import logging as renamed_logging - -__revision__ = '' - -class Logger(object): - """Fake logger""" - pass - -logger = renamed_logging.getLogger(__name__) -fake_logger = Logger() - -# Statements that should be flagged: -renamed_logging.warning('%s, %s' % (4, 5)) -logger.warning('%s' % 5) - -# Statements that should not be flagged: -fake_logger.warn('%s' % 5) diff --git a/pymode/libs/pylint/test/input/func_disable_linebased.py b/pymode/libs/pylint/test/input/func_disable_linebased.py deleted file mode 100644 index b94c2e31..00000000 --- a/pymode/libs/pylint/test/input/func_disable_linebased.py +++ /dev/null @@ -1,14 +0,0 @@ -# This is a very very very very very very very very very very very very very very very very very very very very very long line. -# pylint: disable=line-too-long -"""Make sure enable/disable pragmas work for messages that are applied to lines and not syntax nodes. - -A disable pragma for a message that applies to nodes is applied to the whole -block if it comes before the first statement (excluding the docstring). For -line-based messages, this behavior needs to be altered to really only apply to -the enclosed lines. -""" -# pylint: enable=line-too-long - -from __future__ import print_function - -print('This is a very long line which the linter will warn about, now that line-too-long has been enabled again.') diff --git a/pymode/libs/pylint/test/input/func_dotted_ancestor.py b/pymode/libs/pylint/test/input/func_dotted_ancestor.py deleted file mode 100644 index ff328580..00000000 --- a/pymode/libs/pylint/test/input/func_dotted_ancestor.py +++ /dev/null @@ -1,11 +0,0 @@ -"""bla""" -# pylint: disable=no-absolute-import - -from input import func_w0233 - -__revision__ = 'yo' - -class Aaaa(func_w0233.AAAA): - """test dotted name in ancestors""" - def __init__(self): - func_w0233.AAAA.__init__(self) diff --git a/pymode/libs/pylint/test/input/func_e0012.py b/pymode/libs/pylint/test/input/func_e0012.py deleted file mode 100644 index f4810ee7..00000000 --- a/pymode/libs/pylint/test/input/func_e0012.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint:enable=W04044 -"""check unknown option -""" -__revision__ = 1 diff --git a/pymode/libs/pylint/test/input/func_e0203.py b/pymode/libs/pylint/test/input/func_e0203.py deleted file mode 100644 index d86f4798..00000000 --- a/pymode/libs/pylint/test/input/func_e0203.py +++ /dev/null @@ -1,19 +0,0 @@ -"""check for method without self as first argument -""" -from __future__ import print_function -__revision__ = 0 - - -class Abcd(object): - """dummy class""" - def __init__(self): - pass - - def abcd(yoo): - """another test""" - - abcd = classmethod(abcd) - - def edf(self): - """justo ne more method""" - print('yapudju in', self) diff --git a/pymode/libs/pylint/test/input/func_e0204.py b/pymode/libs/pylint/test/input/func_e0204.py deleted file mode 100644 index 7ab9cff2..00000000 --- a/pymode/libs/pylint/test/input/func_e0204.py +++ /dev/null @@ -1,19 +0,0 @@ -"""check for method without self as first argument -""" -from __future__ import print_function -__revision__ = 0 - - -class Abcd(object): - """dummy class""" - - def __init__(truc): - """method without self""" - print(1) - - def abdc(yoo): - """another test""" - print(yoo) - def edf(self): - """just another method""" - print('yapudju in', self) diff --git a/pymode/libs/pylint/test/input/func_e0601.py b/pymode/libs/pylint/test/input/func_e0601.py deleted file mode 100644 index 122ba019..00000000 --- a/pymode/libs/pylint/test/input/func_e0601.py +++ /dev/null @@ -1,9 +0,0 @@ -"""test local variable used before assignment -""" -from __future__ import print_function -__revision__ = 0 - -def function(): - """dummy""" - print(aaaa) - aaaa = 1 diff --git a/pymode/libs/pylint/test/input/func_e0604.py b/pymode/libs/pylint/test/input/func_e0604.py deleted file mode 100644 index d077f31a..00000000 --- a/pymode/libs/pylint/test/input/func_e0604.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Test for invalid objects in a module's __all__ variable. - -""" -# pylint: disable=R0903,R0201,W0612 - -__revision__ = 0 - -def some_function(): - """Just a function.""" - pass - - -__all__ = [some_function] diff --git a/pymode/libs/pylint/test/input/func_e12xx.py b/pymode/libs/pylint/test/input/func_e12xx.py deleted file mode 100644 index 74984d99..00000000 --- a/pymode/libs/pylint/test/input/func_e12xx.py +++ /dev/null @@ -1,28 +0,0 @@ -# pylint: disable=E1101, no-absolute-import -"""Test checking of log format strings -""" - -import logging - -__revision__ = '' - - -def pprint(): - """Test string format in logging statements. - """ - # These should all emit lint errors: - logging.info(0, '') # 1205 - logging.info('', '') # 1205 - logging.info('%s%', '') # 1201 - logging.info('%s%s', '') # 1206 - logging.info('%s%y', '', '') # 1200 - logging.info('%s%s', '', '', '') # 1205 - - # These should be okay: - logging.info(1) - logging.info(True) - logging.info('') - logging.info('%s%') - logging.info('%s', '') - logging.info('%s%%', '') - logging.info('%s%s', '', '') diff --git a/pymode/libs/pylint/test/input/func_e13xx.py b/pymode/libs/pylint/test/input/func_e13xx.py deleted file mode 100644 index 227311cb..00000000 --- a/pymode/libs/pylint/test/input/func_e13xx.py +++ /dev/null @@ -1,21 +0,0 @@ -"""test string format error -""" -# pylint: disable=print-statement,unsupported-binary-operation -from __future__ import print_function - -PARG_1 = PARG_2 = PARG_3 = 1 - -def pprint(): - """Test string format - """ - print("%s %s" % {'PARG_1': 1, 'PARG_2': 2}) # E1306 - print("%s" % (PARG_1, PARG_2)) # E1305 - print("%(PARG_1)d %d" % {'PARG_1': 1, 'PARG_2': 2}) # E1302 - print("%(PARG_1)d %(PARG_2)d" % {'PARG_1': 1}) # E1304 - print("%(PARG_1)d %(PARG_2)d" % {'PARG_1': 1, 'PARG_2':2, 'PARG_3':3}) #W1301 - print("%(PARG_1)d %(PARG_2)d" % {'PARG_1': 1, 2:3}) # W1300 E1304 - print("%(PARG_1)d %(PARG_2)d" % (2, 3)) # 1303 - print("%(PARG_1)d %(PARG_2)d" % [2, 3]) # 1303 - print("%2z" % PARG_1) - print("strange format %2" % PARG_2) - print("works in 3 %a" % 1) diff --git a/pymode/libs/pylint/test/input/func_excess_escapes.py b/pymode/libs/pylint/test/input/func_excess_escapes.py deleted file mode 100644 index 12ac8622..00000000 --- a/pymode/libs/pylint/test/input/func_excess_escapes.py +++ /dev/null @@ -1,30 +0,0 @@ -# pylint:disable=W0105, W0511, misplaced-comparison-constant -"""Stray backslash escapes may be missing a raw-string prefix.""" - -__revision__ = '$Id$' - -# Bad escape sequences, which probably don't do what you expect. -A = "\[\]\\" -assert '\/' == '\\/' -ESCAPE_BACKSLASH = '\`' - -# Valid escape sequences. -NEWLINE = "\n" -OLD_ESCAPES = '\a\b\f\n\t\r\v' -HEX = '\xad\x0a\x0d' -FALSE_OCTAL = '\o123\o000' # Not octal in Python -OCTAL = '\123\000' -NOT_OCTAL = '\888\999' -NUL = '\0' -UNICODE = u'\u1234' -HIGH_UNICODE = u'\U0000abcd' -QUOTES = '\'\"' -LITERAL_NEWLINE = '\ -' -ESCAPE_UNICODE = "\\\\n" - -# Bad docstring -"""Even in a docstring - -You shouldn't have ambiguous text like: C:\Program Files\alpha -""" diff --git a/pymode/libs/pylint/test/input/func_first_arg.py b/pymode/libs/pylint/test/input/func_first_arg.py deleted file mode 100644 index efff51da..00000000 --- a/pymode/libs/pylint/test/input/func_first_arg.py +++ /dev/null @@ -1,42 +0,0 @@ -# pylint: disable=C0111, W0232 -"""check for methods first arguments -""" - -__revision__ = 0 - - -class Obj(object): - # C0202, classmethod - def __new__(something): - pass - - # C0202, classmethod - def class1(cls): - pass - class1 = classmethod(class1) - - def class2(other): - pass - class2 = classmethod(class2) - - -class Meta(type): - # C0204, metaclass __new__ - def __new__(other, name, bases, dct): - pass - - # C0203, metaclass method - def method1(cls): - pass - - def method2(other): - pass - - # C0205, metaclass classmethod - def class1(mcs): - pass - class1 = classmethod(class1) - - def class2(other): - pass - class2 = classmethod(class2) diff --git a/pymode/libs/pylint/test/input/func_i0011.py b/pymode/libs/pylint/test/input/func_i0011.py deleted file mode 100644 index a4ef215b..00000000 --- a/pymode/libs/pylint/test/input/func_i0011.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint:disable=W0404 -"""check warning on local disabling -""" -__revision__ = 1 diff --git a/pymode/libs/pylint/test/input/func_i0012.py b/pymode/libs/pylint/test/input/func_i0012.py deleted file mode 100644 index 9b6fbe79..00000000 --- a/pymode/libs/pylint/test/input/func_i0012.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint:enable=W0404 -"""check warning on local enabling -""" -__revision__ = 1 diff --git a/pymode/libs/pylint/test/input/func_i0013.py b/pymode/libs/pylint/test/input/func_i0013.py deleted file mode 100644 index 0a3f8336..00000000 --- a/pymode/libs/pylint/test/input/func_i0013.py +++ /dev/null @@ -1,8 +0,0 @@ -# pylint: skip-file -"""disable-all is usable as an inline option""" - -# no warning should be issued -try: - import this -except: - pass diff --git a/pymode/libs/pylint/test/input/func_i0014.py b/pymode/libs/pylint/test/input/func_i0014.py deleted file mode 100644 index 63ff37c9..00000000 --- a/pymode/libs/pylint/test/input/func_i0014.py +++ /dev/null @@ -1,8 +0,0 @@ -# pylint: disable-all -"""disable-all is usable as an inline option""" - -# no warning should be issued -try: - import this -except: - pass diff --git a/pymode/libs/pylint/test/input/func_i0020.py b/pymode/libs/pylint/test/input/func_i0020.py deleted file mode 100644 index 8c0fe9f5..00000000 --- a/pymode/libs/pylint/test/input/func_i0020.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Test for reporting of suppressed messages.""" - -__revision__ = 0 - -def suppressed(): - """A function with an unused variable.""" - # pylint: disable=W0612 - var = 0 diff --git a/pymode/libs/pylint/test/input/func_i0022.py b/pymode/libs/pylint/test/input/func_i0022.py deleted file mode 100644 index f5b308f7..00000000 --- a/pymode/libs/pylint/test/input/func_i0022.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Deprecated suppression style.""" - -__revision__ = None - -a = 1 # pylint: disable=invalid-name -b = 1 # pylint: disable-msg=invalid-name - -# pylint: disable=invalid-name -c = 1 -# pylint: enable=invalid-name - -# pylint: disable-msg=invalid-name -d = 1 -# pylint: enable-msg=invalid-name - -# pylint: disable-msg=C0103 -e = 1 -# pylint: enable-msg=C0103 - -# pylint: disable=C0103 -f = 1 -# pylint: enable=C0103 diff --git a/pymode/libs/pylint/test/input/func_init_vars.py b/pymode/libs/pylint/test/input/func_init_vars.py deleted file mode 100644 index 473d1ccb..00000000 --- a/pymode/libs/pylint/test/input/func_init_vars.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Checks that class variables are seen as inherited ! -""" -# pylint: disable=too-few-public-methods -from __future__ import print_function - - -class MyClass(object): - """Inherits from nothing - """ - - def __init__(self): - self.var = {} - - def met(self): - """Checks that base_var is seen as defined outside '__init__' - """ - self.var[1] = 'one' - self.base_var = 'one' - print(self.base_var, self.var) - - def met2(self): - """dummy method""" - print(self) -class MySubClass(MyClass): - """Inherits from MyClass - """ - class_attr = 1 - - def __init__(self): - MyClass.__init__(self) - self.var2 = 2 - print(self.__doc__) - print(self.__dict__) - print(self.__class__) - - def met2(self): - """Checks that var is seen as defined outside '__init__' - """ - self.var[1] = 'one' - self.var2 += 1 - print(self.class_attr) - -if __name__ == '__main__': - OBJ = MyClass() - OBJ.met() diff --git a/pymode/libs/pylint/test/input/func_kwoa_py30.py b/pymode/libs/pylint/test/input/func_kwoa_py30.py deleted file mode 100644 index a5fe07c3..00000000 --- a/pymode/libs/pylint/test/input/func_kwoa_py30.py +++ /dev/null @@ -1,12 +0,0 @@ -# pylint: disable=C0102 -'''A little testscript for PEP 3102 and pylint''' -def function(*, foo): - '''A function for testing''' - print(foo) - -function(foo=1) - -foo = 1 -function(foo) - -function(1) diff --git a/pymode/libs/pylint/test/input/func_logging_not_lazy_with_logger.py b/pymode/libs/pylint/test/input/func_logging_not_lazy_with_logger.py deleted file mode 100644 index 973a5c79..00000000 --- a/pymode/libs/pylint/test/input/func_logging_not_lazy_with_logger.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Logging warnings using a logger class.""" -from __future__ import absolute_import -import logging - -__revision__ = '' - -LOG = logging.getLogger("domain") -LOG.debug("%s" % "junk") -LOG.log(logging.DEBUG, "%s" % "junk") -LOG2 = LOG.debug -LOG2("%s" % "junk") - -logging.getLogger("domain").debug("%s" % "junk") diff --git a/pymode/libs/pylint/test/input/func_loopvar_in_dict_comp_py27.py b/pymode/libs/pylint/test/input/func_loopvar_in_dict_comp_py27.py deleted file mode 100644 index 312eee72..00000000 --- a/pymode/libs/pylint/test/input/func_loopvar_in_dict_comp_py27.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Tests for loopvar-in-closure.""" - -__revision__ = 0 - - -def bad_case(): - """Loop variable from dict comprehension.""" - return {x: lambda: x for x in range(10)} diff --git a/pymode/libs/pylint/test/input/func_module___dict__.py b/pymode/libs/pylint/test/input/func_module___dict__.py deleted file mode 100644 index 54514224..00000000 --- a/pymode/libs/pylint/test/input/func_module___dict__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""http://www.logilab.org/ticket/6949.""" -from __future__ import print_function -__revision__ = None - -print(__dict__ is not None) - -__dict__ = {} - -print(__dict__ is not None) diff --git a/pymode/libs/pylint/test/input/func_nameerror_on_string_substitution.py b/pymode/libs/pylint/test/input/func_nameerror_on_string_substitution.py deleted file mode 100644 index be7b5c82..00000000 --- a/pymode/libs/pylint/test/input/func_nameerror_on_string_substitution.py +++ /dev/null @@ -1,8 +0,0 @@ -"""pylint doesn't see the NameError in this module""" - -__revision__ = None - -MSG = "hello %s" % MSG - -MSG2 = ("hello %s" % - MSG2) diff --git a/pymode/libs/pylint/test/input/func_no_dummy_redefined.py b/pymode/libs/pylint/test/input/func_no_dummy_redefined.py deleted file mode 100644 index a5c0aea4..00000000 --- a/pymode/libs/pylint/test/input/func_no_dummy_redefined.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Make sure warnings about redefinitions do not trigger for dummy variables.""" -from __future__ import print_function - - -_, INTERESTING = 'a=b'.split('=') - -value = 10 - - -def clobbering(): - """Clobbers a dummy name from the outer scope.""" - value = 9 - for _ in range(7): - print(value) diff --git a/pymode/libs/pylint/test/input/func_noerror___init___return_from_inner_function.py b/pymode/libs/pylint/test/input/func_noerror___init___return_from_inner_function.py deleted file mode 100644 index 44f5fd0b..00000000 --- a/pymode/libs/pylint/test/input/func_noerror___init___return_from_inner_function.py +++ /dev/null @@ -1,12 +0,0 @@ -# pylint: disable=R0903 -"""#10075""" - -__revision__ = 1 - -class Aaa(object): - """docstring""" - def __init__(self): - def inner_function(arg): - """inner docstring""" - return arg + 4 - self.func = inner_function diff --git a/pymode/libs/pylint/test/input/func_noerror_access_attr_before_def_false_positive.py b/pymode/libs/pylint/test/input/func_noerror_access_attr_before_def_false_positive.py deleted file mode 100644 index 7bc554b8..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_access_attr_before_def_false_positive.py +++ /dev/null @@ -1,98 +0,0 @@ -#pylint: disable=C0103,R0904,R0903,W0201,old-style-class,no-absolute-import -""" -This module demonstrates a possible problem of pyLint with calling __init__ s -from inherited classes. -Initializations done there are not considered, which results in Error E0203 for -self.cookedq. -""" - -from __future__ import print_function - -import telnetlib - -class SeeTelnet(telnetlib.Telnet): - """ - Extension of telnetlib. - """ - - def __init__(self, host=None, port=0): - """ - Constructor. - When called without arguments, create an unconnected instance. - With a hostname argument, it connects the instance; a port - number is optional. - Parameter: - - host: IP address of the host - - port: Port number - """ - telnetlib.Telnet.__init__(self, host, port) - - def readUntilArray(self, matches, _=None): - """ - Read until a given string is encountered or until timeout. - ... - """ - self.process_rawq() - maxLength = 0 - for match in matches: - if len(match) > maxLength: - maxLength = len(match) - -class Base(object): - """bla bla""" - dougloup_papa = None - - def __init__(self): - self._var = False - -class Derived(Base): - """derived blabla""" - dougloup_moi = None - def Work(self): - """do something""" - # E0203 - Access to member '_var' before its definition - if self._var: - print("True") - else: - print("False") - self._var = True - - # E0203 - Access to member 'dougloup_papa' before its definition - if self.dougloup_papa: - print('dougloup !') - self.dougloup_papa = True - # E0203 - Access to member 'dougloup_moi' before its definition - if self.dougloup_moi: - print('dougloup !') - self.dougloup_moi = True - - -class QoSALConnection(object): - """blabla""" - - _the_instance = None - - def __new__(cls): - if cls._the_instance is None: - cls._the_instance = object.__new__(cls) - return cls._the_instance - - def __init__(self): - pass - -class DefinedOutsideInit(object): - """use_attr is seen as the method defining attr because its in - first position - """ - def __init__(self): - self.reset() - - def use_attr(self): - """use and set members""" - if self.attr: - print('hop') - self.attr = 10 - - def reset(self): - """reset members""" - self.attr = 4 diff --git a/pymode/libs/pylint/test/input/func_noerror_base_init_vars.py b/pymode/libs/pylint/test/input/func_noerror_base_init_vars.py deleted file mode 100644 index 3c25fc91..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_base_init_vars.py +++ /dev/null @@ -1,35 +0,0 @@ -# pylint:disable=R0201, print-statement, too-few-public-methods -"""Checks that class variables are seen as inherited ! -""" -__revision__ = '' - -class BaseClass(object): - """A simple base class - """ - - def __init__(self): - self.base_var = {} - - def met(self): - """yo""" - def meeting(self, with_): - """ye""" - return with_ -class MyClass(BaseClass): - """Inherits from BaseClass - """ - - def __init__(self): - BaseClass.__init__(self) - self.var = {} - - def met(self): - """Checks that base_var is not seen as defined outsite '__init__' - """ - self.var[1] = 'one' - self.base_var[1] = 'one' - return self.base_var, self.var - -if __name__ == '__main__': - OBJ = MyClass() - OBJ.met() diff --git a/pymode/libs/pylint/test/input/func_noerror_builtin_module_test.py b/pymode/libs/pylint/test/input/func_noerror_builtin_module_test.py deleted file mode 100644 index 9b1e7ce8..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_builtin_module_test.py +++ /dev/null @@ -1,11 +0,0 @@ -"""test import from a builtin module""" - -from __future__ import absolute_import -from math import log10 - -__revision__ = None - - -def log10_2(): - """bla bla bla""" - return log10(2) diff --git a/pymode/libs/pylint/test/input/func_noerror_class_attributes.py b/pymode/libs/pylint/test/input/func_noerror_class_attributes.py deleted file mode 100644 index 75fb435e..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_class_attributes.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Test that valid class attribute doesn't trigger errors""" -__revision__ = 'sponge bob' - -class Clazz(object): - "dummy class" - - def __init__(self): - self.topic = 5 - self._data = 45 - - def change_type(self, new_class): - """Change type""" - self.__class__ = new_class - - def do_nothing(self): - "I do nothing useful" - return self.topic + 56 diff --git a/pymode/libs/pylint/test/input/func_noerror_classes_meth_could_be_a_function.py b/pymode/libs/pylint/test/input/func_noerror_classes_meth_could_be_a_function.py deleted file mode 100644 index e9e4cf07..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_classes_meth_could_be_a_function.py +++ /dev/null @@ -1,33 +0,0 @@ -# pylint: disable=C0111,R0903,W0232 -""" -#2479 - -R0201 (formely W0212), Method could be a function shouldn't be emitted in case -like factory method pattern -""" -__revision__ = 1 - -class XAsub(object): - pass -class XBsub(XAsub): - pass -class XCsub(XAsub): - pass - -class Aimpl(object): - # disable "method could be a function" on classes which are not overriding - # the factory method because in that case the usage of polymorphism is not - # detected - # pylint: disable=R0201 - def makex(self): - return XAsub() - -class Bimpl(Aimpl): - - def makex(self): - return XBsub() - -class Cimpl(Aimpl): - - def makex(self): - return XCsub() diff --git a/pymode/libs/pylint/test/input/func_noerror_classes_protected_member_access.py b/pymode/libs/pylint/test/input/func_noerror_classes_protected_member_access.py deleted file mode 100644 index 2ffd9d11..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_classes_protected_member_access.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -#3123: W0212 false positive on static method -""" -__revision__ = 1 - -# pylint: disable=no-classmethod-decorator, no-staticmethod-decorator -class A3123(object): - """oypuee""" - _protected = 1 - def __init__(self): - pass - - - def cmeth(cls, val): - """set protected member""" - cls._protected = +val - - cmeth = classmethod(cmeth) - - def smeth(val): - """set protected member""" - A3123._protected += val - - smeth = staticmethod(smeth) - - prop = property(lambda self: self._protected) diff --git a/pymode/libs/pylint/test/input/func_noerror_crash_127416.py b/pymode/libs/pylint/test/input/func_noerror_crash_127416.py deleted file mode 100644 index 6c30a792..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_crash_127416.py +++ /dev/null @@ -1,20 +0,0 @@ -# pylint: disable=C0111,R0201 -""" -FUNCTIONALITY -""" - -class Example(object): - """ - @summary: Demonstrates pylint error caused by method expecting tuple - but called method does not return tuple - """ - - def method_expects_tuple(self, obj): - meth, args = self.method_doesnot_return_tuple(obj) - result = meth(args) - return result - - def method_doesnot_return_tuple(self, obj): - # we want to lock what we have in the inventory, not what is to have - # in the future - return {'success': obj} diff --git a/pymode/libs/pylint/test/input/func_noerror_decorator_scope.py b/pymode/libs/pylint/test/input/func_noerror_decorator_scope.py deleted file mode 100644 index 81f929cd..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_decorator_scope.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- pylint: disable=W0232,R0903 -"""Test that decorators sees the class namespace - just like -function default values does but function body doesn't. - -https://www.logilab.net/elo/ticket/3711 - bug finding decorator arguments -https://www.logilab.net/elo/ticket/5626 - name resolution bug inside classes -""" - -from __future__ import print_function - -class Test(object): - """test class""" - ident = lambda x: x - - @ident(ident) - def method(self, val=ident(7), func=ident): - """hop""" - print(self) - return func(val) diff --git a/pymode/libs/pylint/test/input/func_noerror_e1101_9588_base_attr_aug_assign.py b/pymode/libs/pylint/test/input/func_noerror_e1101_9588_base_attr_aug_assign.py deleted file mode 100644 index 5bd96250..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_e1101_9588_base_attr_aug_assign.py +++ /dev/null @@ -1,38 +0,0 @@ -# pylint: disable=R0903 -""" -False positive case of E1101: - -The error is triggered when the attribute set in the base class is -modified with augmented assignment in a derived class. - -http://www.logilab.org/ticket/9588 -""" -__revision__ = 0 - -class BaseClass(object): - "The base class" - def __init__(self): - "Set an attribute." - self.e1101 = 1 - -class FalsePositiveClass(BaseClass): - "The first derived class which triggers the false positive" - def __init__(self): - "Augmented assignment triggers E1101." - BaseClass.__init__(self) - self.e1101 += 1 - - def countup(self): - "Consequently this also triggers E1101." - self.e1101 += 1 - -class NegativeClass(BaseClass): - "The second derived class, which does not trigger the error E1101" - def __init__(self): - "Ordinary assignment is OK." - BaseClass.__init__(self) - self.e1101 = self.e1101 + 1 - - def countup(self): - "No problem." - self.e1101 += 1 diff --git a/pymode/libs/pylint/test/input/func_noerror_encoding.py b/pymode/libs/pylint/test/input/func_noerror_encoding.py deleted file mode 100644 index 15e60c0f..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_encoding.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: ISO-8859-1 -*- -""" check correct encoding declaration -""" - -__revision__ = '' diff --git a/pymode/libs/pylint/test/input/func_noerror_except_pass.py b/pymode/libs/pylint/test/input/func_noerror_except_pass.py deleted file mode 100644 index 5bb8011b..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_except_pass.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -#3205: W0704 (except doesn't do anything) false positive if some statements -follow a "pass" -""" -from __future__ import print_function -__revision__ = None - -try: - A = 2 -except ValueError: - pass # pylint: disable=W0107 - print(A) diff --git a/pymode/libs/pylint/test/input/func_noerror_exception.py b/pymode/libs/pylint/test/input/func_noerror_exception.py deleted file mode 100644 index 1c3d8b56..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_exception.py +++ /dev/null @@ -1,7 +0,0 @@ -""" module doc """ -__revision__ = '' - -class MyException(Exception): - """a custom exception with its *own* __init__ !!""" - def __init__(self, msg): - Exception.__init__(self, msg) diff --git a/pymode/libs/pylint/test/input/func_noerror_external_classmethod_crash.py b/pymode/libs/pylint/test/input/func_noerror_external_classmethod_crash.py deleted file mode 100644 index 318f01c3..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_external_classmethod_crash.py +++ /dev/null @@ -1,21 +0,0 @@ -# pylint: disable=W0232,R0903,W0613 -"""tagging a function as a class method cause a crash when checking for -signature overriding -""" - -def fetch_config(mainattr=None): - """return a class method""" - - def fetch_order(cls, attr, var): - """a class method""" - if attr == mainattr: - return var - return None - fetch_order = classmethod(fetch_order) - return fetch_order - -class Aaa(object): - """hop""" - fetch_order = fetch_config('A') - -__revision__ = None diff --git a/pymode/libs/pylint/test/input/func_noerror_function_as_method.py b/pymode/libs/pylint/test/input/func_noerror_function_as_method.py deleted file mode 100644 index 0fbb59cd..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_function_as_method.py +++ /dev/null @@ -1,18 +0,0 @@ -# pylint: disable=R0903 -'''Test that a function is considered a method when looked up through a class. -''' -from __future__ import print_function - -class Clazz(object): - 'test class' - - def __init__(self, value): - self.value = value - -def func(arg1, arg2): - 'function that will be used as a method' - return arg1.value + arg2 - -Clazz.method = func - -print(Clazz(1).method(2)) diff --git a/pymode/libs/pylint/test/input/func_noerror_genexp_in_class_scope.py b/pymode/libs/pylint/test/input/func_noerror_genexp_in_class_scope.py deleted file mode 100644 index 5631026a..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_genexp_in_class_scope.py +++ /dev/null @@ -1,9 +0,0 @@ -# pylint: disable=W0232,R0903 -"""class scope must be handled correctly in genexps""" - -__revision__ = '' - -class MyClass(object): - """ds""" - var1 = [] - var2 = list(value*2 for value in var1) diff --git a/pymode/libs/pylint/test/input/func_noerror_inner_classes.py b/pymode/libs/pylint/test/input/func_noerror_inner_classes.py deleted file mode 100644 index 84fb43d8..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_inner_classes.py +++ /dev/null @@ -1,33 +0,0 @@ -# pylint: disable=R0903 -"""Backend Base Classes for the schwelm user DB""" - -__revision__ = "alpha" - -class Aaa(object): - """docstring""" - def __init__(self): - self.__setattr__('a', 'b') - - - def one_public(self): - """docstring""" - pass - - def another_public(self): - """docstring""" - pass - -class Bbb(Aaa): - """docstring""" - pass - -class Ccc(Aaa): - """docstring""" - - class Ddd(Aaa): - """docstring""" - pass - - class Eee(Ddd): - """docstring""" - pass diff --git a/pymode/libs/pylint/test/input/func_noerror_lambda_use_before_assign.py b/pymode/libs/pylint/test/input/func_noerror_lambda_use_before_assign.py deleted file mode 100644 index af2775ca..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_lambda_use_before_assign.py +++ /dev/null @@ -1,8 +0,0 @@ -"""https://www.logilab.net/elo/ticket/18862""" -from __future__ import print_function -__revision__ = 1 -def function(): - """hop""" - ggg = lambda: xxx - xxx = 1 - print(ggg()) diff --git a/pymode/libs/pylint/test/input/func_noerror_long_utf8_line.py b/pymode/libs/pylint/test/input/func_noerror_long_utf8_line.py deleted file mode 100644 index 815759fe..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_long_utf8_line.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -"""this utf-8 doc string have some non ASCII caracters like 'é', or '¢»ß'""" -### check also comments with some more non ASCII caracters like 'é' or '¢»ß' - -__revision__ = 1100 - -ASCII = "----------------------------------------------------------------------" -UTF_8 = "--------------------------------------------------------------------éé" diff --git a/pymode/libs/pylint/test/input/func_noerror_mcs_attr_access.py b/pymode/libs/pylint/test/input/func_noerror_mcs_attr_access.py deleted file mode 100644 index 7d9652ea..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_mcs_attr_access.py +++ /dev/null @@ -1,20 +0,0 @@ -# pylint: disable=R0903, metaclass-assignment -"""test attribute access on metaclass""" - - -from __future__ import print_function - -class Meta(type): - """the meta class""" - def __init__(cls, name, bases, dictionary): - super(Meta, cls).__init__(name, bases, dictionary) - print(cls, cls._meta_args) - delattr(cls, '_meta_args') - -class Test(object): - """metaclassed class""" - __metaclass__ = Meta - _meta_args = ('foo', 'bar') - - def __init__(self): - print('__init__', self) diff --git a/pymode/libs/pylint/test/input/func_noerror_new_style_class_py_30.py b/pymode/libs/pylint/test/input/func_noerror_new_style_class_py_30.py deleted file mode 100644 index a33ae19f..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_new_style_class_py_30.py +++ /dev/null @@ -1,45 +0,0 @@ -"""check builtin data descriptors such as mode and name attributes -on a file are correctly handled - -bug notified by Pierre Rouleau on 2005-04-24 -""" -from __future__ import print_function -__revision__ = None - -class File(file): # pylint: disable=file-builtin - """ Testing new-style class inheritance from file""" - - # - def __init__(self, name, mode="r", buffering=-1, verbose=False): - """Constructor""" - - self.was_modified = False - self.verbose = verbose - super(File, self).__init__(name, mode, buffering) - if self.verbose: - print("File %s is opened. The mode is: %s" % (self.name, - self.mode)) - - # - def write(self, a_string): - """ Write a string to the file.""" - - super(File, self).write(a_string) - self.was_modified = True - - # - def writelines(self, sequence): - """ Write a sequence of strings to the file. """ - - super(File, self).writelines(sequence) - self.was_modified = True - - # - def close(self): - """Close the file.""" - - if self.verbose: - print("Closing file %s" % self.name) - - super(File, self).close() - self.was_modified = False diff --git a/pymode/libs/pylint/test/input/func_noerror_no_warning_docstring.py b/pymode/libs/pylint/test/input/func_noerror_no_warning_docstring.py deleted file mode 100644 index bd30d7eb..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_no_warning_docstring.py +++ /dev/null @@ -1,42 +0,0 @@ -''' Test for inheritence ''' -from __future__ import print_function -__revision__ = 1 -# pylint: disable=too-few-public-methods, using-constant-test -class AAAA(object): - ''' class AAAA ''' - - def __init__(self): - pass - - def method1(self): - ''' method 1 ''' - print(self) - - def method2(self): - ''' method 2 ''' - print(self) - -class BBBB(AAAA): - ''' class BBBB ''' - - def __init__(self): - AAAA.__init__(self) - - # should ignore docstring calling from class AAAA - def method1(self): - AAAA.method1(self) - -class CCCC(BBBB): - ''' class CCCC ''' - - def __init__(self): - BBBB.__init__(self) - - # should ignore docstring since CCCC is inherited from BBBB which is - # inherited from AAAA containing method2 - if __revision__: - def method2(self): - AAAA.method2(self) - else: - def method2(self): - AAAA.method1(self) diff --git a/pymode/libs/pylint/test/input/func_noerror_nonregr.py b/pymode/libs/pylint/test/input/func_noerror_nonregr.py deleted file mode 100644 index c4c8c382..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_nonregr.py +++ /dev/null @@ -1,13 +0,0 @@ -# pylint: disable=W0106 -"""snippets of codes which have at some point made pylint crash""" - -__revision__ = 1 - -def function1(cbarg=lambda: None): - """ - File "/usr/lib/python2.4/site-packages/logilab/astroid/scoped_nodes.py", line -391, in mularg_class # this method doesn't exist anymore - i = self.args.args.index(argname) -ValueError: list.index(x): x not in list - """ - cbarg().x diff --git a/pymode/libs/pylint/test/input/func_noerror_object_as_class_attribute.py b/pymode/libs/pylint/test/input/func_noerror_object_as_class_attribute.py deleted file mode 100644 index a134f1d8..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_object_as_class_attribute.py +++ /dev/null @@ -1,18 +0,0 @@ -# pylint: disable=R0903 -"""Test case for the problem described below : - - A class extends 'object' - - This class defines its own __init__() - * pylint will therefore check that baseclasses' init() - are called - - If this class defines an 'object' attribute, then pylint - will use this new definition when trying to retrieve - object.__init__() -""" - -__revision__ = None - -class Statement(object): - """ ... """ - def __init__(self): - pass - object = None diff --git a/pymode/libs/pylint/test/input/func_noerror_overloaded_operator.py b/pymode/libs/pylint/test/input/func_noerror_overloaded_operator.py deleted file mode 100644 index 2e0e8a11..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_overloaded_operator.py +++ /dev/null @@ -1,21 +0,0 @@ -# pylint: disable=C0111,R0903 -"""#3291""" -from __future__ import print_function - -class Myarray(object): - def __init__(self, array): - self.array = array - - def __mul__(self, val): - return Myarray(val) - - def astype(self): - return "ASTYPE", self - -def randint(maximum): - if maximum is not None: - return Myarray([1, 2, 3]) * 2 - else: - return int(5) - -print(randint(1).astype()) # we don't wan't an error for astype access diff --git a/pymode/libs/pylint/test/input/func_noerror_overriden_method_varargs.py b/pymode/libs/pylint/test/input/func_noerror_overriden_method_varargs.py deleted file mode 100644 index afe30863..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_overriden_method_varargs.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=R0201,R0903 -"""docstring""" - -__revision__ = 1 - -class SuperClass(object): - """docstring""" - def impl(self, arg1, arg2): - """docstring""" - return arg1 + arg2 - -class MyClass(SuperClass): - """docstring""" - def impl(self, *args, **kwargs): - """docstring""" - # ...do stuff here... - super(MyClass, self).impl(*args, **kwargs) - -# ...do stuff here... diff --git a/pymode/libs/pylint/test/input/func_noerror_property_affectation_py26.py b/pymode/libs/pylint/test/input/func_noerror_property_affectation_py26.py deleted file mode 100644 index d91f455d..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_property_affectation_py26.py +++ /dev/null @@ -1,24 +0,0 @@ -# pylint: disable=R0903 -""" -Simple test case for an annoying behavior in pylint. -""" - -__revision__ = 'pouet' - -class Test(object): - """Smallest test case for reported issue.""" - - def __init__(self): - self._thing = None - - @property - def myattr(self): - """Getter for myattr""" - return self._thing - - @myattr.setter - def myattr(self, value): - """Setter for myattr.""" - self._thing = value - -Test().myattr = 'grou' diff --git a/pymode/libs/pylint/test/input/func_noerror_raise_return_self.py b/pymode/libs/pylint/test/input/func_noerror_raise_return_self.py deleted file mode 100644 index 486b504d..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_raise_return_self.py +++ /dev/null @@ -1,14 +0,0 @@ -"""see ticket #5672""" -# pylint: disable=R0903,W0232,C0111,C0103,using-constant-test - -__revision__ = 0 - -class MultiException(Exception): - def __init__(self): - Exception.__init__(self) - def return_self(self): - return self - -# raise Exception -if 1: - raise MultiException().return_self() diff --git a/pymode/libs/pylint/test/input/func_noerror_static_method.py b/pymode/libs/pylint/test/input/func_noerror_static_method.py deleted file mode 100644 index 7457f457..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_static_method.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Checks if static / class methods works fine in Pylint -""" -from __future__ import print_function -__revision__ = '' - -#pylint: disable=no-classmethod-decorator, no-staticmethod-decorator -class MyClass(object): - """doc - """ - def __init__(self): - pass - - def static_met(var1, var2): - """This is a static method - """ - print(var1, var2) - - def class_met(cls, var1): - """This is a class method - """ - print(cls, var1) - - static_met = staticmethod(static_met) - class_met = classmethod(class_met) - -if __name__ == '__main__': - MyClass.static_met("var1", "var2") - MyClass.class_met("var1") diff --git a/pymode/libs/pylint/test/input/func_noerror_yield_assign_py25.py b/pymode/libs/pylint/test/input/func_noerror_yield_assign_py25.py deleted file mode 100644 index f40d8d96..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_yield_assign_py25.py +++ /dev/null @@ -1,21 +0,0 @@ -"""http://www.logilab.org/ticket/8771""" - -from __future__ import print_function - -def generator(): - """yield as assignment""" - yield 45 - xxxx = yield 123 - print(xxxx) - -def generator_fp1(seq): - """W0631 false positive""" - for val in seq: - pass - for val in seq: - yield val - -def generator_fp2(): - """E0601 false positive""" - xxxx = 12 - yield xxxx diff --git a/pymode/libs/pylint/test/input/func_noerror_yield_return_mix.py b/pymode/libs/pylint/test/input/func_noerror_yield_return_mix.py deleted file mode 100644 index bd786333..00000000 --- a/pymode/libs/pylint/test/input/func_noerror_yield_return_mix.py +++ /dev/null @@ -1,7 +0,0 @@ -""" module doc """ -__revision__ = None - -def somegen(): - """this kind of mix is OK""" - yield 1 - return diff --git a/pymode/libs/pylint/test/input/func_nonregr___file___global.py b/pymode/libs/pylint/test/input/func_nonregr___file___global.py deleted file mode 100644 index 910033c4..00000000 --- a/pymode/libs/pylint/test/input/func_nonregr___file___global.py +++ /dev/null @@ -1,8 +0,0 @@ -"""test no crash on __file__ global""" - -def func(): - """override __file__""" - global __file__ - __file__ = 'hop' - -__revision__ = 'pouet' diff --git a/pymode/libs/pylint/test/input/func_return_yield_mix_py_33.py b/pymode/libs/pylint/test/input/func_return_yield_mix_py_33.py deleted file mode 100644 index 473c9daa..00000000 --- a/pymode/libs/pylint/test/input/func_return_yield_mix_py_33.py +++ /dev/null @@ -1,15 +0,0 @@ -"""pylint should detect yield and return mix inside genrators""" -# pylint: disable=using-constant-test -def somegen(): - """this is a bad generator""" - if True: - return 1 - else: - yield 2 - -def moregen(): - """this is another bad generator""" - if True: - yield 1 - else: - return 2 diff --git a/pymode/libs/pylint/test/input/func_too_many_returns_yields.py b/pymode/libs/pylint/test/input/func_too_many_returns_yields.py deleted file mode 100644 index c61bd7d5..00000000 --- a/pymode/libs/pylint/test/input/func_too_many_returns_yields.py +++ /dev/null @@ -1,42 +0,0 @@ -"""test""" - -__revision__ = None - -def too_many_returns(arg): - """is this real ?""" - if arg == 1: - return 1 - elif arg == 2: - return 2 - elif arg == 3: - return 3 - elif arg == 4: - return 4 - elif arg == 5: - return 5 - elif arg == 6: - return 6 - elif arg == 7: - return 7 - elif arg == 8: - return 8 - elif arg == 9: - return 9 - elif arg == 10: - return 10 - return None - -def many_yield(text): - """not a problem""" - if text: - yield " line 1: %s\n" % text - yield " line 2\n" - yield " line 3\n" - yield " line 4\n" - yield " line 5\n" - else: - yield " line 6\n" - yield " line 7\n" - yield " line 8\n" - yield " line 9\n" - yield " line 10\n" diff --git a/pymode/libs/pylint/test/input/func_typecheck_callfunc_assigment.py b/pymode/libs/pylint/test/input/func_typecheck_callfunc_assigment.py deleted file mode 100644 index 927dcb58..00000000 --- a/pymode/libs/pylint/test/input/func_typecheck_callfunc_assigment.py +++ /dev/null @@ -1,63 +0,0 @@ - -"""check assignment to function call where the function doesn't return - - 'E1111': ('Assigning to function call which doesn\'t return', - 'Used when an assignment is done on a function call but the \ - infered function doesn\'t return anything.'), - 'W1111': ('Assigning to function call which only returns None', - 'Used when an assignment is done on a function call but the \ - infered function returns nothing but None.'), - -""" -from __future__ import generators, print_function - -#pylint: disable=redefined-variable-type - -def func_no_return(): - """function without return""" - print('dougloup') - -A = func_no_return() - - -def func_return_none(): - """function returning none""" - print('dougloup') - return None - -A = func_return_none() - - -def func_implicit_return_none(): - """Function returning None from bare return statement.""" - return - -A = func_implicit_return_none() - - -def func_return_none_and_smth(): - """function returning none and something else""" - print('dougloup') - if 2 or 3: - return None - return 3 - -A = func_return_none_and_smth() - -def generator(): - """no problemo""" - yield 2 - -A = generator() - -class Abstract(object): - """bla bla""" - - def abstract_method(self): - """use to return something in concrete implementation""" - raise NotImplementedError - - def use_abstract(self): - """should not issue E1111""" - var = self.abstract_method() - print(var) diff --git a/pymode/libs/pylint/test/input/func_unused_import_py30.py b/pymode/libs/pylint/test/input/func_unused_import_py30.py deleted file mode 100644 index 91a9e9ac..00000000 --- a/pymode/libs/pylint/test/input/func_unused_import_py30.py +++ /dev/null @@ -1,20 +0,0 @@ -"""check unused import for metaclasses -""" -# pylint: disable=too-few-public-methods,wrong-import-position,ungrouped-imports -__revision__ = 1 -import abc -import sys -from abc import ABCMeta -from abc import ABCMeta as SomethingElse - -class Meta(metaclass=abc.ABCMeta): - """ Test """ - def __init__(self): - self.data = sys.executable - self.test = abc - -class Meta2(metaclass=ABCMeta): - """ Test """ - -class Meta3(metaclass=SomethingElse): - """ test """ diff --git a/pymode/libs/pylint/test/input/func_unused_overridden_argument.py b/pymode/libs/pylint/test/input/func_unused_overridden_argument.py deleted file mode 100644 index a0e61986..00000000 --- a/pymode/libs/pylint/test/input/func_unused_overridden_argument.py +++ /dev/null @@ -1,31 +0,0 @@ -# pylint: disable=R0903, print-statement -"""for Sub.inherited, only the warning for "aay" is desired. -The warnings for "aab" and "aac" are most likely false positives though, -because there could be another subclass that overrides the same method and does -use the arguments (eg Sub2) -""" - -__revision__ = 'thx to Maarten ter Huurne' - -class Base(object): - "parent" - def inherited(self, aaa, aab, aac): - "abstract method" - raise NotImplementedError - -class Sub(Base): - "child 1" - def inherited(self, aaa, aab, aac): - "overridden method, though don't use every argument" - return aaa - - def newmethod(self, aax, aay): - "another method, warning for aay desired" - return self, aax - -class Sub2(Base): - "child 1" - - def inherited(self, aaa, aab, aac): - "overridden method, use every argument" - return aaa + aab + aac diff --git a/pymode/libs/pylint/test/input/func_use_for_or_listcomp_var.py b/pymode/libs/pylint/test/input/func_use_for_or_listcomp_var.py deleted file mode 100644 index 517d0a27..00000000 --- a/pymode/libs/pylint/test/input/func_use_for_or_listcomp_var.py +++ /dev/null @@ -1,27 +0,0 @@ -"""test a warning is triggered when using for a lists comprehension variable""" -from __future__ import print_function -__revision__ = 'yo' - -TEST_LC = [C for C in __revision__ if C.isalpha()] -print(C) # WARN -C = 4 -print(C) # this one shouldn't trigger any warning - -B = [B for B in __revision__ if B.isalpha()] -print(B) # nor this one - -for var1, var2 in TEST_LC: - var1 = var2 + 4 -print(var1) # WARN - -for note in __revision__: - note.something() -for line in __revision__: - for note in line: - A = note.anotherthing() - - -for x in []: - pass -for x in range(3): - print((lambda: x)()) # OK diff --git a/pymode/libs/pylint/test/input/func_variables_unused_name_from_wilcard_import.py b/pymode/libs/pylint/test/input/func_variables_unused_name_from_wilcard_import.py deleted file mode 100644 index bb92155c..00000000 --- a/pymode/libs/pylint/test/input/func_variables_unused_name_from_wilcard_import.py +++ /dev/null @@ -1,3 +0,0 @@ -"""check unused import from a wildcard import""" -# pylint: disable=no-absolute-import -from input.func_w0611 import * diff --git a/pymode/libs/pylint/test/input/func_w0122_py_30.py b/pymode/libs/pylint/test/input/func_w0122_py_30.py deleted file mode 100644 index 6b866913..00000000 --- a/pymode/libs/pylint/test/input/func_w0122_py_30.py +++ /dev/null @@ -1,12 +0,0 @@ -"""test global statement""" - -__revision__ = 0 - -exec 'a = __revision__' -exec 'a = 1' in {} - -exec 'a = 1' in globals() - -def func(): - """exec in local scope""" - exec 'b = 1' diff --git a/pymode/libs/pylint/test/input/func_w0205.py b/pymode/libs/pylint/test/input/func_w0205.py deleted file mode 100644 index 896be6c8..00000000 --- a/pymode/libs/pylint/test/input/func_w0205.py +++ /dev/null @@ -1,24 +0,0 @@ -"""check different signatures""" -from __future__ import print_function -__revision__ = 0 -# pylint: disable=too-few-public-methods -class Abcd(object): - '''dummy''' - def __init__(self): - self.aarg = False - def abcd(self, aaa=1, bbbb=None): - """hehehe""" - print(self, aaa, bbbb) - def args(self): - """gaarrrggll""" - self.aarg = True - -class Cdef(Abcd): - """dummy""" - def __init__(self, aaa): - Abcd.__init__(self) - self.aaa = aaa - - def abcd(self, aaa, bbbb=None): - """hehehe""" - print(self, aaa, bbbb) diff --git a/pymode/libs/pylint/test/input/func_w0233.py b/pymode/libs/pylint/test/input/func_w0233.py deleted file mode 100644 index efaaeae3..00000000 --- a/pymode/libs/pylint/test/input/func_w0233.py +++ /dev/null @@ -1,50 +0,0 @@ -# pylint: disable=R0903,W0212,W0403,W0406,no-absolute-import,wrong-import-order -"""test for call to __init__ from a non ancestor class -""" -from __future__ import print_function -from . import func_w0233 -import nonexistant -__revision__ = '$Id: func_w0233.py,v 1.2 2004-09-29 08:35:13 syt Exp $' - -class AAAA(object): - """ancestor 1""" - - def __init__(self): - print('init', self) - BBBBMixin.__init__(self) - -class BBBBMixin(object): - """ancestor 2""" - - def __init__(self): - print('init', self) - -class CCC(BBBBMixin, func_w0233.AAAA, func_w0233.BBBB, nonexistant.AClass): - """mix different things, some inferable some not""" - def __init__(self): - BBBBMixin.__init__(self) - func_w0233.AAAA.__init__(self) - func_w0233.BBBB.__init__(self) - nonexistant.AClass.__init__(self) - -class DDDD(AAAA): - """call superclass constructor in disjunct branches""" - def __init__(self, value): - if value: - AAAA.__init__(self) - else: - AAAA.__init__(self) - -class Super(dict): - """ test late binding super() call """ - def __init__(self): - base = super() - base.__init__() - -class Super2(dict): - """ Using the same idiom as Super, but without calling - the __init__ method. - """ - def __init__(self): - base = super() - base.__woohoo__() diff --git a/pymode/libs/pylint/test/input/func_w0332_py_30.py b/pymode/libs/pylint/test/input/func_w0332_py_30.py deleted file mode 100644 index 6a38e8c0..00000000 --- a/pymode/libs/pylint/test/input/func_w0332_py_30.py +++ /dev/null @@ -1,4 +0,0 @@ -"""check use of l as long int marker -""" -# pylint: disable=long-suffix -__revision__ = 1l diff --git a/pymode/libs/pylint/test/input/func_w0401.py b/pymode/libs/pylint/test/input/func_w0401.py deleted file mode 100644 index 12227bc9..00000000 --- a/pymode/libs/pylint/test/input/func_w0401.py +++ /dev/null @@ -1,9 +0,0 @@ -"""test cyclic import -""" -# pylint: disable=no-absolute-import -from __future__ import print_function - -from . import w0401_cycle - -if w0401_cycle: - print(w0401_cycle) diff --git a/pymode/libs/pylint/test/input/func_w0401_package/__init__.py b/pymode/libs/pylint/test/input/func_w0401_package/__init__.py deleted file mode 100644 index dedef660..00000000 --- a/pymode/libs/pylint/test/input/func_w0401_package/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -"""Our big package.""" -__revision__ = None diff --git a/pymode/libs/pylint/test/input/func_w0401_package/all_the_things.py b/pymode/libs/pylint/test/input/func_w0401_package/all_the_things.py deleted file mode 100644 index b8bd47b9..00000000 --- a/pymode/libs/pylint/test/input/func_w0401_package/all_the_things.py +++ /dev/null @@ -1,9 +0,0 @@ -"""All the things!""" -# pylint: disable=no-absolute-import -from .thing1 import THING1 -from .thing2 import THING2 -from .thing2 import THING1_PLUS_THING2 -__revision__ = None - -_ = (THING1, THING2, THING1_PLUS_THING2) -del _ diff --git a/pymode/libs/pylint/test/input/func_w0401_package/thing1.py b/pymode/libs/pylint/test/input/func_w0401_package/thing1.py deleted file mode 100644 index 34972a7d..00000000 --- a/pymode/libs/pylint/test/input/func_w0401_package/thing1.py +++ /dev/null @@ -1,3 +0,0 @@ -"""The first thing.""" -__revision__ = None -THING1 = "I am thing1" diff --git a/pymode/libs/pylint/test/input/func_w0401_package/thing2.py b/pymode/libs/pylint/test/input/func_w0401_package/thing2.py deleted file mode 100644 index 66d33167..00000000 --- a/pymode/libs/pylint/test/input/func_w0401_package/thing2.py +++ /dev/null @@ -1,7 +0,0 @@ -"""The second thing.""" -# pylint: disable=no-absolute-import -from .all_the_things import THING1 -__revision__ = None - -THING2 = "I am thing2" -THING1_PLUS_THING2 = "%s, plus %s" % (THING1, THING2) diff --git a/pymode/libs/pylint/test/input/func_w0404.py b/pymode/libs/pylint/test/input/func_w0404.py deleted file mode 100644 index 2ce7d651..00000000 --- a/pymode/libs/pylint/test/input/func_w0404.py +++ /dev/null @@ -1,27 +0,0 @@ -"""Unittests for W0404 (reimport)""" -from __future__ import absolute_import, print_function - -import sys - -import xml.etree.ElementTree -from xml.etree import ElementTree - -from email import encoders -import email.encoders - -import sys #pylint: disable=ungrouped-imports,wrong-import-order -__revision__ = 0 - -def no_reimport(): - """docstring""" - import os - print(os) - - -def reimport(): - """This function contains a reimport.""" - import sys - del sys - - -del sys, ElementTree, xml.etree.ElementTree, encoders, email.encoders diff --git a/pymode/libs/pylint/test/input/func_w0405.py b/pymode/libs/pylint/test/input/func_w0405.py deleted file mode 100644 index 50a069d7..00000000 --- a/pymode/libs/pylint/test/input/func_w0405.py +++ /dev/null @@ -1,31 +0,0 @@ -"""check reimport -""" -from __future__ import absolute_import, print_function - -# pylint: disable=using-constant-test,ungrouped-imports,wrong-import-position -import os -from os.path import join, exists -import os -import re as _re - -__revision__ = 0 -_re.match('yo', '.*') - -if __revision__: - print(os) - from os.path import exists - print(join, exists) - -def func(yooo): - """reimport in different scope""" - import os as ass - ass.remove(yooo) - import re - re.compile('.*') - -if 1: # pylint: disable=using-constant-test - import sys - print(sys.modules) -else: - print('bla') - import sys diff --git a/pymode/libs/pylint/test/input/func_w0406.py b/pymode/libs/pylint/test/input/func_w0406.py deleted file mode 100644 index ceb12b5f..00000000 --- a/pymode/libs/pylint/test/input/func_w0406.py +++ /dev/null @@ -1,10 +0,0 @@ -"""test module importing itself""" -# pylint: disable=no-absolute-import,using-constant-test -from __future__ import print_function -from . import func_w0406 - -__revision__ = 0 - - -if __revision__: - print(func_w0406) diff --git a/pymode/libs/pylint/test/input/func_w0611.py b/pymode/libs/pylint/test/input/func_w0611.py deleted file mode 100644 index c129aba5..00000000 --- a/pymode/libs/pylint/test/input/func_w0611.py +++ /dev/null @@ -1,25 +0,0 @@ -"""check unused import -""" -# pylint: disable=no-absolute-import - -from __future__ import print_function - -import os -import sys - -class NonRegr(object): - """???""" - def __init__(self): - print('initialized') - - def sys(self): - """should not get sys from there...""" - print(self, sys) - - def dummy(self, truc): - """yo""" - return self, truc - - def blop(self): - """yo""" - print(self, 'blip') diff --git a/pymode/libs/pylint/test/input/func_w0612.py b/pymode/libs/pylint/test/input/func_w0612.py deleted file mode 100644 index 3d873bbe..00000000 --- a/pymode/libs/pylint/test/input/func_w0612.py +++ /dev/null @@ -1,37 +0,0 @@ -"""test unused variable -""" -# pylint: disable=invalid-name, redefined-outer-name, no-absolute-import -from __future__ import print_function -PATH = OS = collections = deque = None - -def function(matches): - """"yo""" - aaaa = 1 - index = -1 - for match in matches: - index += 1 - print(match) - -def visit_if(self, node): - """increments the branches counter""" - branches = 1 - # don't double count If nodes coming from some 'elif' - if node.orelse and len(node.orelse) > 1: - branches += 1 - self.inc_branch(branches) - self.stmts += branches - -def test_global(): - """ Test various assignments of global - variables through imports. - """ - global PATH, OS, collections, deque - from os import path as PATH - import os as OS - import collections - from collections import deque - # make sure that these triggers unused-variable - from sys import platform - from sys import version as VERSION - import this - import re as RE diff --git a/pymode/libs/pylint/test/input/func_w0613.py b/pymode/libs/pylint/test/input/func_w0613.py deleted file mode 100644 index ea1ab29b..00000000 --- a/pymode/libs/pylint/test/input/func_w0613.py +++ /dev/null @@ -1,42 +0,0 @@ -# pylint: disable=R0903, print-statement -"""test unused argument -""" -from __future__ import print_function - - -def function(arg=1): - """ignore arg""" - - -class AAAA(object): - """dummy class""" - - def method(self, arg): - """dummy method""" - print(self) - def __init__(self, *unused_args, **unused_kwargs): - pass - - @classmethod - def selected(cls, *args, **kwargs): - """called by the registry when the vobject has been selected. - """ - return cls - - def using_inner_function(self, etype, size=1): - """return a fake result set for a particular entity type""" - rset = AAAA([('A',)]*size, '%s X' % etype, - description=[(etype,)]*size) - def inner(row, col=0, etype=etype, req=self, rset=rset): - """inner using all its argument""" - # pylint: disable = E1103 - return req.vreg.etype_class(etype)(req, rset, row, col) - # pylint: disable = W0201 - rset.get_entity = inner - -class BBBB(object): - """dummy class""" - - def __init__(self, arg): - """Constructor with an extra parameter. Should raise a warning""" - self.spam = 1 diff --git a/pymode/libs/pylint/test/input/func_w0623_py30.py b/pymode/libs/pylint/test/input/func_w0623_py30.py deleted file mode 100644 index 163256b1..00000000 --- a/pymode/libs/pylint/test/input/func_w0623_py30.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Test for W0623, overwriting names in exception handlers.""" - -__revision__ = '' - -class MyError(Exception): - """Special exception class.""" - pass - - -def some_function(): - """A function.""" - - try: - {}["a"] - except KeyError as some_function: # W0623 - pass diff --git a/pymode/libs/pylint/test/input/func_w0623_py_30.py b/pymode/libs/pylint/test/input/func_w0623_py_30.py deleted file mode 100644 index cc8d36cf..00000000 --- a/pymode/libs/pylint/test/input/func_w0623_py_30.py +++ /dev/null @@ -1,67 +0,0 @@ -"""Test for W0623, overwriting names in exception handlers.""" -# pylint: disable=broad-except,bare-except,print-statement,no-absolute-import,duplicate-except -import exceptions - -__revision__ = '' - -class MyError(Exception): - """Special exception class.""" - pass - - -def some_function(): - """A function.""" - exc = None - - try: - {}["a"] - except KeyError, exceptions.RuntimeError: # W0623 - pass - except KeyError, OSError: # W0623 - pass - except KeyError, MyError: # W0623 - pass - except KeyError, exc: # this is fine - print exc - except KeyError, exc1: # this is fine - print exc1 - except KeyError, FOO: # C0103 - print FOO - - try: - pass - except KeyError, exc1: # this is fine - print exc1 - -class MyOtherError(Exception): - """Special exception class.""" - pass - - -exc3 = None - -try: - pass -except KeyError, exceptions.RuntimeError: # W0623 - pass -except KeyError, exceptions.RuntimeError.args: # W0623 - pass -except KeyError, OSError: # W0623 - pass -except KeyError, MyOtherError: # W0623 - pass -except KeyError, exc3: # this is fine - print exc3 -except KeyError, exc4: # this is fine - print exc4 -except KeyError, OOPS: # C0103 - print OOPS - -try: - pass -except KeyError, exc4: # this is fine - print exc4 -except IOError, exc5: # this is fine - print exc5 -except MyOtherError, exc5: # this is fine - print exc5 diff --git a/pymode/libs/pylint/test/input/func_w0631.py b/pymode/libs/pylint/test/input/func_w0631.py deleted file mode 100644 index 0390ac77..00000000 --- a/pymode/libs/pylint/test/input/func_w0631.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Check possible undefined loopvar -""" -from __future__ import print_function -__revision__ = 0 - -def do_stuff(some_random_list): - """This is not right.""" - for var in some_random_list: - pass - print(var) - - -def do_else(some_random_list): - """This is not right.""" - for var in some_random_list: - if var == 42: - break - else: - var = 84 - print(var) diff --git a/pymode/libs/pylint/test/input/func_w0703.py b/pymode/libs/pylint/test/input/func_w0703.py deleted file mode 100644 index fb633fdf..00000000 --- a/pymode/libs/pylint/test/input/func_w0703.py +++ /dev/null @@ -1,9 +0,0 @@ -"""check empty except statement -""" -from __future__ import print_function -__revision__ = 0 - -try: - __revision__ += 1 -except Exception: - print('error') diff --git a/pymode/libs/pylint/test/input/func_w0705.py b/pymode/libs/pylint/test/input/func_w0705.py deleted file mode 100644 index ba2bab32..00000000 --- a/pymode/libs/pylint/test/input/func_w0705.py +++ /dev/null @@ -1,46 +0,0 @@ -"""test misordered except -""" - -__revision__ = 1 - -try: - __revision__ += 1 -except Exception: - __revision__ = 0 -except TypeError: - __revision__ = 0 - -try: - __revision__ += 1 -except LookupError: - __revision__ = 0 -except IndexError: - __revision__ = 0 - -try: - __revision__ += 1 -except (LookupError, NameError): - __revision__ = 0 -except (IndexError, UnboundLocalError): - __revision__ = 0 - -try: - __revision__ += 1 -except: - pass -except Exception: - pass - -try: - __revision__ += 1 -except TypeError: - __revision__ = 0 -except: - __revision__ = 0 - -try: - __revision__ += 1 -except Exception: - pass -except: - pass diff --git a/pymode/libs/pylint/test/input/func_w0801.py b/pymode/libs/pylint/test/input/func_w0801.py deleted file mode 100644 index cd386ff5..00000000 --- a/pymode/libs/pylint/test/input/func_w0801.py +++ /dev/null @@ -1,11 +0,0 @@ -"""test code similarities -by defaut docstring are not considered -""" -__revision__ = 'id' -A = 2 -B = 3 -C = A + B -# need more than X lines to trigger the message -C *= 2 -A -= B -# all this should be detected diff --git a/pymode/libs/pylint/test/input/func_with_without_as_py25.py b/pymode/libs/pylint/test/input/func_with_without_as_py25.py deleted file mode 100644 index 7ecf574a..00000000 --- a/pymode/libs/pylint/test/input/func_with_without_as_py25.py +++ /dev/null @@ -1,12 +0,0 @@ -'''This is a little non regression test on a with statement -without 'as'. -''' -from __future__ import with_statement, print_function -__revision__ = 32321313 - -def do_nothing(arg): - 'ho foo' - print(arg) - with open('x'): - base.baz - base = 7 diff --git a/pymode/libs/pylint/test/input/ignore_except_pass_by_default.py b/pymode/libs/pylint/test/input/ignore_except_pass_by_default.py deleted file mode 100644 index 444e540d..00000000 --- a/pymode/libs/pylint/test/input/ignore_except_pass_by_default.py +++ /dev/null @@ -1,6 +0,0 @@ -"""#5575: by default no W0704 warning on bare pass in except""" - -try: - __exception__ = 0 -except ValueError: - pass diff --git a/pymode/libs/pylint/test/input/noext b/pymode/libs/pylint/test/input/noext deleted file mode 100644 index 8aeda06d..00000000 --- a/pymode/libs/pylint/test/input/noext +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env python -"""a python file without .py extension""" - -__revision__ = None diff --git a/pymode/libs/pylint/test/input/similar1 b/pymode/libs/pylint/test/input/similar1 deleted file mode 100644 index 2b04ee2f..00000000 --- a/pymode/libs/pylint/test/input/similar1 +++ /dev/null @@ -1,22 +0,0 @@ -import one -from two import two -three -four -five -six # comments optionally ignored -seven -eight -nine -''' ten -eleven -twelve ''' -thirteen -fourteen -fifteen - - - - -sixteen -seventeen -eighteen diff --git a/pymode/libs/pylint/test/input/similar2 b/pymode/libs/pylint/test/input/similar2 deleted file mode 100644 index 77f5f1ed..00000000 --- a/pymode/libs/pylint/test/input/similar2 +++ /dev/null @@ -1,22 +0,0 @@ -import one -from two import two -three -four -five -six -seven -eight -nine -''' ten -ELEVEN -twelve ''' -thirteen -fourteen -FIFTEEN - - - - -sixteen -seventeen -eighteen diff --git a/pymode/libs/pylint/test/input/syntax_error.py b/pymode/libs/pylint/test/input/syntax_error.py deleted file mode 100644 index 6c1e7a74..00000000 --- a/pymode/libs/pylint/test/input/syntax_error.py +++ /dev/null @@ -1,2 +0,0 @@ -if False: -print('hop') diff --git a/pymode/libs/pylint/test/input/w0401_cycle.py b/pymode/libs/pylint/test/input/w0401_cycle.py deleted file mode 100644 index ddb42557..00000000 --- a/pymode/libs/pylint/test/input/w0401_cycle.py +++ /dev/null @@ -1,9 +0,0 @@ -"""w0401 dependency -""" -# pylint: disable=print-statement, no-absolute-import -from __future__ import print_function - -from . import func_w0401 - -if func_w0401: - print(input) diff --git a/pymode/libs/pylint/test/input/w0801_same.py b/pymode/libs/pylint/test/input/w0801_same.py deleted file mode 100644 index cd386ff5..00000000 --- a/pymode/libs/pylint/test/input/w0801_same.py +++ /dev/null @@ -1,11 +0,0 @@ -"""test code similarities -by defaut docstring are not considered -""" -__revision__ = 'id' -A = 2 -B = 3 -C = A + B -# need more than X lines to trigger the message -C *= 2 -A -= B -# all this should be detected diff --git a/pymode/libs/pylint/test/messages/builtin_module.txt b/pymode/libs/pylint/test/messages/builtin_module.txt deleted file mode 100644 index 2616c0e2..00000000 --- a/pymode/libs/pylint/test/messages/builtin_module.txt +++ /dev/null @@ -1 +0,0 @@ -F: 1: ignored builtin module sys diff --git a/pymode/libs/pylint/test/messages/func_3k_removed_stuff_py_30.txt b/pymode/libs/pylint/test/messages/func_3k_removed_stuff_py_30.txt deleted file mode 100644 index 9920f1b6..00000000 --- a/pymode/libs/pylint/test/messages/func_3k_removed_stuff_py_30.txt +++ /dev/null @@ -1,2 +0,0 @@ -E: 12:function: Instance of 'unicode' has no 'looower' member -W: 4: Relative import 'func_w0401', should be 'input.func_w0401' diff --git a/pymode/libs/pylint/test/messages/func_bad_assigment_to_exception_var.txt b/pymode/libs/pylint/test/messages/func_bad_assigment_to_exception_var.txt deleted file mode 100644 index 119fbe2d..00000000 --- a/pymode/libs/pylint/test/messages/func_bad_assigment_to_exception_var.txt +++ /dev/null @@ -1,5 +0,0 @@ -E: 11: Raising int while only classes or instances are allowed -E: 20:func: Raising NoneType while only classes or instances are allowed -E: 30: Raising NoneType while only classes or instances are allowed -W: 12: Catching too general exception Exception - diff --git a/pymode/libs/pylint/test/messages/func_bad_cont_dictcomp_py27.txt b/pymode/libs/pylint/test/messages/func_bad_cont_dictcomp_py27.txt deleted file mode 100644 index 51bde771..00000000 --- a/pymode/libs/pylint/test/messages/func_bad_cont_dictcomp_py27.txt +++ /dev/null @@ -1,6 +0,0 @@ -C: 35: Wrong continued indentation (add 2 spaces). - for x in range(3)} # [bad-continuation] - ^ | -C: 38: Wrong continued indentation (remove 4 spaces). - for x in range(3)} # [bad-continuation] - | ^ diff --git a/pymode/libs/pylint/test/messages/func_block_disable_msg.txt b/pymode/libs/pylint/test/messages/func_block_disable_msg.txt deleted file mode 100644 index 1a16fbed..00000000 --- a/pymode/libs/pylint/test/messages/func_block_disable_msg.txt +++ /dev/null @@ -1,13 +0,0 @@ -E: 26:Foo.meth3: Instance of 'Foo' has no 'blop' member -E: 36:Foo.meth4: Instance of 'Foo' has no 'blip' member -E: 46:Foo.meth5: Instance of 'Foo' has no 'blip' member -E: 61:Foo.meth6: Instance of 'Foo' has no 'blip' member -E: 72:Foo.meth7: Instance of 'Foo' has no 'blip' member -E: 75:Foo.meth7: Instance of 'Foo' has no 'blip' member -E: 77:Foo.meth7: Instance of 'Foo' has no 'blip' member -E: 83:Foo.meth8: Instance of 'Foo' has no 'blip' member -E:102:Foo.meth9: Instance of 'Foo' has no 'blip' member -W: 11:Foo.meth1: Unused argument 'arg' -W:144:ClassLevelMessage.too_complex_but_thats_ok: Else clause on loop without a break statement -W:150:ClassLevelMessage.too_complex_but_thats_ok: Else clause on loop without a break statement -W:156:ClassLevelMessage.too_complex_but_thats_ok: Else clause on loop without a break statement diff --git a/pymode/libs/pylint/test/messages/func_break_or_return_in_try_finally.txt b/pymode/libs/pylint/test/messages/func_break_or_return_in_try_finally.txt deleted file mode 100644 index 04f27fe7..00000000 --- a/pymode/libs/pylint/test/messages/func_break_or_return_in_try_finally.txt +++ /dev/null @@ -1,3 +0,0 @@ -W: 18:insidious_break_and_return: break statement in finally block may swallow exception -W: 20:insidious_break_and_return: return statement in finally block may swallow exception -W: 39:break_and_return.strange: Cell variable my_var defined in loop diff --git a/pymode/libs/pylint/test/messages/func_bug113231.txt b/pymode/libs/pylint/test/messages/func_bug113231.txt deleted file mode 100644 index a9d3f7ef..00000000 --- a/pymode/libs/pylint/test/messages/func_bug113231.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 20: Specify string format arguments as logging function parameters -W: 21: Specify string format arguments as logging function parameters diff --git a/pymode/libs/pylint/test/messages/func_disable_linebased.txt b/pymode/libs/pylint/test/messages/func_disable_linebased.txt deleted file mode 100644 index 06e391d4..00000000 --- a/pymode/libs/pylint/test/messages/func_disable_linebased.txt +++ /dev/null @@ -1,2 +0,0 @@ -C: 1: Line too long (127/100) -C: 14: Line too long (114/100) diff --git a/pymode/libs/pylint/test/messages/func_disable_linebased_py30.txt b/pymode/libs/pylint/test/messages/func_disable_linebased_py30.txt deleted file mode 100644 index 06e391d4..00000000 --- a/pymode/libs/pylint/test/messages/func_disable_linebased_py30.txt +++ /dev/null @@ -1,2 +0,0 @@ -C: 1: Line too long (127/100) -C: 14: Line too long (114/100) diff --git a/pymode/libs/pylint/test/messages/func_dotted_ancestor.txt b/pymode/libs/pylint/test/messages/func_dotted_ancestor.txt deleted file mode 100644 index 6e2c6fa5..00000000 --- a/pymode/libs/pylint/test/messages/func_dotted_ancestor.txt +++ /dev/null @@ -1 +0,0 @@ -R: 8:Aaaa: Too few public methods (0/2) diff --git a/pymode/libs/pylint/test/messages/func_e0012.txt b/pymode/libs/pylint/test/messages/func_e0012.txt deleted file mode 100644 index a6d1b698..00000000 --- a/pymode/libs/pylint/test/messages/func_e0012.txt +++ /dev/null @@ -1 +0,0 @@ -E: 1: Bad option value 'W04044' diff --git a/pymode/libs/pylint/test/messages/func_e0203.txt b/pymode/libs/pylint/test/messages/func_e0203.txt deleted file mode 100644 index 96769def..00000000 --- a/pymode/libs/pylint/test/messages/func_e0203.txt +++ /dev/null @@ -1,2 +0,0 @@ -C: 12:Abcd.abcd: Class method abcd should have 'cls' as first argument -R: 15:Abcd: Consider using a decorator instead of calling classmethod diff --git a/pymode/libs/pylint/test/messages/func_e0204.txt b/pymode/libs/pylint/test/messages/func_e0204.txt deleted file mode 100644 index 8e05efea..00000000 --- a/pymode/libs/pylint/test/messages/func_e0204.txt +++ /dev/null @@ -1,3 +0,0 @@ -E: 10:Abcd.__init__: Method should have "self" as first argument -E: 14:Abcd.abdc: Method should have "self" as first argument - diff --git a/pymode/libs/pylint/test/messages/func_e0601.txt b/pymode/libs/pylint/test/messages/func_e0601.txt deleted file mode 100644 index 321c7316..00000000 --- a/pymode/libs/pylint/test/messages/func_e0601.txt +++ /dev/null @@ -1 +0,0 @@ -E: 8:function: Using variable 'aaaa' before assignment diff --git a/pymode/libs/pylint/test/messages/func_e0604.txt b/pymode/libs/pylint/test/messages/func_e0604.txt deleted file mode 100644 index e2326331..00000000 --- a/pymode/libs/pylint/test/messages/func_e0604.txt +++ /dev/null @@ -1 +0,0 @@ -E: 13: Invalid object 'some_function' in __all__, must contain only strings diff --git a/pymode/libs/pylint/test/messages/func_e12xx.txt b/pymode/libs/pylint/test/messages/func_e12xx.txt deleted file mode 100644 index 92640d25..00000000 --- a/pymode/libs/pylint/test/messages/func_e12xx.txt +++ /dev/null @@ -1,6 +0,0 @@ -E: 14:pprint: Too many arguments for logging format string -E: 15:pprint: Too many arguments for logging format string -E: 16:pprint: Logging format string ends in middle of conversion specifier -E: 17:pprint: Not enough arguments for logging format string -E: 18:pprint: Unsupported logging format character 'y' (0x79) at index 3 -E: 19:pprint: Too many arguments for logging format string diff --git a/pymode/libs/pylint/test/messages/func_e13xx.txt b/pymode/libs/pylint/test/messages/func_e13xx.txt deleted file mode 100644 index f2d0d364..00000000 --- a/pymode/libs/pylint/test/messages/func_e13xx.txt +++ /dev/null @@ -1,13 +0,0 @@ -E: 11:pprint: Not enough arguments for format string -E: 12:pprint: Too many arguments for format string -E: 13:pprint: Mixing named and unnamed conversion specifiers in format string -E: 14:pprint: Missing key 'PARG_2' in format string dictionary -E: 16:pprint: Missing key 'PARG_2' in format string dictionary -E: 17:pprint: Expected mapping for format string, not Tuple -E: 18:pprint: Expected mapping for format string, not List -E: 19:pprint: Unsupported format character 'z' (0x7a) at index 2 -E: 20:pprint: Format string ends in middle of conversion specifier -E: 21:pprint: Unsupported format character 'a' (0x61) at index 12 -W: 15:pprint: Unused key 'PARG_3' in format string dictionary -W: 16:pprint: Format string dictionary key should be a string, not 2 - diff --git a/pymode/libs/pylint/test/messages/func_e13xx_py30.txt b/pymode/libs/pylint/test/messages/func_e13xx_py30.txt deleted file mode 100644 index 7ac9fb18..00000000 --- a/pymode/libs/pylint/test/messages/func_e13xx_py30.txt +++ /dev/null @@ -1,11 +0,0 @@ -E: 11:pprint: Not enough arguments for format string -E: 12:pprint: Too many arguments for format string -E: 13:pprint: Mixing named and unnamed conversion specifiers in format string -E: 14:pprint: Missing key 'PARG_2' in format string dictionary -E: 16:pprint: Missing key 'PARG_2' in format string dictionary -E: 17:pprint: Expected mapping for format string, not Tuple -E: 18:pprint: Expected mapping for format string, not List -E: 19:pprint: Unsupported format character 'z' (0x7a) at index 2 -E: 20:pprint: Format string ends in middle of conversion specifier -W: 15:pprint: Unused key 'PARG_3' in format string dictionary -W: 16:pprint: Format string dictionary key should be a string, not 2 \ No newline at end of file diff --git a/pymode/libs/pylint/test/messages/func_excess_escapes.txt b/pymode/libs/pylint/test/messages/func_excess_escapes.txt deleted file mode 100644 index 2f07722c..00000000 --- a/pymode/libs/pylint/test/messages/func_excess_escapes.txt +++ /dev/null @@ -1,9 +0,0 @@ -W: 7: Anomalous backslash in string: '\['. String constant might be missing an r prefix. -W: 7: Anomalous backslash in string: '\]'. String constant might be missing an r prefix. -W: 8: Anomalous backslash in string: '\/'. String constant might be missing an r prefix. -W: 9: Anomalous backslash in string: '\`'. String constant might be missing an r prefix. -W: 15: Anomalous backslash in string: '\o'. String constant might be missing an r prefix. -W: 15: Anomalous backslash in string: '\o'. String constant might be missing an r prefix. -W: 17: Anomalous backslash in string: '\8'. String constant might be missing an r prefix. -W: 17: Anomalous backslash in string: '\9'. String constant might be missing an r prefix. -W: 27: Anomalous backslash in string: '\P'. String constant might be missing an r prefix. diff --git a/pymode/libs/pylint/test/messages/func_first_arg.txt b/pymode/libs/pylint/test/messages/func_first_arg.txt deleted file mode 100644 index ba4efb8a..00000000 --- a/pymode/libs/pylint/test/messages/func_first_arg.txt +++ /dev/null @@ -1,9 +0,0 @@ -C: 10:Obj.__new__: Class method __new__ should have 'cls' as first argument -C: 18:Obj.class2: Class method class2 should have 'cls' as first argument -C: 25:Meta.__new__: Metaclass class method __new__ should have 'mcs' as first argument -C: 32:Meta.method2: Metaclass method method2 should have 'cls' as first argument -C: 40:Meta.class2: Metaclass class method class2 should have 'mcs' as first argument -R: 16:Obj: Consider using a decorator instead of calling classmethod -R: 20:Obj: Consider using a decorator instead of calling classmethod -R: 38:Meta: Consider using a decorator instead of calling classmethod -R: 42:Meta: Consider using a decorator instead of calling classmethod diff --git a/pymode/libs/pylint/test/messages/func_i0011.txt b/pymode/libs/pylint/test/messages/func_i0011.txt deleted file mode 100644 index 6c1071d3..00000000 --- a/pymode/libs/pylint/test/messages/func_i0011.txt +++ /dev/null @@ -1,2 +0,0 @@ -I: 1: Locally disabling reimported (W0404) -I: 1: Useless suppression of 'reimported' diff --git a/pymode/libs/pylint/test/messages/func_i0012.txt b/pymode/libs/pylint/test/messages/func_i0012.txt deleted file mode 100644 index 76b0c77e..00000000 --- a/pymode/libs/pylint/test/messages/func_i0012.txt +++ /dev/null @@ -1 +0,0 @@ -I: 1: Locally enabling reimported (W0404) diff --git a/pymode/libs/pylint/test/messages/func_i0013.txt b/pymode/libs/pylint/test/messages/func_i0013.txt deleted file mode 100644 index 75d7afd6..00000000 --- a/pymode/libs/pylint/test/messages/func_i0013.txt +++ /dev/null @@ -1 +0,0 @@ -I: 1: Ignoring entire file diff --git a/pymode/libs/pylint/test/messages/func_i0014.txt b/pymode/libs/pylint/test/messages/func_i0014.txt deleted file mode 100644 index c3b521d5..00000000 --- a/pymode/libs/pylint/test/messages/func_i0014.txt +++ /dev/null @@ -1,2 +0,0 @@ -I: 1: Ignoring entire file -I: 1: Pragma "disable-all" is deprecated, use "skip-file" instead diff --git a/pymode/libs/pylint/test/messages/func_i0020.txt b/pymode/libs/pylint/test/messages/func_i0020.txt deleted file mode 100644 index 73f83a42..00000000 --- a/pymode/libs/pylint/test/messages/func_i0020.txt +++ /dev/null @@ -1,2 +0,0 @@ -I: 7: Locally disabling unused-variable (W0612) -I: 8: Suppressed 'unused-variable' (from line 7) diff --git a/pymode/libs/pylint/test/messages/func_i0022.txt b/pymode/libs/pylint/test/messages/func_i0022.txt deleted file mode 100644 index fb527b1d..00000000 --- a/pymode/libs/pylint/test/messages/func_i0022.txt +++ /dev/null @@ -1,21 +0,0 @@ -I: 5: Locally disabling invalid-name (C0103) -I: 5: Suppressed 'invalid-name' (from line 5) -I: 6: Locally disabling invalid-name (C0103) -I: 6: Pragma "disable-msg" is deprecated, use "disable" instead -I: 6: Suppressed 'invalid-name' (from line 6) -I: 8: Locally disabling invalid-name (C0103) -I: 9: Suppressed 'invalid-name' (from line 8) -I: 10: Locally enabling invalid-name (C0103) -I: 12: Locally disabling invalid-name (C0103) -I: 12: Pragma "disable-msg" is deprecated, use "disable" instead -I: 13: Suppressed 'invalid-name' (from line 12) -I: 14: Locally enabling invalid-name (C0103) -I: 14: Pragma "enable-msg" is deprecated, use "enable" instead -I: 16: Locally disabling invalid-name (C0103) -I: 16: Pragma "disable-msg" is deprecated, use "disable" instead -I: 17: Suppressed 'invalid-name' (from line 16) -I: 18: Locally enabling invalid-name (C0103) -I: 18: Pragma "enable-msg" is deprecated, use "enable" instead -I: 20: Locally disabling invalid-name (C0103) -I: 21: Suppressed 'invalid-name' (from line 20) -I: 22: Locally enabling invalid-name (C0103) diff --git a/pymode/libs/pylint/test/messages/func_init_vars.txt b/pymode/libs/pylint/test/messages/func_init_vars.txt deleted file mode 100644 index 44ef6f31..00000000 --- a/pymode/libs/pylint/test/messages/func_init_vars.txt +++ /dev/null @@ -1 +0,0 @@ -W: 18:MyClass.met: Attribute 'base_var' defined outside __init__ diff --git a/pymode/libs/pylint/test/messages/func_kwoa_py30.txt b/pymode/libs/pylint/test/messages/func_kwoa_py30.txt deleted file mode 100644 index 08dd8c57..00000000 --- a/pymode/libs/pylint/test/messages/func_kwoa_py30.txt +++ /dev/null @@ -1,5 +0,0 @@ -E: 10: Missing mandatory keyword argument 'foo' in function call -E: 10: Too many positional arguments for function call -E: 12: Missing mandatory keyword argument 'foo' in function call -E: 12: Too many positional arguments for function call -W: 3:function: Redefining name 'foo' from outer scope (line 9) diff --git a/pymode/libs/pylint/test/messages/func_logging_not_lazy_with_logger.txt b/pymode/libs/pylint/test/messages/func_logging_not_lazy_with_logger.txt deleted file mode 100644 index 04823cf3..00000000 --- a/pymode/libs/pylint/test/messages/func_logging_not_lazy_with_logger.txt +++ /dev/null @@ -1,4 +0,0 @@ -W: 8: Specify string format arguments as logging function parameters -W: 9: Specify string format arguments as logging function parameters -W: 11: Specify string format arguments as logging function parameters -W: 13: Specify string format arguments as logging function parameters diff --git a/pymode/libs/pylint/test/messages/func_loopvar_in_dict_comp_py27.txt b/pymode/libs/pylint/test/messages/func_loopvar_in_dict_comp_py27.txt deleted file mode 100644 index bc11121c..00000000 --- a/pymode/libs/pylint/test/messages/func_loopvar_in_dict_comp_py27.txt +++ /dev/null @@ -1 +0,0 @@ -W: 8:bad_case.: Cell variable x defined in loop diff --git a/pymode/libs/pylint/test/messages/func_module___dict__.txt b/pymode/libs/pylint/test/messages/func_module___dict__.txt deleted file mode 100644 index 41698243..00000000 --- a/pymode/libs/pylint/test/messages/func_module___dict__.txt +++ /dev/null @@ -1 +0,0 @@ -E: 5: Using variable '__dict__' before assignment diff --git a/pymode/libs/pylint/test/messages/func_nameerror_on_string_substitution.txt b/pymode/libs/pylint/test/messages/func_nameerror_on_string_substitution.txt deleted file mode 100644 index aab21024..00000000 --- a/pymode/libs/pylint/test/messages/func_nameerror_on_string_substitution.txt +++ /dev/null @@ -1,2 +0,0 @@ -E: 5: Using variable 'MSG' before assignment -E: 8: Using variable 'MSG2' before assignment diff --git a/pymode/libs/pylint/test/messages/func_no_dummy_redefined.txt b/pymode/libs/pylint/test/messages/func_no_dummy_redefined.txt deleted file mode 100644 index 9ef7891e..00000000 --- a/pymode/libs/pylint/test/messages/func_no_dummy_redefined.txt +++ /dev/null @@ -1,2 +0,0 @@ -C: 7: Invalid constant name "value" -W: 12:clobbering: Redefining name 'value' from outer scope (line 7) diff --git a/pymode/libs/pylint/test/messages/func_nonregr___file___global.txt b/pymode/libs/pylint/test/messages/func_nonregr___file___global.txt deleted file mode 100644 index c0d7340f..00000000 --- a/pymode/libs/pylint/test/messages/func_nonregr___file___global.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 5:func: Redefining built-in '__file__' -W: 5:func: Using the global statement diff --git a/pymode/libs/pylint/test/messages/func_raw_escapes.txt b/pymode/libs/pylint/test/messages/func_raw_escapes.txt deleted file mode 100644 index 991fba7d..00000000 --- a/pymode/libs/pylint/test/messages/func_raw_escapes.txt +++ /dev/null @@ -1,3 +0,0 @@ -W: 5: Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix. -W: 6: Anomalous Unicode escape in byte string: '\U'. String constant might be missing an r or u prefix. -W: 7: Anomalous Unicode escape in byte string: '\N'. String constant might be missing an r or u prefix. diff --git a/pymode/libs/pylint/test/messages/func_return_yield_mix_py_33.txt b/pymode/libs/pylint/test/messages/func_return_yield_mix_py_33.txt deleted file mode 100644 index d81ce5cf..00000000 --- a/pymode/libs/pylint/test/messages/func_return_yield_mix_py_33.txt +++ /dev/null @@ -1,2 +0,0 @@ -E: 6:somegen: Return with argument inside generator -E: 15:moregen: Return with argument inside generator diff --git a/pymode/libs/pylint/test/messages/func_too_many_returns_yields.txt b/pymode/libs/pylint/test/messages/func_too_many_returns_yields.txt deleted file mode 100644 index f8a0f0d2..00000000 --- a/pymode/libs/pylint/test/messages/func_too_many_returns_yields.txt +++ /dev/null @@ -1 +0,0 @@ -R: 5:too_many_returns: Too many return statements (11/6) diff --git a/pymode/libs/pylint/test/messages/func_toolonglines_py30.txt b/pymode/libs/pylint/test/messages/func_toolonglines_py30.txt deleted file mode 100644 index cd594f5f..00000000 --- a/pymode/libs/pylint/test/messages/func_toolonglines_py30.txt +++ /dev/null @@ -1,4 +0,0 @@ -C: 1: Line too long (101/100) -C: 2: Line too long (104/100) -C: 17: Line too long (102/100) -C: 25: Line too long (105/100) diff --git a/pymode/libs/pylint/test/messages/func_typecheck_callfunc_assigment.txt b/pymode/libs/pylint/test/messages/func_typecheck_callfunc_assigment.txt deleted file mode 100644 index e1d05642..00000000 --- a/pymode/libs/pylint/test/messages/func_typecheck_callfunc_assigment.txt +++ /dev/null @@ -1,3 +0,0 @@ -E: 20: Assigning to function call which doesn't return -E: 28: Assigning to function call which only returns None -E: 35: Assigning to function call which only returns None diff --git a/pymode/libs/pylint/test/messages/func_typecheck_getattr_py30.txt b/pymode/libs/pylint/test/messages/func_typecheck_getattr_py30.txt deleted file mode 100644 index b6bf150f..00000000 --- a/pymode/libs/pylint/test/messages/func_typecheck_getattr_py30.txt +++ /dev/null @@ -1,9 +0,0 @@ -E: 25:Client.__init__: Class 'Provider' has no 'cattribute' member -E: 35:Client.use_method: Instance of 'Provider' has no 'hophophop' member -E: 40:Client.use_attr: Instance of 'Provider' has no 'attribute' member -E: 52:Client.test_bt_types: Instance of 'list' has no 'apppend' member -E: 54:Client.test_bt_types: Instance of 'dict' has no 'set' member -E: 56:Client.test_bt_types: Instance of 'tuple' has no 'append' member -E: 58:Client.test_bt_types: Instance of 'str' has no 'loower' member -E: 62:Client.test_bt_types: Instance of 'int' has no 'whatever' member -E: 66: Instance of 'int' has no 'lower' member (but some types could not be inferred) diff --git a/pymode/libs/pylint/test/messages/func_typecheck_non_callable_call.txt b/pymode/libs/pylint/test/messages/func_typecheck_non_callable_call.txt deleted file mode 100644 index 8baa237a..00000000 --- a/pymode/libs/pylint/test/messages/func_typecheck_non_callable_call.txt +++ /dev/null @@ -1,8 +0,0 @@ -E: 10: __revision__ is not callable -E: 29: INSTANCE is not callable -E: 31: LIST is not callable -E: 33: DICT is not callable -E: 35: TUPLE is not callable -E: 37: INT is not callable -E: 72: PROP.test is not callable -E: 73: PROP.custom is not callable \ No newline at end of file diff --git a/pymode/libs/pylint/test/messages/func_unicode_literal_py26.txt b/pymode/libs/pylint/test/messages/func_unicode_literal_py26.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/pymode/libs/pylint/test/messages/func_unicode_literal_py274.txt b/pymode/libs/pylint/test/messages/func_unicode_literal_py274.txt deleted file mode 100644 index 25efa999..00000000 --- a/pymode/libs/pylint/test/messages/func_unicode_literal_py274.txt +++ /dev/null @@ -1 +0,0 @@ -W: 6: Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix. diff --git a/pymode/libs/pylint/test/messages/func_unused_import_py30.txt b/pymode/libs/pylint/test/messages/func_unused_import_py30.txt deleted file mode 100644 index aa79b287..00000000 --- a/pymode/libs/pylint/test/messages/func_unused_import_py30.txt +++ /dev/null @@ -1 +0,0 @@ -W: 8: Reimport 'ABCMeta' (imported line 7) diff --git a/pymode/libs/pylint/test/messages/func_unused_overridden_argument.txt b/pymode/libs/pylint/test/messages/func_unused_overridden_argument.txt deleted file mode 100644 index d7da45b1..00000000 --- a/pymode/libs/pylint/test/messages/func_unused_overridden_argument.txt +++ /dev/null @@ -1 +0,0 @@ -W: 22:Sub.newmethod: Unused argument 'aay' diff --git a/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py29.txt b/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py29.txt deleted file mode 100644 index 14d61ad6..00000000 --- a/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py29.txt +++ /dev/null @@ -1,3 +0,0 @@ -W: 6: Using possibly undefined loop variable 'C' -W: 15: Using possibly undefined loop variable 'var1' - diff --git a/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py30.txt b/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py30.txt deleted file mode 100644 index 46d3430a..00000000 --- a/pymode/libs/pylint/test/messages/func_use_for_or_listcomp_var_py30.txt +++ /dev/null @@ -1,3 +0,0 @@ -E: 6: Using variable 'C' before assignment -W: 15: Using possibly undefined loop variable 'var1' - diff --git a/pymode/libs/pylint/test/messages/func_variables_unused_name_from_wilcard_import.txt b/pymode/libs/pylint/test/messages/func_variables_unused_name_from_wilcard_import.txt deleted file mode 100644 index 01c57af0..00000000 --- a/pymode/libs/pylint/test/messages/func_variables_unused_name_from_wilcard_import.txt +++ /dev/null @@ -1,4 +0,0 @@ -W: 3: Unused import NonRegr from wildcard import -W: 3: Unused import os from wildcard import -W: 3: Unused import sys from wildcard import -W: 3: Wildcard import input.func_w0611 diff --git a/pymode/libs/pylint/test/messages/func_w0122_py_30.txt b/pymode/libs/pylint/test/messages/func_w0122_py_30.txt deleted file mode 100644 index d833076d..00000000 --- a/pymode/libs/pylint/test/messages/func_w0122_py_30.txt +++ /dev/null @@ -1,5 +0,0 @@ -W: 5: Use of exec -W: 6: Use of exec -W: 8: Use of exec -W: 12:func: Use of exec - diff --git a/pymode/libs/pylint/test/messages/func_w0205.txt b/pymode/libs/pylint/test/messages/func_w0205.txt deleted file mode 100644 index 83ac5de2..00000000 --- a/pymode/libs/pylint/test/messages/func_w0205.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 22:Cdef.abcd: Signature differs from overridden 'abcd' method - diff --git a/pymode/libs/pylint/test/messages/func_w0233.txt b/pymode/libs/pylint/test/messages/func_w0233.txt deleted file mode 100644 index 7c7780e7..00000000 --- a/pymode/libs/pylint/test/messages/func_w0233.txt +++ /dev/null @@ -1,6 +0,0 @@ -E: 6: Unable to import 'nonexistant' -E: 22:CCC: Module 'input.func_w0233' has no 'BBBB' member -E: 27:CCC.__init__: Module 'input.func_w0233' has no 'BBBB' member -E: 50:Super2.__init__: Super of 'Super2' has no '__woohoo__' member -W: 14:AAAA.__init__: __init__ method from a non direct base class 'BBBBMixin' is called -W: 48:Super2.__init__: __init__ method from base class 'dict' is not called diff --git a/pymode/libs/pylint/test/messages/func_w0312.txt b/pymode/libs/pylint/test/messages/func_w0312.txt deleted file mode 100644 index 917e8d0e..00000000 --- a/pymode/libs/pylint/test/messages/func_w0312.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 10: Found indentation with tabs instead of spaces -W: 11: Found indentation with tabs instead of spaces diff --git a/pymode/libs/pylint/test/messages/func_w0332_py_30.txt b/pymode/libs/pylint/test/messages/func_w0332_py_30.txt deleted file mode 100644 index 16f1d802..00000000 --- a/pymode/libs/pylint/test/messages/func_w0332_py_30.txt +++ /dev/null @@ -1 +0,0 @@ -W: 4: Use of "l" as long integer identifier diff --git a/pymode/libs/pylint/test/messages/func_w0401.txt b/pymode/libs/pylint/test/messages/func_w0401.txt deleted file mode 100644 index f6648f47..00000000 --- a/pymode/libs/pylint/test/messages/func_w0401.txt +++ /dev/null @@ -1,3 +0,0 @@ -R: 1: Cyclic import (input.func_w0401 -> input.w0401_cycle) -W: 8: Using a conditional statement with a constant value -W: 8: Using a conditional statement with a constant value diff --git a/pymode/libs/pylint/test/messages/func_w0401_package.txt b/pymode/libs/pylint/test/messages/func_w0401_package.txt deleted file mode 100644 index 4b1145bb..00000000 --- a/pymode/libs/pylint/test/messages/func_w0401_package.txt +++ /dev/null @@ -1 +0,0 @@ -R: 1: Cyclic import (input.func_w0401_package.all_the_things -> input.func_w0401_package.thing2) diff --git a/pymode/libs/pylint/test/messages/func_w0404.txt b/pymode/libs/pylint/test/messages/func_w0404.txt deleted file mode 100644 index 2cfc1373..00000000 --- a/pymode/libs/pylint/test/messages/func_w0404.txt +++ /dev/null @@ -1,5 +0,0 @@ -W: 7: Reimport 'ElementTree' (imported line 6) -W: 10: Reimport 'email.encoders' (imported line 9) -W: 12: Reimport 'sys' (imported line 4) -W: 23:reimport: Redefining name 'sys' from outer scope (line 4) -W: 23:reimport: Reimport 'sys' (imported line 4) diff --git a/pymode/libs/pylint/test/messages/func_w0405.txt b/pymode/libs/pylint/test/messages/func_w0405.txt deleted file mode 100644 index 072b1554..00000000 --- a/pymode/libs/pylint/test/messages/func_w0405.txt +++ /dev/null @@ -1,4 +0,0 @@ -W: 8: Reimport 'os' (imported line 6) -W: 16: Reimport 'exists' (imported line 7) -W: 21:func: Reimport 'os' (imported line 6) -W: 23:func: Reimport 're' (imported line 9) diff --git a/pymode/libs/pylint/test/messages/func_w0406.txt b/pymode/libs/pylint/test/messages/func_w0406.txt deleted file mode 100644 index f6bc14db..00000000 --- a/pymode/libs/pylint/test/messages/func_w0406.txt +++ /dev/null @@ -1 +0,0 @@ -W: 4: Module import itself diff --git a/pymode/libs/pylint/test/messages/func_w0611.txt b/pymode/libs/pylint/test/messages/func_w0611.txt deleted file mode 100644 index 2be0d0a8..00000000 --- a/pymode/libs/pylint/test/messages/func_w0611.txt +++ /dev/null @@ -1 +0,0 @@ -W: 7: Unused import os diff --git a/pymode/libs/pylint/test/messages/func_w0612.txt b/pymode/libs/pylint/test/messages/func_w0612.txt deleted file mode 100644 index 752aa700..00000000 --- a/pymode/libs/pylint/test/messages/func_w0612.txt +++ /dev/null @@ -1,5 +0,0 @@ -W: 9:function: Unused variable 'aaaa' -W: 34:test_global: Unused variable 'platform' -W: 35:test_global: Unused variable 'VERSION' -W: 36:test_global: Unused variable 'this' -W: 37:test_global: Unused variable 'RE' diff --git a/pymode/libs/pylint/test/messages/func_w0613.txt b/pymode/libs/pylint/test/messages/func_w0613.txt deleted file mode 100644 index 36cb3801..00000000 --- a/pymode/libs/pylint/test/messages/func_w0613.txt +++ /dev/null @@ -1,5 +0,0 @@ -W: 7:function: Unused argument 'arg' -W: 14:AAAA.method: Unused argument 'arg' -W: 21:AAAA.selected: Unused argument 'args' -W: 21:AAAA.selected: Unused argument 'kwargs' -W: 40:BBBB.__init__: Unused argument 'arg' diff --git a/pymode/libs/pylint/test/messages/func_w0622.txt b/pymode/libs/pylint/test/messages/func_w0622.txt deleted file mode 100644 index 71913472..00000000 --- a/pymode/libs/pylint/test/messages/func_w0622.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 8:function: Redefining built-in 'type' -W: 11: Redefining built-in 'map' diff --git a/pymode/libs/pylint/test/messages/func_w0623.txt b/pymode/libs/pylint/test/messages/func_w0623.txt deleted file mode 100644 index b764def8..00000000 --- a/pymode/libs/pylint/test/messages/func_w0623.txt +++ /dev/null @@ -1,11 +0,0 @@ -C: 28:some_function: Invalid variable name "FOO" -C: 41: Invalid constant name "exc3" -C: 55: Invalid variable name "OOPS" -W: 18:some_function: Redefining name 'RuntimeError' from object 'exceptions' in exception handler -W: 20:some_function: Redefining name 'OSError' from builtins in exception handler -W: 20:some_function: Unused variable 'OSError' -W: 22:some_function: Redefining name 'MyError' from outer scope (line 7) in exception handler -W: 22:some_function: Unused variable 'MyError' -W: 45: Redefining name 'RuntimeError' from object 'exceptions' in exception handler -W: 47: Redefining name 'OSError' from builtins in exception handler -W: 49: Redefining name 'MyOtherError' from outer scope (line 36) in exception handler diff --git a/pymode/libs/pylint/test/messages/func_w0623_py30.txt b/pymode/libs/pylint/test/messages/func_w0623_py30.txt deleted file mode 100644 index 5d78dbfd..00000000 --- a/pymode/libs/pylint/test/messages/func_w0623_py30.txt +++ /dev/null @@ -1,2 +0,0 @@ -W: 15:some_function: Redefining name 'some_function' from outer scope (line 10) in exception handler -W: 15:some_function: Unused variable 'some_function' diff --git a/pymode/libs/pylint/test/messages/func_w0623_py_30.txt b/pymode/libs/pylint/test/messages/func_w0623_py_30.txt deleted file mode 100644 index a2923f1f..00000000 --- a/pymode/libs/pylint/test/messages/func_w0623_py_30.txt +++ /dev/null @@ -1,12 +0,0 @@ -C: 28:some_function: Invalid variable name "FOO" -C: 41: Invalid constant name "exc3" -C: 57: Invalid variable name "OOPS" -W: 18:some_function: Redefining name 'RuntimeError' from object 'exceptions' in exception handler -W: 20:some_function: Redefining name 'OSError' from builtins in exception handler -W: 20:some_function: Unused variable 'OSError' -W: 22:some_function: Redefining name 'MyError' from outer scope (line 7) in exception handler -W: 22:some_function: Unused variable 'MyError' -W: 45: Redefining name 'RuntimeError' from object 'exceptions' in exception handler -W: 47: Redefining name 'args' from object 'exceptions.RuntimeError' in exception handler -W: 49: Redefining name 'OSError' from builtins in exception handler -W: 51: Redefining name 'MyOtherError' from outer scope (line 36) in exception handler diff --git a/pymode/libs/pylint/test/messages/func_w0631.txt b/pymode/libs/pylint/test/messages/func_w0631.txt deleted file mode 100644 index af335a17..00000000 --- a/pymode/libs/pylint/test/messages/func_w0631.txt +++ /dev/null @@ -1 +0,0 @@ -W: 10:do_stuff: Using possibly undefined loop variable 'var' diff --git a/pymode/libs/pylint/test/messages/func_w0703.txt b/pymode/libs/pylint/test/messages/func_w0703.txt deleted file mode 100644 index 6135664e..00000000 --- a/pymode/libs/pylint/test/messages/func_w0703.txt +++ /dev/null @@ -1 +0,0 @@ -W: 8: Catching too general exception Exception diff --git a/pymode/libs/pylint/test/messages/func_w0705.txt b/pymode/libs/pylint/test/messages/func_w0705.txt deleted file mode 100644 index 1cc32a7a..00000000 --- a/pymode/libs/pylint/test/messages/func_w0705.txt +++ /dev/null @@ -1,11 +0,0 @@ -E: 10: Bad except clauses order (Exception is an ancestor class of TypeError) -E: 17: Bad except clauses order (LookupError is an ancestor class of IndexError) -E: 24: Bad except clauses order (LookupError is an ancestor class of IndexError) -E: 24: Bad except clauses order (NameError is an ancestor class of UnboundLocalError) -E: 27: Bad except clauses order (empty except clause should always appear last) -W: 8: Catching too general exception Exception -W: 29: No exception type(s) specified -W: 31: Catching too general exception Exception -W: 38: No exception type(s) specified -W: 43: Catching too general exception Exception -W: 45: No exception type(s) specified diff --git a/pymode/libs/pylint/test/messages/func_w0801.txt b/pymode/libs/pylint/test/messages/func_w0801.txt deleted file mode 100644 index 203ce929..00000000 --- a/pymode/libs/pylint/test/messages/func_w0801.txt +++ /dev/null @@ -1,11 +0,0 @@ -R: 1: Similar lines in 2 files -==input.func_w0801:3 -==input.w0801_same:3 -__revision__ = 'id' -A = 2 -B = 3 -C = A + B -# need more than X lines to trigger the message -C *= 2 -A -= B -# all this should be detected diff --git a/pymode/libs/pylint/test/messages/func_with_without_as_py25.txt b/pymode/libs/pylint/test/messages/func_with_without_as_py25.txt deleted file mode 100644 index 18ca3711..00000000 --- a/pymode/libs/pylint/test/messages/func_with_without_as_py25.txt +++ /dev/null @@ -1,3 +0,0 @@ -E: 11:do_nothing: Using variable 'base' before assignment -W: 11:do_nothing: Statement seems to have no effect - diff --git a/pymode/libs/pylint/test/regrtest_data/.pylintrc b/pymode/libs/pylint/test/regrtest_data/.pylintrc deleted file mode 100644 index 9a5bb5a4..00000000 --- a/pymode/libs/pylint/test/regrtest_data/.pylintrc +++ /dev/null @@ -1,4 +0,0 @@ -[MASTER] - -optimize-ast=no - diff --git a/pymode/libs/pylint/test/regrtest_data/absimp/__init__.py b/pymode/libs/pylint/test/regrtest_data/absimp/__init__.py deleted file mode 100644 index fdabe9f7..00000000 --- a/pymode/libs/pylint/test/regrtest_data/absimp/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""a package with absolute import activated -""" - -from __future__ import absolute_import diff --git a/pymode/libs/pylint/test/regrtest_data/absimp/string.py b/pymode/libs/pylint/test/regrtest_data/absimp/string.py deleted file mode 100644 index f47e9a5e..00000000 --- a/pymode/libs/pylint/test/regrtest_data/absimp/string.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -http://www.logilab.org/ticket/70495 -http://www.logilab.org/ticket/70565 -""" -from __future__ import absolute_import, print_function -import string -print(string) diff --git a/pymode/libs/pylint/test/regrtest_data/application_crash.py b/pymode/libs/pylint/test/regrtest_data/application_crash.py deleted file mode 100644 index 6e6044aa..00000000 --- a/pymode/libs/pylint/test/regrtest_data/application_crash.py +++ /dev/null @@ -1,12 +0,0 @@ -class ErudiPublisher: - def __init__(self, config): - self.url_resolver = self.select_component('urlpublisher') - - def select_component(self, cid, *args, **kwargs): - try: - return self.select(self.registry_objects('components', cid), *args, **kwargs) - except NoSelectableObject: - return - - def main_publish(self, path, req): - ctrlid = self.url_resolver.process(req, path) diff --git a/pymode/libs/pylint/test/regrtest_data/bad_package/__init__.py b/pymode/libs/pylint/test/regrtest_data/bad_package/__init__.py deleted file mode 100644 index 76f75d3f..00000000 --- a/pymode/libs/pylint/test/regrtest_data/bad_package/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import missing -raise missing.Missing.. \ No newline at end of file diff --git a/pymode/libs/pylint/test/regrtest_data/bad_package/wrong.py b/pymode/libs/pylint/test/regrtest_data/bad_package/wrong.py deleted file mode 100644 index 4feea7e8..00000000 --- a/pymode/libs/pylint/test/regrtest_data/bad_package/wrong.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -Test that pylint doesn't crash when a relative import -depends on the local __init__, which contains an expected syntax error. -""" -from . import missing diff --git a/pymode/libs/pylint/test/regrtest_data/classdoc_usage.py b/pymode/libs/pylint/test/regrtest_data/classdoc_usage.py deleted file mode 100644 index c17c9f6f..00000000 --- a/pymode/libs/pylint/test/regrtest_data/classdoc_usage.py +++ /dev/null @@ -1,16 +0,0 @@ -"""ds""" - -__revision__ = None - -class SomeClass(object): - """cds""" - doc = __doc__ - - def __init__(self): - """only to make pylint happier""" - - def please(self): - """public method 1/2""" - - def besilent(self): - """public method 2/2""" diff --git a/pymode/libs/pylint/test/regrtest_data/decimal_inference.py b/pymode/libs/pylint/test/regrtest_data/decimal_inference.py deleted file mode 100644 index 00c91304..00000000 --- a/pymode/libs/pylint/test/regrtest_data/decimal_inference.py +++ /dev/null @@ -1,10 +0,0 @@ -"""hum E1011 on .prec member is justifiable since Context instance are built -using setattr/locals :( - -2007/02/17 update: .prec attribute is now detected by astroid :o) -""" -from __future__ import print_function -import decimal - -decimal.getcontext().prec = 200 -print(decimal.getcontext().prec) diff --git a/pymode/libs/pylint/test/regrtest_data/descriptor_crash.py b/pymode/libs/pylint/test/regrtest_data/descriptor_crash.py deleted file mode 100644 index 4b3adccd..00000000 --- a/pymode/libs/pylint/test/regrtest_data/descriptor_crash.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: iso-8859-1 -*- - -import urllib - -class Page(object): - _urlOpen = staticmethod(urllib.urlopen) - - def getPage(self, url): - handle = self._urlOpen(url) - data = handle.read() - handle.close() - return data - #_getPage - -#Page - -if __name__ == "__main__": - import sys - p = Page() - print p.getPage(sys.argv[1]) diff --git a/pymode/libs/pylint/test/regrtest_data/dummy/__init__.py b/pymode/libs/pylint/test/regrtest_data/dummy/__init__.py deleted file mode 100644 index 0b43a709..00000000 --- a/pymode/libs/pylint/test/regrtest_data/dummy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# pylint: disable=missing-docstring -from .dummy import DUMMY -from .another import ANOTHER diff --git a/pymode/libs/pylint/test/regrtest_data/dummy/another.py b/pymode/libs/pylint/test/regrtest_data/dummy/another.py deleted file mode 100644 index 56a87123..00000000 --- a/pymode/libs/pylint/test/regrtest_data/dummy/another.py +++ /dev/null @@ -1,3 +0,0 @@ -# pylint: disable=missing-docstring - -ANOTHER = 42 diff --git a/pymode/libs/pylint/test/regrtest_data/dummy/dummy.py b/pymode/libs/pylint/test/regrtest_data/dummy/dummy.py deleted file mode 100644 index 60345dc1..00000000 --- a/pymode/libs/pylint/test/regrtest_data/dummy/dummy.py +++ /dev/null @@ -1,2 +0,0 @@ -# pylint: disable=missing-docstring -DUMMY = 42 diff --git a/pymode/libs/pylint/test/regrtest_data/html_crash_420.py b/pymode/libs/pylint/test/regrtest_data/html_crash_420.py deleted file mode 100644 index 2a8481aa..00000000 --- a/pymode/libs/pylint/test/regrtest_data/html_crash_420.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -tag2struct = {u"#": "R_HEADER" - ,u"£": "RDR_HEADER" - ,u"µ": "RDR_DRAFT" - } \ No newline at end of file diff --git a/pymode/libs/pylint/test/regrtest_data/huge.py b/pymode/libs/pylint/test/regrtest_data/huge.py deleted file mode 100644 index 7ffdbac7..00000000 --- a/pymode/libs/pylint/test/regrtest_data/huge.py +++ /dev/null @@ -1,12600 +0,0 @@ -a,b=2 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 -a,b=2,3 diff --git a/pymode/libs/pylint/test/regrtest_data/import_assign.py b/pymode/libs/pylint/test/regrtest_data/import_assign.py deleted file mode 100644 index c01cd52f..00000000 --- a/pymode/libs/pylint/test/regrtest_data/import_assign.py +++ /dev/null @@ -1,5 +0,0 @@ -import shmixml.dom.minidom -import xml.dom.minidom - -if 'dom' not in xml.__dict__: - xml.dom = shmixml.dom diff --git a/pymode/libs/pylint/test/regrtest_data/import_package_subpackage_module.py b/pymode/libs/pylint/test/regrtest_data/import_package_subpackage_module.py deleted file mode 100644 index 2864e3c9..00000000 --- a/pymode/libs/pylint/test/regrtest_data/import_package_subpackage_module.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: disable=I0011,C0301,W0611 -"""I found some of my scripts trigger off an AttributeError in pylint -0.8.1 (with common 0.12.0 and astroid 0.13.1). - -Traceback (most recent call last): - File "/usr/bin/pylint", line 4, in ? - lint.Run(sys.argv[1:]) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__ - linter.check(args) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check - self.check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file - astroid = self._check_file(filepath, modname, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file - self.check_astroid_module(astroid, checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module - self.astroid_events(astroid, [checker for checker in checkers - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events - self.astroid_events(child, checkers, _reversed_checkers) - File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events - checker.visit(astroid) - File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit - method(node) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import - self._check_module_attrs(node, module, name_parts[1:]) - File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs - self.add_message('E0611', args=(name, module.name), -AttributeError: Import instance has no attribute 'name' - - -You can reproduce it by: -(1) create package structure like the following: - -package/ - __init__.py - subpackage/ - __init__.py - module.py - -(2) in package/__init__.py write: - -import subpackage - -(3) run pylint with a script importing package.subpackage.module. -""" -import package.subpackage.module -__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 16:08:54 syt Exp $' diff --git a/pymode/libs/pylint/test/regrtest_data/import_something.py b/pymode/libs/pylint/test/regrtest_data/import_something.py deleted file mode 100644 index 61bc51fd..00000000 --- a/pymode/libs/pylint/test/regrtest_data/import_something.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=missing-docstring,unused-import - -import os -import sys diff --git a/pymode/libs/pylint/test/regrtest_data/meta.py b/pymode/libs/pylint/test/regrtest_data/meta.py deleted file mode 100644 index 70012072..00000000 --- a/pymode/libs/pylint/test/regrtest_data/meta.py +++ /dev/null @@ -1,3 +0,0 @@ -# pylint: disable=invalid-name, missing-docstring -# pylint: disable=unbalanced-tuple-unpacking -n = 42 diff --git a/pymode/libs/pylint/test/regrtest_data/module_global.py b/pymode/libs/pylint/test/regrtest_data/module_global.py deleted file mode 100644 index 107d6528..00000000 --- a/pymode/libs/pylint/test/regrtest_data/module_global.py +++ /dev/null @@ -1,7 +0,0 @@ -# pylint: disable=W0603,W0601,W0604,E0602,W0104 -"""was causing infinite recursion -""" -__revision__ = 1 - -global GLOBAL_VAR -GLOBAL_VAR.foo diff --git a/pymode/libs/pylint/test/regrtest_data/no_stdout_encoding.py b/pymode/libs/pylint/test/regrtest_data/no_stdout_encoding.py deleted file mode 100644 index 0574da8a..00000000 --- a/pymode/libs/pylint/test/regrtest_data/no_stdout_encoding.py +++ /dev/null @@ -1,4 +0,0 @@ -#-*- coding:iso-8859-1 -*- -class test: - def __init__ (self, dir): - testString = u"répertoire :\n%s !"%dir diff --git a/pymode/libs/pylint/test/regrtest_data/numarray_import.py b/pymode/libs/pylint/test/regrtest_data/numarray_import.py deleted file mode 100644 index e89757f1..00000000 --- a/pymode/libs/pylint/test/regrtest_data/numarray_import.py +++ /dev/null @@ -1,7 +0,0 @@ -"""#10077""" - -__revision__ = 1 - -from numarray import zeros - -zeros(shape=(4, 5)) diff --git a/pymode/libs/pylint/test/regrtest_data/numarray_inf.py b/pymode/libs/pylint/test/regrtest_data/numarray_inf.py deleted file mode 100644 index 4ea22a9c..00000000 --- a/pymode/libs/pylint/test/regrtest_data/numarray_inf.py +++ /dev/null @@ -1,5 +0,0 @@ -"""#3216""" - -import numarray as na -import numarray.random_array as nar -IM16 = nar.randint(0, 256, 300).astype(na.UInt8) diff --git a/pymode/libs/pylint/test/regrtest_data/package/AudioTime.py b/pymode/libs/pylint/test/regrtest_data/package/AudioTime.py deleted file mode 100644 index a1fde965..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package/AudioTime.py +++ /dev/null @@ -1,3 +0,0 @@ -"""test preceeded by the AudioTime class in __init__.py""" - -__revision__ = 0 diff --git a/pymode/libs/pylint/test/regrtest_data/package/__init__.py b/pymode/libs/pylint/test/regrtest_data/package/__init__.py deleted file mode 100644 index 7353ba87..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# pylint: disable=R0903,W0403 -"""package's __init__ file""" - -from . import subpackage - -__revision__ = 0 - -# E0602 - Undefined variable '__path__' -__path__ += "folder" - -class AudioTime(object): - """test precedence over the AudioTime submodule""" - - DECIMAL = 3 diff --git a/pymode/libs/pylint/test/regrtest_data/package/subpackage/__init__.py b/pymode/libs/pylint/test/regrtest_data/package/subpackage/__init__.py deleted file mode 100644 index dc4782e6..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package/subpackage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage""" diff --git a/pymode/libs/pylint/test/regrtest_data/package/subpackage/module.py b/pymode/libs/pylint/test/regrtest_data/package/subpackage/module.py deleted file mode 100644 index 4b7244ba..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package/subpackage/module.py +++ /dev/null @@ -1 +0,0 @@ -"""package.subpackage.module""" diff --git a/pymode/libs/pylint/test/regrtest_data/package_all/__init__.py b/pymode/libs/pylint/test/regrtest_data/package_all/__init__.py deleted file mode 100644 index 3107fff5..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package_all/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" Check for E0603 for missing submodule found in __all__ """ -__revision__ = 1 -__all__ = ['notmissing', 'missing'] diff --git a/pymode/libs/pylint/test/regrtest_data/package_all/notmissing.py b/pymode/libs/pylint/test/regrtest_data/package_all/notmissing.py deleted file mode 100644 index 4ca0c328..00000000 --- a/pymode/libs/pylint/test/regrtest_data/package_all/notmissing.py +++ /dev/null @@ -1,2 +0,0 @@ -""" empty """ -__revision__ = 1 diff --git a/pymode/libs/pylint/test/regrtest_data/precedence_test.py b/pymode/libs/pylint/test/regrtest_data/precedence_test.py deleted file mode 100644 index ff5871d4..00000000 --- a/pymode/libs/pylint/test/regrtest_data/precedence_test.py +++ /dev/null @@ -1,21 +0,0 @@ -""" - # package/__init__.py - class AudioTime(object): - DECIMAL = 3 - - # package/AudioTime.py - class AudioTime(object): - pass - - # test.py - from package import AudioTime - # E0611 - No name 'DECIMAL' in module 'AudioTime.AudioTime' - print AudioTime.DECIMAL - -""" -from __future__ import print_function -from package import AudioTime -__revision__ = 0 - - -print(AudioTime.DECIMAL) diff --git a/pymode/libs/pylint/test/regrtest_data/py3k_error_flag.py b/pymode/libs/pylint/test/regrtest_data/py3k_error_flag.py deleted file mode 100644 index 12f5c4de..00000000 --- a/pymode/libs/pylint/test/regrtest_data/py3k_error_flag.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Contains both normal error messages and Python3 porting error messages.""" -# pylint: disable=too-few-public-methods - -raise Exception, 1 # Error emitted here with the Python 3 checker. - - -class Test(object): - """dummy""" - - def __init__(self): - return 42 diff --git a/pymode/libs/pylint/test/regrtest_data/special_attr_scope_lookup_crash.py b/pymode/libs/pylint/test/regrtest_data/special_attr_scope_lookup_crash.py deleted file mode 100644 index b693a9fc..00000000 --- a/pymode/libs/pylint/test/regrtest_data/special_attr_scope_lookup_crash.py +++ /dev/null @@ -1,3 +0,0 @@ -class Klass(object): - """A""" - __doc__ += "B" diff --git a/pymode/libs/pylint/test/regrtest_data/syntax_error.py b/pymode/libs/pylint/test/regrtest_data/syntax_error.py deleted file mode 100644 index bf86aff0..00000000 --- a/pymode/libs/pylint/test/regrtest_data/syntax_error.py +++ /dev/null @@ -1 +0,0 @@ -class A extends B {} \ No newline at end of file diff --git a/pymode/libs/pylint/test/regrtest_data/try_finally_disable_msg_crash.py b/pymode/libs/pylint/test/regrtest_data/try_finally_disable_msg_crash.py deleted file mode 100644 index 1719308f..00000000 --- a/pymode/libs/pylint/test/regrtest_data/try_finally_disable_msg_crash.py +++ /dev/null @@ -1,5 +0,0 @@ -try: - pass -finally: - # pylint: disable=W0201 - pass diff --git a/pymode/libs/pylint/test/regrtest_data/wrong_import_position.py b/pymode/libs/pylint/test/regrtest_data/wrong_import_position.py deleted file mode 100644 index 30fa9234..00000000 --- a/pymode/libs/pylint/test/regrtest_data/wrong_import_position.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Test that wrong-import-position is properly reset when -other errors are disabled. -""" -# pylint: disable=unused-import, too-few-public-methods - - -class Something(object): - """A class before an import.""" - - -import os diff --git a/pymode/libs/pylint/test/test_func.py b/pymode/libs/pylint/test/test_func.py deleted file mode 100644 index 4ddfaf62..00000000 --- a/pymode/libs/pylint/test/test_func.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""functional/non regression tests for pylint""" - -import unittest -import sys -import re - -from os import getcwd -from os.path import abspath, dirname, join - -from pylint.testutils import (make_tests, LintTestUsingModule, LintTestUsingFile, - LintTestUpdate, cb_test_gen, linter, test_reporter) - -PY3K = sys.version_info >= (3, 0) - -# Configure paths -INPUT_DIR = join(dirname(abspath(__file__)), 'input') -MSG_DIR = join(dirname(abspath(__file__)), 'messages') - -# Classes - -quote = "'" if sys.version_info >= (3, 3) else '' - -class LintTestNonExistentModuleTC(LintTestUsingModule): - module = 'nonexistent' - _get_expected = lambda self: 'F: 1: No module named %snonexistent%s\n' % (quote, quote) - - -def gen_tests(filter_rgx): - if UPDATE: - callbacks = [cb_test_gen(LintTestUpdate)] - else: - callbacks = [cb_test_gen(LintTestUsingModule)] - tests = make_tests(INPUT_DIR, MSG_DIR, filter_rgx, callbacks) - if UPDATE: - return tests - - if filter_rgx: - is_to_run = re.compile(filter_rgx).search - else: - is_to_run = lambda x: 1 - - if is_to_run('nonexistent'): - tests.append(LintTestNonExistentModuleTC) - - assert len(tests) < 196, "Please do not add new test cases here." - return tests - -# Create suite - -FILTER_RGX = None -UPDATE = False - -def suite(): - return unittest.TestSuite([unittest.makeSuite(test, suiteClass=unittest.TestSuite) - for test in gen_tests(FILTER_RGX)]) - - -def load_tests(loader, tests, pattern): - return suite() - - -if __name__=='__main__': - if '-u' in sys.argv: - UPDATE = True - sys.argv.remove('-u') - - if len(sys.argv) > 1: - FILTER_RGX = sys.argv[1] - del sys.argv[1] - unittest.main(defaultTest='suite') diff --git a/pymode/libs/pylint/test/test_functional.py b/pymode/libs/pylint/test/test_functional.py deleted file mode 100644 index 231430c3..00000000 --- a/pymode/libs/pylint/test/test_functional.py +++ /dev/null @@ -1,374 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Functional full-module tests for PyLint.""" -import csv -import collections -import io -import operator -import os -import re -import sys -import platform -import unittest - -import six -from six.moves import configparser - -from pylint import checkers -from pylint import interfaces -from pylint import lint -from pylint import reporters -from pylint import utils - -class test_dialect(csv.excel): - if sys.version_info[0] < 3: - delimiter = b':' - lineterminator = b'\n' - else: - delimiter = ':' - lineterminator = '\n' - - -csv.register_dialect('test', test_dialect) - - -class NoFileError(Exception): - pass - -# Notes: -# - for the purpose of this test, the confidence levels HIGH and UNDEFINED -# are treated as the same. - -# TODOs -# - implement exhaustivity tests - -# If message files should be updated instead of checked. -UPDATE = False - -class OutputLine(collections.namedtuple('OutputLine', - ['symbol', 'lineno', 'object', 'msg', 'confidence'])): - @classmethod - def from_msg(cls, msg): - return cls( - msg.symbol, msg.line, msg.obj or '', msg.msg.replace("\r\n", "\n"), - msg.confidence.name - if msg.confidence != interfaces.UNDEFINED else interfaces.HIGH.name) - - @classmethod - def from_csv(cls, row): - confidence = row[4] if len(row) == 5 else interfaces.HIGH.name - return cls(row[0], int(row[1]), row[2], row[3], confidence) - - def to_csv(self): - if self.confidence == interfaces.HIGH.name: - return self[:-1] - else: - return self - - -# Common sub-expressions. -_MESSAGE = {'msg': r'[a-z][a-z\-]+'} -# Matches a #, -# - followed by a comparison operator and a Python version (optional), -# - followed by an line number with a +/- (optional), -# - followed by a list of bracketed message symbols. -# Used to extract expected messages from testdata files. -_EXPECTED_RE = re.compile( - r'\s*#\s*(?:(?P[+-]?[0-9]+):)?' - r'(?:(?P[><=]+) *(?P[0-9.]+):)?' - r'\s*\[(?P%(msg)s(?:,\s*%(msg)s)*)\]' % _MESSAGE) - - -def parse_python_version(str): - return tuple(int(digit) for digit in str.split('.')) - - -class TestReporter(reporters.BaseReporter): - def handle_message(self, msg): - self.messages.append(msg) - - def on_set_current_module(self, module, filepath): - self.messages = [] - - def display_reports(self, layout): - """Ignore layouts.""" - - -class TestFile(object): - """A single functional test case file with options.""" - - _CONVERTERS = { - 'min_pyver': parse_python_version, - 'max_pyver': parse_python_version, - 'requires': lambda s: s.split(',') - } - - - def __init__(self, directory, filename): - self._directory = directory - self.base = filename.replace('.py', '') - self.options = { - 'min_pyver': (2, 5), - 'max_pyver': (4, 0), - 'requires': [], - 'except_implementations': [], - } - self._parse_options() - - def _parse_options(self): - cp = configparser.ConfigParser() - cp.add_section('testoptions') - try: - cp.read(self.option_file) - except NoFileError: - pass - - for name, value in cp.items('testoptions'): - conv = self._CONVERTERS.get(name, lambda v: v) - self.options[name] = conv(value) - - @property - def option_file(self): - return self._file_type('.rc') - - @property - def module(self): - package = os.path.basename(self._directory) - return '.'.join([package, self.base]) - - @property - def expected_output(self): - return self._file_type('.txt', check_exists=False) - - @property - def source(self): - return self._file_type('.py') - - def _file_type(self, ext, check_exists=True): - name = os.path.join(self._directory, self.base + ext) - if not check_exists or os.path.exists(name): - return name - else: - raise NoFileError - - -_OPERATORS = { - '>': operator.gt, - '<': operator.lt, - '>=': operator.ge, - '<=': operator.le, -} - -def parse_expected_output(stream): - return [OutputLine.from_csv(row) for row in csv.reader(stream, 'test')] - - -def get_expected_messages(stream): - """Parses a file and get expected messages. - - :param stream: File-like input stream. - :returns: A dict mapping line,msg-symbol tuples to the count on this line. - """ - messages = collections.Counter() - for i, line in enumerate(stream): - match = _EXPECTED_RE.search(line) - if match is None: - continue - line = match.group('line') - if line is None: - line = i + 1 - elif line.startswith('+') or line.startswith('-'): - line = i + 1 + int(line) - else: - line = int(line) - - version = match.group('version') - op = match.group('op') - if version: - required = parse_python_version(version) - if not _OPERATORS[op](sys.version_info, required): - continue - - for msg_id in match.group('msgs').split(','): - messages[line, msg_id.strip()] += 1 - return messages - - -def multiset_difference(left_op, right_op): - """Takes two multisets and compares them. - - A multiset is a dict with the cardinality of the key as the value. - - :param left_op: The expected entries. - :param right_op: Actual entries. - - :returns: The two multisets of missing and unexpected messages. - """ - missing = left_op.copy() - missing.subtract(right_op) - unexpected = {} - for key, value in list(six.iteritems(missing)): - if value <= 0: - missing.pop(key) - if value < 0: - unexpected[key] = -value - return missing, unexpected - - -class LintModuleTest(unittest.TestCase): - maxDiff = None - - def __init__(self, test_file): - super(LintModuleTest, self).__init__('_runTest') - test_reporter = TestReporter() - self._linter = lint.PyLinter() - self._linter.set_reporter(test_reporter) - self._linter.config.persistent = 0 - checkers.initialize(self._linter) - self._linter.disable('I') - try: - self._linter.read_config_file(test_file.option_file) - self._linter.load_config_file() - except NoFileError: - pass - self._test_file = test_file - - def setUp(self): - if (sys.version_info < self._test_file.options['min_pyver'] - or sys.version_info >= self._test_file.options['max_pyver']): - self.skipTest( - 'Test cannot run with Python %s.' % (sys.version.split(' ')[0],)) - missing = [] - for req in self._test_file.options['requires']: - try: - __import__(req) - except ImportError: - missing.append(req) - if missing: - self.skipTest('Requires %s to be present.' % (','.join(missing),)) - if self._test_file.options['except_implementations']: - implementations = [ - item.strip() for item in - self._test_file.options['except_implementations'].split(",") - ] - implementation = platform.python_implementation() - if implementation in implementations: - self.skipTest( - 'Test cannot run with Python implementation %r' - % (implementation, )) - - def __str__(self): - return "%s (%s.%s)" % (self._test_file.base, self.__class__.__module__, - self.__class__.__name__) - - def _open_expected_file(self): - return open(self._test_file.expected_output) - - def _open_source_file(self): - if self._test_file.base == "invalid_encoded_data": - return open(self._test_file.source) - else: - return io.open(self._test_file.source, encoding="utf8") - - def _get_expected(self): - with self._open_source_file() as fobj: - expected_msgs = get_expected_messages(fobj) - - if expected_msgs: - with self._open_expected_file() as fobj: - expected_output_lines = parse_expected_output(fobj) - else: - expected_output_lines = [] - return expected_msgs, expected_output_lines - - def _get_received(self): - messages = self._linter.reporter.messages - messages.sort(key=lambda m: (m.line, m.symbol, m.msg)) - received_msgs = collections.Counter() - received_output_lines = [] - for msg in messages: - received_msgs[msg.line, msg.symbol] += 1 - received_output_lines.append(OutputLine.from_msg(msg)) - return received_msgs, received_output_lines - - def _runTest(self): - self._linter.check([self._test_file.module]) - - expected_messages, expected_text = self._get_expected() - received_messages, received_text = self._get_received() - - if expected_messages != received_messages: - msg = ['Wrong results for file "%s":' % (self._test_file.base)] - missing, unexpected = multiset_difference(expected_messages, - received_messages) - if missing: - msg.append('\nExpected in testdata:') - msg.extend(' %3d: %s' % msg for msg in sorted(missing)) - if unexpected: - msg.append('\nUnexpected in testdata:') - msg.extend(' %3d: %s' % msg for msg in sorted(unexpected)) - self.fail('\n'.join(msg)) - self._check_output_text(expected_messages, expected_text, received_text) - - def _split_lines(self, expected_messages, lines): - emitted, omitted = [], [] - for msg in lines: - if (msg[1], msg[0]) in expected_messages: - emitted.append(msg) - else: - omitted.append(msg) - return emitted, omitted - - def _check_output_text(self, expected_messages, expected_lines, - received_lines): - self.assertSequenceEqual( - self._split_lines(expected_messages, expected_lines)[0], - received_lines) - - -class LintModuleOutputUpdate(LintModuleTest): - def _open_expected_file(self): - try: - return super(LintModuleOutputUpdate, self)._open_expected_file() - except IOError: - return io.StringIO() - - def _check_output_text(self, expected_messages, expected_lines, - received_lines): - if not expected_messages: - return - emitted, remaining = self._split_lines(expected_messages, expected_lines) - if emitted != received_lines: - remaining.extend(received_lines) - remaining.sort(key=lambda m: (m[1], m[0], m[3])) - with open(self._test_file.expected_output, 'w') as fobj: - writer = csv.writer(fobj, dialect='test') - for line in remaining: - writer.writerow(line.to_csv()) - -def suite(): - input_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'functional') - suite = unittest.TestSuite() - for fname in os.listdir(input_dir): - if fname != '__init__.py' and fname.endswith('.py'): - test_file = TestFile(input_dir, fname) - if UPDATE: - suite.addTest(LintModuleOutputUpdate(test_file)) - else: - suite.addTest(LintModuleTest(test_file)) - return suite - - -def load_tests(loader, tests, pattern): - return suite() - - -if __name__=='__main__': - if '-u' in sys.argv: - UPDATE = True - sys.argv.remove('-u') - unittest.main(defaultTest='suite') diff --git a/pymode/libs/pylint/test/test_import_graph.py b/pymode/libs/pylint/test/test_import_graph.py deleted file mode 100644 index 441c313c..00000000 --- a/pymode/libs/pylint/test/test_import_graph.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import sys -import os -from os.path import exists -import unittest - -import six - -from pylint.checkers import initialize, imports -from pylint.lint import PyLinter - -from pylint.testutils import TestReporter - -class DependenciesGraphTC(unittest.TestCase): - """test the imports graph function""" - - dest = 'dependencies_graph.dot' - def tearDown(self): - os.remove(self.dest) - - def test_dependencies_graph(self): - imports._dependencies_graph(self.dest, {'labas': ['hoho', 'yep'], - 'hoho': ['yep']}) - with open(self.dest) as stream: - self.assertEqual(stream.read().strip(), - ''' -digraph "dependencies_graph" { -rankdir=LR -charset="utf-8" -URL="." node[shape="box"] -"hoho" []; -"yep" []; -"labas" []; -"yep" -> "hoho" []; -"hoho" -> "labas" []; -"yep" -> "labas" []; -} -'''.strip()) - -class ImportCheckerTC(unittest.TestCase): - def setUp(self): - self.linter = l = PyLinter(reporter=TestReporter()) - initialize(l) - - def test_checker_dep_graphs(self): - l = self.linter - l.global_set_option('persistent', False) - l.global_set_option('enable', 'imports') - l.global_set_option('import-graph', 'import.dot') - l.global_set_option('ext-import-graph', 'ext_import.dot') - l.global_set_option('int-import-graph', 'int_import.dot') - l.global_set_option('int-import-graph', 'int_import.dot') - # ignore this file causing spurious MemoryError w/ some python version (>=2.3?) - l.global_set_option('ignore', ('func_unknown_encoding.py',)) - try: - l.check('input') - l.generate_reports() - self.assertTrue(exists('import.dot')) - self.assertTrue(exists('ext_import.dot')) - self.assertTrue(exists('int_import.dot')) - finally: - for fname in ('import.dot', 'ext_import.dot', 'int_import.dot'): - try: - os.remove(fname) - except: - pass - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/test_regr.py b/pymode/libs/pylint/test/test_regr.py deleted file mode 100644 index 3fd36f48..00000000 --- a/pymode/libs/pylint/test/test_regr.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright (c) 2005-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""non regression tests for pylint, which requires a too specific configuration -to be incorporated in the automatic functional test framework -""" - -import sys -import platform -import os -from os.path import abspath, dirname, join -import unittest - -from pylint.testutils import TestReporter -from pylint.lint import PyLinter -from pylint import checkers -from pylint import epylint - -test_reporter = TestReporter() -linter = PyLinter() -linter.set_reporter(test_reporter) -linter.disable('I') -linter.config.persistent = 0 -checkers.initialize(linter) - -REGR_DATA = join(dirname(abspath(__file__)), 'regrtest_data') -sys.path.insert(1, REGR_DATA) - -class NonRegrTC(unittest.TestCase): - def setUp(self): - """call reporter.finalize() to cleanup - pending messages if a test finished badly - """ - linter.reporter.finalize() - - def test_package___path___manipulation(self): - linter.check('package.__init__') - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_package___init___precedence(self): - linter.check('precedence_test') - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_check_package___init__(self): - for variation in ('package.__init__', join(REGR_DATA, 'package', '__init__.py')): - linter.check(variation) - got = linter.reporter.finalize().strip() - checked = list(linter.stats['by_module'].keys()) - self.assertEqual(checked, ['package.__init__'], - '%s: %s' % (variation, checked)) - cwd = os.getcwd() - os.chdir(join(REGR_DATA, 'package')) - sys.path.insert(0, '') - try: - for variation in ('__init__', '__init__.py'): - linter.check(variation) - got = linter.reporter.finalize().strip() - checked = list(linter.stats['by_module'].keys()) - self.assertEqual(checked, ['__init__'], - '%s: %s' % (variation, checked)) - finally: - sys.path.pop(0) - os.chdir(cwd) - - def test_numarray_inference(self): - try: - from numarray import random_array - except ImportError: - self.skipTest('test skipped: numarray.random_array is not available') - linter.check(join(REGR_DATA, 'numarray_inf.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, "E: 5: Instance of 'int' has no 'astype' member (but some types could not be inferred)") - - def test_numarray_import(self): - try: - import numarray - except ImportError: - self.skipTest('test skipped: numarray is not available') - linter.check(join(REGR_DATA, 'numarray_import.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_class__doc__usage(self): - linter.check(join(REGR_DATA, 'classdoc_usage.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_package_import_relative_subpackage_no_attribute_error(self): - linter.check('import_package_subpackage_module') - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_import_assign_crash(self): - linter.check(join(REGR_DATA, 'import_assign.py')) - - def test_special_attr_scope_lookup_crash(self): - linter.check(join(REGR_DATA, 'special_attr_scope_lookup_crash.py')) - - def test_module_global_crash(self): - linter.check(join(REGR_DATA, 'module_global.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, '') - - def test_decimal_inference(self): - linter.check(join(REGR_DATA, 'decimal_inference.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, "") - - def test_descriptor_crash(self): - for fname in os.listdir(REGR_DATA): - if fname.endswith('_crash.py'): - linter.check(join(REGR_DATA, fname)) - linter.reporter.finalize().strip() - - def test_try_finally_disable_msg_crash(self): - linter.check(join(REGR_DATA, 'try_finally_disable_msg_crash')) - - def test___path__(self): - linter.check('pylint.checkers.__init__') - messages = linter.reporter.finalize().strip() - self.assertFalse('__path__' in messages, messages) - - def test_absolute_import(self): - linter.check(join(REGR_DATA, 'absimp', 'string.py')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, "") - - def test_no_context_file(self): - expected = "Unused import missing" - linter.check(join(REGR_DATA, 'bad_package')) - got = linter.reporter.finalize().strip() - self.assertIn(expected, got) - - def test_epylint_does_not_block_on_huge_files(self): - path = join(REGR_DATA, 'huge.py') - out, err = epylint.py_run(path, return_std=True) - self.assertTrue(hasattr(out, 'read')) - self.assertTrue(hasattr(err, 'read')) - output = out.read(10) - self.assertIsInstance(output, str) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/test_self.py b/pymode/libs/pylint/test/test_self.py deleted file mode 100644 index dbc5983f..00000000 --- a/pymode/libs/pylint/test/test_self.py +++ /dev/null @@ -1,356 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import contextlib -import json -import re -import sys -import os -from os.path import join, dirname, abspath -import tempfile -import textwrap -import unittest -import warnings - -import six - -from pylint.lint import Run -from pylint import __pkginfo__ -from pylint.reporters import BaseReporter -from pylint.reporters.text import * -from pylint.reporters.html import HTMLReporter -from pylint.reporters.json import JSONReporter -from pylint import testutils - -HERE = abspath(dirname(__file__)) - - - -@contextlib.contextmanager -def _patch_streams(out): - sys.stderr = sys.stdout = out - try: - yield - finally: - sys.stderr = sys.__stderr__ - sys.stdout = sys.__stdout__ - - -class MultiReporter(BaseReporter): - def __init__(self, reporters): - self._reporters = reporters - self.path_strip_prefix = os.getcwd() + os.sep - - def on_set_current_module(self, *args, **kwargs): - for rep in self._reporters: - rep.on_set_current_module(*args, **kwargs) - - def handle_message(self, msg): - for rep in self._reporters: - rep.handle_message(msg) - - def display_reports(self, layout): - pass - - @property - def out(self): - return self._reporters[0].out - - @property - def linter(self): - return self._linter - - @linter.setter - def linter(self, value): - self._linter = value - for rep in self._reporters: - rep.linter = value - - -class RunTC(unittest.TestCase): - - def _runtest(self, args, reporter=None, out=None, code=28): - if out is None: - out = six.StringIO() - pylint_code = self._run_pylint(args, reporter=reporter, out=out) - if reporter: - output = reporter.out.getvalue() - elif hasattr(out, 'getvalue'): - output = out.getvalue() - else: - output = None - msg = 'expected output status %s, got %s' % (code, pylint_code) - if output is not None: - msg = '%s. Below pylint output: \n%s' % (msg, output) - self.assertEqual(pylint_code, code, msg) - - def _run_pylint(self, args, out, reporter=None): - args = args + ['--persistent=no'] - with _patch_streams(out): - with self.assertRaises(SystemExit) as cm: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - Run(args, reporter=reporter) - return cm.exception.code - - def _test_output(self, args, expected_output): - out = six.StringIO() - self._run_pylint(args, out=out) - actual_output = out.getvalue() - self.assertIn(expected_output.strip(), actual_output.strip()) - - def test_pkginfo(self): - """Make pylint check itself.""" - self._runtest(['pylint.__pkginfo__'], reporter=TextReporter(six.StringIO()), - code=0) - - def test_all(self): - """Make pylint check itself.""" - with testutils.catch_warnings(): - reporters = [ - TextReporter(six.StringIO()), - HTMLReporter(six.StringIO()), - ColorizedTextReporter(six.StringIO()), - JSONReporter(six.StringIO()) - ] - - self._runtest(['pylint/test/functional/arguments.py'], - reporter=MultiReporter(reporters), code=1) - - def test_no_ext_file(self): - self._runtest([join(HERE, 'input', 'noext')], code=0) - - def test_w0704_ignored(self): - self._runtest([join(HERE, 'input', 'ignore_except_pass_by_default.py')], code=0) - - def test_generate_config_option(self): - self._runtest(['--generate-rcfile'], code=0) - - def test_generate_config_disable_symbolic_names(self): - # Test that --generate-rcfile puts symbolic names in the --disable - # option. - - out = six.StringIO() - self._run_pylint(["--generate-rcfile", "--rcfile="], out=out) - - output = out.getvalue() - # Get rid of the pesky messages that pylint emits if the - # configuration file is not found. - master = re.search("\[MASTER", output) - out = six.StringIO(output[master.start():]) - parser = six.moves.configparser.RawConfigParser() - parser.readfp(out) - messages = parser.get('MESSAGES CONTROL', 'disable').split(",") - self.assertIn('suppressed-message', messages) - - def test_generate_rcfile_no_obsolete_methods(self): - out = six.StringIO() - self._run_pylint(["--generate-rcfile"], out=out) - output = out.getvalue() - self.assertNotIn("profile", output) - - def _test_deprecated_options(self, option, expected): - out = six.StringIO() - self._run_pylint([option, "--rcfile=", "pylint.config"], out=out) - output = out.getvalue() - if __pkginfo__.numversion >= (1, 6, 0): - self.assertIn("no such option", output) - else: - self.assertIn(expected, output) - - def test_deprecated_options_zope(self): - expected = "no such option" - self._test_deprecated_options("--zope=y", expected) - - def test_deprecated_options_symbols(self): - expected = "no such option" - self._test_deprecated_options("--symbols=y", expected) - - def test_deprecated_options_include_ids(self): - expected = "no such option" - self._test_deprecated_options("--include-ids=y", expected) - - def test_deprecated_options_profile(self): - expected = "no such option" - self._test_deprecated_options("--profile=y", expected) - - def test_help_message_option(self): - self._runtest(['--help-msg', 'W0101'], code=0) - - def test_error_help_message_option(self): - self._runtest(['--help-msg', 'WX101'], code=0) - - def test_error_missing_arguments(self): - self._runtest([], code=32) - - def test_no_out_encoding(self): - """test redirection of stdout with non ascii caracters - """ - #This test reproduces bug #48066 ; it happens when stdout is redirected - # through '>' : the sys.stdout.encoding becomes then None, and if the - # output contains non ascii, pylint will crash - if sys.version_info < (3, 0): - strio = tempfile.TemporaryFile() - else: - strio = six.StringIO() - assert strio.encoding is None - self._runtest([join(HERE, 'regrtest_data/no_stdout_encoding.py')], - out=strio) - - def test_parallel_execution(self): - self._runtest(['-j 2', 'pylint/test/functional/arguments.py', - 'pylint/test/functional/bad_continuation.py'], code=1) - - def test_parallel_execution_missing_arguments(self): - self._runtest(['-j 2', 'not_here', 'not_here_too'], code=1) - - def test_py3k_option(self): - # Test that --py3k flag works. - rc_code = 2 if six.PY2 else 0 - self._runtest([join(HERE, 'functional', 'unpacked_exceptions.py'), - '--py3k'], - code=rc_code) - - def test_py3k_jobs_option(self): - rc_code = 2 if six.PY2 else 0 - self._runtest([join(HERE, 'functional', 'unpacked_exceptions.py'), - '--py3k', '-j 2'], - code=rc_code) - - @unittest.skipIf(sys.version_info[0] > 2, "Requires the --py3k flag.") - def test_py3k_commutative_with_errors_only(self): - - # Test what gets emitted with -E only - module = join(HERE, 'regrtest_data', 'py3k_error_flag.py') - expected = textwrap.dedent(""" - No config file found, using default configuration - ************* Module py3k_error_flag - Explicit return in __init__ - """) - self._test_output([module, "-E", "--msg-template='{msg}'"], - expected_output=expected) - - # Test what gets emitted with -E --py3k - expected = textwrap.dedent(""" - No config file found, using default configuration - ************* Module py3k_error_flag - Use raise ErrorClass(args) instead of raise ErrorClass, args. - """) - self._test_output([module, "-E", "--py3k", "--msg-template='{msg}'"], - expected_output=expected) - - # Test what gets emitted with --py3k -E - self._test_output([module, "--py3k", "-E", "--msg-template='{msg}'"], - expected_output=expected) - - def test_abbreviations_are_not_supported(self): - expected = "no such option: --load-plugin" - self._test_output([".", "--load-plugin"], expected_output=expected) - - def test_enable_all_works(self): - module = join(HERE, 'data', 'clientmodule_test.py') - expected = textwrap.dedent(""" - No config file found, using default configuration - ************* Module data.clientmodule_test - W: 10, 8: Unused variable 'local_variable' (unused-variable) - C: 18, 4: Missing method docstring (missing-docstring) - C: 22, 0: Missing class docstring (missing-docstring) - """) - self._test_output([module, "--disable=all", "--enable=all", "-rn"], - expected_output=expected) - - def test_html_crash_report(self): - out = six.StringIO() - module = join(HERE, 'regrtest_data', 'html_crash_420.py') - with testutils.catch_warnings(): - self._runtest([module], code=16, reporter=HTMLReporter(out)) - - def test_wrong_import_position_when_others_disabled(self): - expected_output = textwrap.dedent(''' - No config file found, using default configuration - ************* Module wrong_import_position - C: 11, 0: Import "import os" should be placed at the top of the module (wrong-import-position) - ''') - module1 = join(HERE, 'regrtest_data', 'import_something.py') - module2 = join(HERE, 'regrtest_data', 'wrong_import_position.py') - args = [module2, module1, - "--disable=all", "--enable=wrong-import-position", - "-rn"] - out = six.StringIO() - self._run_pylint(args, out=out) - actual_output = out.getvalue() - self.assertEqual(expected_output.strip(), actual_output.strip()) - - def test_import_itself_not_accounted_for_relative_imports(self): - expected = 'No config file found, using default configuration' - package = join(HERE, 'regrtest_data', 'dummy') - self._test_output([package, '--disable=locally-disabled', '-rn'], - expected_output=expected) - - - def test_json_report_when_file_has_syntax_error(self): - out = six.StringIO() - module = join(HERE, 'regrtest_data', 'syntax_error.py') - self._runtest([module], code=2, reporter=JSONReporter(out)) - output = json.loads(out.getvalue()) - self.assertIsInstance(output, list) - self.assertEqual(len(output), 1) - self.assertIsInstance(output[0], dict) - expected = { - "obj": "", - "column": 0, - "line": 1, - "type": "error", - "symbol": "syntax-error", - "module": "syntax_error" - } - message = output[0] - for key, value in expected.items(): - self.assertIn(key, message) - self.assertEqual(message[key], value) - self.assertIn("invalid syntax", message["message"].lower()) - - def test_json_report_when_file_is_missing(self): - out = six.StringIO() - module = join(HERE, 'regrtest_data', 'totally_missing.py') - self._runtest([module], code=1, reporter=JSONReporter(out)) - output = json.loads(out.getvalue()) - self.assertIsInstance(output, list) - self.assertEqual(len(output), 1) - self.assertIsInstance(output[0], dict) - expected = { - "obj": "", - "column": 0, - "line": 1, - "type": "fatal", - "symbol": "fatal", - "module": module - } - message = output[0] - for key, value in expected.items(): - self.assertIn(key, message) - self.assertEqual(message[key], value) - self.assertTrue(message['message'].startswith("No module named")) - - def test_confidence_levels(self): - expected = 'No config file found, using default configuration' - path = join(HERE, 'regrtest_data', 'meta.py') - self._test_output([path, "--confidence=HIGH,INFERENCE"], - expected_output=expected) - - def test_bom_marker(self): - path = join(HERE, 'regrtest_data', 'meta.py') - config_path = join(HERE, 'regrtest_data', '.pylintrc') - expected = 'Your code has been rated at 10.00/10' - self._test_output([path, "--rcfile=%s" % config_path], - expected_output=expected) - - def test_no_crash_with_formatting_regex_defaults(self): - self._runtest(["--ignore-patterns=a"], reporter=TextReporter(six.StringIO()), - code=32) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_base.py b/pymode/libs/pylint/test/unittest_checker_base.py deleted file mode 100644 index b747a162..00000000 --- a/pymode/libs/pylint/test/unittest_checker_base.py +++ /dev/null @@ -1,319 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unittest for the base checker.""" - -import re -import unittest - -import astroid -from astroid import test_utils -from pylint.checkers import base -from pylint.testutils import CheckerTestCase, Message, set_config - - -class DocstringTest(CheckerTestCase): - CHECKER_CLASS = base.DocStringChecker - - def test_missing_docstring_module(self): - module = astroid.parse("something") - message = Message('missing-docstring', node=module, args=('module',)) - with self.assertAddsMessages(message): - self.checker.visit_module(module) - - def test_missing_docstring_emtpy_module(self): - module = astroid.parse("") - with self.assertNoMessages(): - self.checker.visit_module(module) - - def test_empty_docstring_module(self): - module = astroid.parse("''''''") - message = Message('empty-docstring', node=module, args=('module',)) - with self.assertAddsMessages(message): - self.checker.visit_module(module) - - def test_empty_docstring_function(self): - func = test_utils.extract_node(""" - def func(tion): - pass""") - message = Message('missing-docstring', node=func, args=('function',)) - with self.assertAddsMessages(message): - self.checker.visit_functiondef(func) - - @set_config(docstring_min_length=2) - def test_short_function_no_docstring(self): - func = test_utils.extract_node(""" - def func(tion): - pass""") - with self.assertNoMessages(): - self.checker.visit_functiondef(func) - - @set_config(docstring_min_length=2) - def test_function_no_docstring_by_name(self): - func = test_utils.extract_node(""" - def __fun__(tion): - pass""") - with self.assertNoMessages(): - self.checker.visit_functiondef(func) - - def test_class_no_docstring(self): - klass = test_utils.extract_node(""" - class Klass(object): - pass""") - message = Message('missing-docstring', node=klass, args=('class',)) - with self.assertAddsMessages(message): - self.checker.visit_classdef(klass) - - -class NameCheckerTest(CheckerTestCase): - CHECKER_CLASS = base.NameChecker - CONFIG = { - 'bad_names': set(), - } - - @set_config(include_naming_hint=True) - def test_naming_hint(self): - const = test_utils.extract_node(""" - const = "CONSTANT" #@ - """) - message = Message( - 'invalid-name', node=const.targets[0], - args=('constant', 'const', - ' (hint: (([A-Z_][A-Z0-9_]*)|(__.*__))$)')) - with self.assertAddsMessages(message): - self.checker.visit_assignname(const.targets[0]) - - @set_config(include_naming_hint=True, const_name_hint='CONSTANT') - def test_naming_hint_configured_hint(self): - const = test_utils.extract_node(""" - const = "CONSTANT" #@ - """) - with self.assertAddsMessages( - Message('invalid-name', node=const.targets[0], - args=('constant', 'const', ' (hint: CONSTANT)'))): - self.checker.visit_assignname(const.targets[0]) - - @set_config(attr_rgx=re.compile('[A-Z]+'), - property_classes=('abc.abstractproperty', '.custom_prop')) - def test_property_names(self): - # If a method is annotated with @property, it's name should - # match the attr regex. Since by default the attribute regex is the same - # as the method regex, we override it here. - methods = test_utils.extract_node(""" - import abc - - def custom_prop(f): - return property(f) - - class FooClass(object): - @property - def FOO(self): #@ - pass - - @property - def bar(self): #@ - pass - - @abc.abstractproperty - def BAZ(self): #@ - pass - - @custom_prop - def QUX(self): #@ - pass - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(methods[0]) - self.checker.visit_functiondef(methods[2]) - self.checker.visit_functiondef(methods[3]) - with self.assertAddsMessages(Message('invalid-name', node=methods[1], - args=('attribute', 'bar', ''))): - self.checker.visit_functiondef(methods[1]) - - @set_config(attr_rgx=re.compile('[A-Z]+')) - def test_property_setters(self): - method = test_utils.extract_node(""" - class FooClass(object): - @property - def foo(self): pass - - @foo.setter - def FOOSETTER(self): #@ - pass - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(method) - - def test_module_level_names(self): - assign = test_utils.extract_node(""" - import collections - Class = collections.namedtuple("a", ("b", "c")) #@ - """) - with self.assertNoMessages(): - self.checker.visit_assignname(assign.targets[0]) - - assign = test_utils.extract_node(""" - class ClassA(object): - pass - ClassB = ClassA - """) - with self.assertNoMessages(): - self.checker.visit_assignname(assign.targets[0]) - - module = astroid.parse(""" - def A(): - return 1, 2, 3 - CONSTA, CONSTB, CONSTC = A() - CONSTD = A()""") - with self.assertNoMessages(): - self.checker.visit_assignname(module.body[1].targets[0].elts[0]) - self.checker.visit_assignname(module.body[2].targets[0]) - - assign = test_utils.extract_node(""" - CONST = "12 34 ".rstrip().split()""") - with self.assertNoMessages(): - self.checker.visit_assignname(assign.targets[0]) - - -class MultiNamingStyleTest(CheckerTestCase): - CHECKER_CLASS = base.NameChecker - - MULTI_STYLE_RE = re.compile('(?:(?P[A-Z]+)|(?P[a-z]+))$') - - @set_config(class_rgx=MULTI_STYLE_RE) - def test_multi_name_detection_majority(self): - classes = test_utils.extract_node(""" - class classb(object): #@ - pass - class CLASSA(object): #@ - pass - class CLASSC(object): #@ - pass - """) - message = Message('invalid-name', - node=classes[0], - args=('class', 'classb', '')) - with self.assertAddsMessages(message): - for cls in classes: - self.checker.visit_classdef(cls) - self.checker.leave_module(cls.root) - - @set_config(class_rgx=MULTI_STYLE_RE) - def test_multi_name_detection_first_invalid(self): - classes = test_utils.extract_node(""" - class class_a(object): #@ - pass - class classb(object): #@ - pass - class CLASSC(object): #@ - pass - """) - messages = [ - Message('invalid-name', node=classes[0], - args=('class', 'class_a', '')), - Message('invalid-name', node=classes[2], - args=('class', 'CLASSC', '')) - ] - with self.assertAddsMessages(*messages): - for cls in classes: - self.checker.visit_classdef(cls) - self.checker.leave_module(cls.root) - - @set_config(method_rgx=MULTI_STYLE_RE, - function_rgx=MULTI_STYLE_RE, - name_group=('function:method',)) - def test_multi_name_detection_group(self): - function_defs = test_utils.extract_node(""" - class First(object): - def func(self): #@ - pass - - def FUNC(): #@ - pass - """, module_name='test') - message = Message('invalid-name', node=function_defs[1], - args=('function', 'FUNC', '')) - with self.assertAddsMessages(message): - for func in function_defs: - self.checker.visit_functiondef(func) - self.checker.leave_module(func.root) - - @set_config(function_rgx=re.compile('(?:(?PFOO)|(?P[A-Z]+)|(?P[a-z]+))$')) - def test_multi_name_detection_exempt(self): - function_defs = test_utils.extract_node(""" - def FOO(): #@ - pass - def lower(): #@ - pass - def FOO(): #@ - pass - def UPPER(): #@ - pass - """) - message = Message('invalid-name', node=function_defs[3], - args=('function', 'UPPER', '')) - with self.assertAddsMessages(message): - for func in function_defs: - self.checker.visit_functiondef(func) - self.checker.leave_module(func.root) - -class ComparisonTest(CheckerTestCase): - CHECKER_CLASS = base.ComparisonChecker - - def test_comparison(self): - node = test_utils.extract_node("foo == True") - message = Message('singleton-comparison', - node=node, - args=(True, "just 'expr' or 'expr is True'")) - with self.assertAddsMessages(message): - self.checker.visit_compare(node) - - node = test_utils.extract_node("foo == False") - message = Message('singleton-comparison', - node=node, - args=(False, "'not expr' or 'expr is False'")) - with self.assertAddsMessages(message): - self.checker.visit_compare(node) - - node = test_utils.extract_node("foo == None") - message = Message('singleton-comparison', - node=node, - args=(None, "'expr is None'")) - with self.assertAddsMessages(message): - self.checker.visit_compare(node) - - node = test_utils.extract_node("True == foo") - messages = (Message('misplaced-comparison-constant', - node=node, - args=('foo == True',)), - Message('singleton-comparison', - node=node, - args=(True, "just 'expr' or 'expr is True'"))) - with self.assertAddsMessages(*messages): - self.checker.visit_compare(node) - - node = test_utils.extract_node("False == foo") - messages = (Message('misplaced-comparison-constant', - node=node, - args=('foo == False',)), - Message('singleton-comparison', - node=node, - args=(False, "'not expr' or 'expr is False'"))) - with self.assertAddsMessages(*messages): - self.checker.visit_compare(node) - - node = test_utils.extract_node("None == foo") - messages = (Message('misplaced-comparison-constant', - node=node, - args=('foo == None',)), - Message('singleton-comparison', - node=node, - args=(None, "'expr is None'"))) - with self.assertAddsMessages(*messages): - self.checker.visit_compare(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_classes.py b/pymode/libs/pylint/test/unittest_checker_classes.py deleted file mode 100644 index f3f0a5ca..00000000 --- a/pymode/libs/pylint/test/unittest_checker_classes.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the variables checker.""" -import unittest -import sys - -import astroid -from astroid import test_utils -from pylint.checkers import classes -from pylint.testutils import CheckerTestCase, Message, set_config - -class VariablesCheckerTC(CheckerTestCase): - - CHECKER_CLASS = classes.ClassChecker - - def test_bitbucket_issue_164(self): - """Issue 164 report a false negative for access-member-before-definition""" - n1, n2 = test_utils.extract_node(""" - class MyClass1(object): - def __init__(self): - self.first += 5 #@ - self.first = 0 #@ - """) - message = Message('access-member-before-definition', - node=n1.target, args=('first', n2.lineno)) - with self.assertAddsMessages(message): - self.walk(n1.root()) - - @set_config(exclude_protected=('_meta', '_manager')) - def test_exclude_protected(self): - """Test that exclude-protected can be used to - exclude names from protected-access warning. - """ - - node = astroid.parse(""" - class Protected(object): - '''empty''' - def __init__(self): - self._meta = 42 - self._manager = 24 - self._teta = 29 - OBJ = Protected() - OBJ._meta - OBJ._manager - OBJ._teta - """) - with self.assertAddsMessages( - Message('protected-access', - node=node.body[-1].value, - args='_teta')): - self.walk(node.root()) - - @unittest.skipUnless(sys.version_info[0] == 3, - "The test works on Python 3.") - def test_regression_non_parent_init_called_tracemalloc(self): - # This used to raise a non-parent-init-called on Pylint 1.3 - # See issue https://bitbucket.org/logilab/pylint/issue/308/ - # for reference. - node = test_utils.extract_node(""" - from tracemalloc import Sequence - class _Traces(Sequence): - def __init__(self, traces): #@ - Sequence.__init__(self) - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - def test_super_init_not_called_regression(self): - # This should not emit a super-init-not-called - # warning. It previously did this, because - # ``next(node.infer())`` was used in that checker's - # logic and the first inferred node was an YES object, - # leading to this false positive. - node = test_utils.extract_node(""" - import ctypes - - class Foo(ctypes.BigEndianStructure): - def __init__(self): #@ - ctypes.BigEndianStructure.__init__(self) - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_exceptions.py b/pymode/libs/pylint/test/unittest_checker_exceptions.py deleted file mode 100644 index 34827625..00000000 --- a/pymode/libs/pylint/test/unittest_checker_exceptions.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for pylint.checkers.exceptions.""" - -import sys -import unittest - -from astroid import test_utils -from pylint.checkers import exceptions -from pylint.testutils import CheckerTestCase, Message - - -class ExceptionsCheckerTest(CheckerTestCase): - """Tests for pylint.checkers.exceptions.""" - - CHECKER_CLASS = exceptions.ExceptionsChecker - - # These tests aren't in the functional test suite, - # since they will be converted with 2to3 for Python 3 - # and `raise (Error, ...)` will be converted to - # `raise Error(...)`, so it beats the purpose of the test. - - @unittest.skipUnless(sys.version_info[0] == 3, - "The test should emit an error on Python 3.") - def test_raising_bad_type_python3(self): - node = test_utils.extract_node('raise (ZeroDivisionError, None) #@') - message = Message('raising-bad-type', node=node, args='tuple') - with self.assertAddsMessages(message): - self.checker.visit_raise(node) - - @unittest.skipUnless(sys.version_info[0] == 2, - "The test is valid only on Python 2.") - def test_raising_bad_type_python2(self): - nodes = test_utils.extract_node(''' - raise (ZeroDivisionError, None) #@ - from something import something - raise (something, None) #@ - - raise (4, None) #@ - raise () #@ - ''') - with self.assertNoMessages(): - self.checker.visit_raise(nodes[0]) - with self.assertNoMessages(): - self.checker.visit_raise(nodes[1]) - - message = Message('raising-bad-type', node=nodes[2], args='tuple') - with self.assertAddsMessages(message): - self.checker.visit_raise(nodes[2]) - message = Message('raising-bad-type', node=nodes[3], args='tuple') - with self.assertAddsMessages(message): - self.checker.visit_raise(nodes[3]) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_format.py b/pymode/libs/pylint/test/unittest_checker_format.py deleted file mode 100644 index 78ec81f7..00000000 --- a/pymode/libs/pylint/test/unittest_checker_format.py +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Check format checker helper functions""" - -from __future__ import unicode_literals - -import astroid -from astroid import test_utils - -from pylint.checkers.format import * - -from pylint.testutils import ( - CheckerTestCase, Message, set_config, tokenize_str, -) - - -class MultiStatementLineTest(CheckerTestCase): - CHECKER_CLASS = FormatChecker - - def testSingleLineIfStmts(self): - stmt = test_utils.extract_node(""" - if True: pass #@ - """) - with self.assertAddsMessages(Message('multiple-statements', node=stmt.body[0])): - self.checker.process_tokens([]) - self.checker.visit_default(stmt.body[0]) - self.checker.config.single_line_if_stmt = True - with self.assertNoMessages(): - self.checker.process_tokens([]) - self.checker.visit_default(stmt.body[0]) - stmt = test_utils.extract_node(""" - if True: pass #@ - else: - pass - """) - with self.assertAddsMessages(Message('multiple-statements', node=stmt.body[0])): - self.checker.process_tokens([]) - self.checker.visit_default(stmt.body[0]) - - def testTryExceptFinallyNoMultipleStatement(self): - tree = test_utils.extract_node(""" - try: #@ - pass - except: - pass - finally: - pass""") - with self.assertNoMessages(): - self.checker.process_tokens([]) - self.checker.visit_default(tree.body[0]) - - - -class SuperfluousParenthesesTest(CheckerTestCase): - CHECKER_CLASS = FormatChecker - - def testCheckKeywordParensHandlesValidCases(self): - self.checker._keywords_with_parens = set() - cases = [ - 'if foo:', - 'if foo():', - 'if (x and y) or z:', - 'assert foo()', - 'assert ()', - 'if (1, 2) in (3, 4):', - 'if (a or b) in c:', - 'return (x for x in x)', - 'if (x for x in x):', - 'for x in (x for x in x):', - 'not (foo or bar)', - 'not (foo or bar) and baz', - ] - with self.assertNoMessages(): - for code in cases: - self.checker._check_keyword_parentheses(tokenize_str(code), 0) - - def testCheckKeywordParensHandlesUnnecessaryParens(self): - self.checker._keywords_with_parens = set() - cases = [ - (Message('superfluous-parens', line=1, args='if'), - 'if (foo):', 0), - (Message('superfluous-parens', line=1, args='if'), - 'if ((foo, bar)):', 0), - (Message('superfluous-parens', line=1, args='if'), - 'if (foo(bar)):', 0), - (Message('superfluous-parens', line=1, args='return'), - 'return ((x for x in x))', 0), - (Message('superfluous-parens', line=1, args='not'), - 'not (foo)', 0), - (Message('superfluous-parens', line=1, args='not'), - 'if not (foo):', 1), - (Message('superfluous-parens', line=1, args='if'), - 'if (not (foo)):', 0), - (Message('superfluous-parens', line=1, args='not'), - 'if (not (foo)):', 2), - ] - for msg, code, offset in cases: - with self.assertAddsMessages(msg): - self.checker._check_keyword_parentheses(tokenize_str(code), offset) - - def testFuturePrintStatementWithoutParensWarning(self): - code = """from __future__ import print_function -print('Hello world!') -""" - tree = astroid.parse(code) - with self.assertNoMessages(): - self.checker.process_module(tree) - self.checker.process_tokens(tokenize_str(code)) - - -class CheckSpaceTest(CheckerTestCase): - CHECKER_CLASS = FormatChecker - - def testParenthesesGood(self): - good_cases = [ - '(a)\n', - '(a * (b + c))\n', - '(#\n a)\n', - ] - with self.assertNoMessages(): - for code in good_cases: - self.checker.process_tokens(tokenize_str(code)) - - def testParenthesesBad(self): - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'after', 'bracket', '( a)\n^'))): - self.checker.process_tokens(tokenize_str('( a)\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'bracket', '(a )\n ^'))): - self.checker.process_tokens(tokenize_str('(a )\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'bracket', 'foo (a)\n ^'))): - self.checker.process_tokens(tokenize_str('foo (a)\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'bracket', '{1: 2} [1]\n ^'))): - self.checker.process_tokens(tokenize_str('{1: 2} [1]\n')) - - def testTrailingCommaGood(self): - with self.assertNoMessages(): - self.checker.process_tokens(tokenize_str('(a, )\n')) - self.checker.process_tokens(tokenize_str('(a,)\n')) - - self.checker.config.no_space_check = [] - with self.assertNoMessages(): - self.checker.process_tokens(tokenize_str('(a,)\n')) - - @set_config(no_space_check=[]) - def testTrailingCommaBad(self): - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'bracket', '(a, )\n ^'))): - self.checker.process_tokens(tokenize_str('(a, )\n')) - - def testComma(self): - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'comma', '(a , b)\n ^'))): - self.checker.process_tokens(tokenize_str('(a , b)\n')) - - def testSpacesAllowedInsideSlices(self): - good_cases = [ - '[a:b]\n', - '[a : b]\n', - '[a : ]\n', - '[:a]\n', - '[:]\n', - '[::]\n', - ] - with self.assertNoMessages(): - for code in good_cases: - self.checker.process_tokens(tokenize_str(code)) - - def testKeywordSpacingGood(self): - with self.assertNoMessages(): - self.checker.process_tokens(tokenize_str('foo(foo=bar)\n')) - self.checker.process_tokens(tokenize_str('lambda x=1: x\n')) - - def testKeywordSpacingBad(self): - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'before', 'keyword argument assignment', - '(foo =bar)\n ^'))): - self.checker.process_tokens(tokenize_str('(foo =bar)\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'after', 'keyword argument assignment', - '(foo= bar)\n ^'))): - self.checker.process_tokens(tokenize_str('(foo= bar)\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('No', 'allowed', 'around', 'keyword argument assignment', - '(foo = bar)\n ^'))): - self.checker.process_tokens(tokenize_str('(foo = bar)\n')) - - def testOperatorSpacingGood(self): - good_cases = [ - 'a = b\n' - 'a < b\n' - 'a\n< b\n', - ] - with self.assertNoMessages(): - for code in good_cases: - self.checker.process_tokens(tokenize_str(code)) - - def testOperatorSpacingBad(self): - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('Exactly one', 'required', 'before', 'comparison', 'a< b\n ^'))): - self.checker.process_tokens(tokenize_str('a< b\n')) - - with self.assertAddsMessages( - Message('bad-whitespace', line=1, - args=('Exactly one', 'required', 'after', 'comparison', 'a 2, 'Python 2 only')(test) - -# TODO(cpopa): Port these to the functional test framework instead. - -class Python3CheckerTest(testutils.CheckerTestCase): - CHECKER_CLASS = checker.Python3Checker - - def check_bad_builtin(self, builtin_name): - node = test_utils.extract_node(builtin_name + ' #@') - message = builtin_name.lower() + '-builtin' - with self.assertAddsMessages(testutils.Message(message, node=node)): - self.checker.visit_name(node) - - @python2_only - def test_bad_builtins(self): - builtins = [ - 'apply', - 'buffer', - 'cmp', - 'coerce', - 'execfile', - 'file', - 'input', - 'intern', - 'long', - 'raw_input', - 'round', - 'reduce', - 'StandardError', - 'unichr', - 'unicode', - 'xrange', - 'reload', - ] - for builtin in builtins: - self.check_bad_builtin(builtin) - - def as_iterable_in_for_loop_test(self, fxn): - code = "for x in {}(): pass".format(fxn) - module = astroid.parse(code) - with self.assertNoMessages(): - self.walk(module) - - def as_used_by_iterable_in_for_loop_test(self, fxn): - checker = '{}-builtin-not-iterating'.format(fxn) - node = test_utils.extract_node(""" - for x in (whatever( - {}() #@ - )): - pass - """.format(fxn)) - message = testutils.Message(checker, node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def as_iterable_in_genexp_test(self, fxn): - code = "x = (x for x in {}())".format(fxn) - module = astroid.parse(code) - with self.assertNoMessages(): - self.walk(module) - - def as_iterable_in_listcomp_test(self, fxn): - code = "x = [x for x in {}(None, [1])]".format(fxn) - module = astroid.parse(code) - with self.assertNoMessages(): - self.walk(module) - - def as_used_in_variant_in_genexp_test(self, fxn): - checker = '{}-builtin-not-iterating'.format(fxn) - node = test_utils.extract_node(""" - list( - __({}(x)) - for x in [1] - ) - """.format(fxn)) - message = testutils.Message(checker, node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def as_used_in_variant_in_listcomp_test(self, fxn): - checker = '{}-builtin-not-iterating'.format(fxn) - node = test_utils.extract_node(""" - [ - __({}(None, x)) - for x in [[1]]] - """.format(fxn)) - message = testutils.Message(checker, node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def as_argument_to_callable_constructor_test(self, fxn, callable_fn): - module = astroid.parse("x = {}({}())".format(callable_fn, fxn)) - with self.assertNoMessages(): - self.walk(module) - - def as_argument_to_random_fxn_test(self, fxn): - checker = '{}-builtin-not-iterating'.format(fxn) - node = test_utils.extract_node(""" - y( - {}() #@ - ) - """.format(fxn)) - message = testutils.Message(checker, node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def as_argument_to_str_join_test(self, fxn): - code = "x = ''.join({}())".format(fxn) - module = astroid.parse(code) - with self.assertNoMessages(): - self.walk(module) - - def as_iterable_in_unpacking(self, fxn): - node = test_utils.extract_node(""" - a, b = __({}()) - """.format(fxn)) - with self.assertNoMessages(): - self.checker.visit_call(node) - - def as_assignment(self, fxn): - checker = '{}-builtin-not-iterating'.format(fxn) - node = test_utils.extract_node(""" - a = __({}()) - """.format(fxn)) - message = testutils.Message(checker, node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def iterating_context_tests(self, fxn): - """Helper for verifying a function isn't used as an iterator.""" - self.as_iterable_in_for_loop_test(fxn) - self.as_used_by_iterable_in_for_loop_test(fxn) - self.as_iterable_in_genexp_test(fxn) - self.as_iterable_in_listcomp_test(fxn) - self.as_used_in_variant_in_genexp_test(fxn) - self.as_used_in_variant_in_listcomp_test(fxn) - self.as_argument_to_random_fxn_test(fxn) - self.as_argument_to_str_join_test(fxn) - self.as_iterable_in_unpacking(fxn) - self.as_assignment(fxn) - - for func in ('iter', 'list', 'tuple', 'sorted', - 'set', 'sum', 'any', 'all', - 'enumerate', 'dict'): - self.as_argument_to_callable_constructor_test(fxn, func) - - @python2_only - def test_map_in_iterating_context(self): - self.iterating_context_tests('map') - - @python2_only - def test_zip_in_iterating_context(self): - self.iterating_context_tests('zip') - - @python2_only - def test_range_in_iterating_context(self): - self.iterating_context_tests('range') - - @python2_only - def test_filter_in_iterating_context(self): - self.iterating_context_tests('filter') - - def defined_method_test(self, method, warning): - """Helper for verifying that a certain method is not defined.""" - node = test_utils.extract_node(""" - class Foo(object): - def __{0}__(self, other): #@ - pass""".format(method)) - message = testutils.Message(warning, node=node) - with self.assertAddsMessages(message): - self.checker.visit_functiondef(node) - - def test_delslice_method(self): - self.defined_method_test('delslice', 'delslice-method') - - def test_getslice_method(self): - self.defined_method_test('getslice', 'getslice-method') - - def test_setslice_method(self): - self.defined_method_test('setslice', 'setslice-method') - - def test_coerce_method(self): - self.defined_method_test('coerce', 'coerce-method') - - def test_oct_method(self): - self.defined_method_test('oct', 'oct-method') - - def test_hex_method(self): - self.defined_method_test('hex', 'hex-method') - - def test_nonzero_method(self): - self.defined_method_test('nonzero', 'nonzero-method') - - def test_cmp_method(self): - self.defined_method_test('cmp', 'cmp-method') - - @python2_only - def test_print_statement(self): - node = test_utils.extract_node('print "Hello, World!" #@') - message = testutils.Message('print-statement', node=node) - with self.assertAddsMessages(message): - self.checker.visit_print(node) - - @python2_only - def test_backtick(self): - node = test_utils.extract_node('`test`') - message = testutils.Message('backtick', node=node) - with self.assertAddsMessages(message): - self.checker.visit_repr(node) - - def test_relative_import(self): - node = test_utils.extract_node('import string #@') - message = testutils.Message('no-absolute-import', node=node) - with self.assertAddsMessages(message): - self.checker.visit_import(node) - - def test_relative_from_import(self): - node = test_utils.extract_node('from os import path #@') - message = testutils.Message('no-absolute-import', node=node) - with self.assertAddsMessages(message): - self.checker.visit_import(node) - - def test_absolute_import(self): - module_import = astroid.parse( - 'from __future__ import absolute_import; import os') - module_from = astroid.parse( - 'from __future__ import absolute_import; from os import path') - with self.assertNoMessages(): - for module in (module_import, module_from): - self.walk(module) - - def test_import_star_module_level(self): - node = test_utils.extract_node(''' - def test(): - from lala import * #@ - ''') - absolute = testutils.Message('no-absolute-import', node=node) - star = testutils.Message('import-star-module-level', node=node) - with self.assertAddsMessages(absolute, star): - self.checker.visit_importfrom(node) - - def test_division(self): - node = test_utils.extract_node('3 / 2 #@') - message = testutils.Message('old-division', node=node) - with self.assertAddsMessages(message): - self.checker.visit_binop(node) - - def test_division_with_future_statement(self): - module = astroid.parse('from __future__ import division; 3 / 2') - with self.assertNoMessages(): - self.walk(module) - - def test_floor_division(self): - node = test_utils.extract_node(' 3 // 2 #@') - with self.assertNoMessages(): - self.checker.visit_binop(node) - - def test_division_by_float(self): - left_node = test_utils.extract_node('3.0 / 2 #@') - right_node = test_utils.extract_node(' 3 / 2.0 #@') - with self.assertNoMessages(): - for node in (left_node, right_node): - self.checker.visit_binop(node) - - def test_dict_iter_method(self): - for meth in ('keys', 'values', 'items'): - node = test_utils.extract_node('x.iter%s() #@' % meth) - message = testutils.Message('dict-iter-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def test_dict_iter_method_on_dict(self): - node = test_utils.extract_node('{}.iterkeys()') - message = testutils.Message('dict-iter-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def test_dict_not_iter_method(self): - arg_node = test_utils.extract_node('x.iterkeys(x) #@') - stararg_node = test_utils.extract_node('x.iterkeys(*x) #@') - kwarg_node = test_utils.extract_node('x.iterkeys(y=x) #@') - non_dict_node = test_utils.extract_node('x=[]\nx.iterkeys() #@') - with self.assertNoMessages(): - for node in (arg_node, stararg_node, kwarg_node, non_dict_node): - self.checker.visit_call(node) - - def test_dict_view_method(self): - for meth in ('keys', 'values', 'items'): - node = test_utils.extract_node('x.view%s() #@' % meth) - message = testutils.Message('dict-view-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def test_dict_view_method_on_dict(self): - node = test_utils.extract_node('{}.viewkeys()') - message = testutils.Message('dict-view-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def test_dict_not_view_method(self): - arg_node = test_utils.extract_node('x.viewkeys(x) #@') - stararg_node = test_utils.extract_node('x.viewkeys(*x) #@') - kwarg_node = test_utils.extract_node('x.viewkeys(y=x) #@') - non_dict_node = test_utils.extract_node('x=[]\nx.viewkeys() #@') - with self.assertNoMessages(): - for node in (arg_node, stararg_node, kwarg_node, non_dict_node): - self.checker.visit_call(node) - - def test_next_method(self): - node = test_utils.extract_node('x.next() #@') - message = testutils.Message('next-method-called', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - def test_not_next_method(self): - arg_node = test_utils.extract_node('x.next(x) #@') - stararg_node = test_utils.extract_node('x.next(*x) #@') - kwarg_node = test_utils.extract_node('x.next(y=x) #@') - with self.assertNoMessages(): - for node in (arg_node, stararg_node, kwarg_node): - self.checker.visit_call(node) - - def test_metaclass_assignment(self): - node = test_utils.extract_node(""" - class Foo(object): #@ - __metaclass__ = type""") - message = testutils.Message('metaclass-assignment', node=node) - with self.assertAddsMessages(message): - self.checker.visit_classdef(node) - - def test_metaclass_global_assignment(self): - module = astroid.parse('__metaclass__ = type') - with self.assertNoMessages(): - self.walk(module) - - @python2_only - def test_parameter_unpacking(self): - node = test_utils.extract_node('def func((a, b)):#@\n pass') - arg = node.args.args[0] - with self.assertAddsMessages(testutils.Message('parameter-unpacking', node=arg)): - self.checker.visit_arguments(node.args) - - @python2_only - def test_old_raise_syntax(self): - node = test_utils.extract_node('raise Exception, "test"') - message = testutils.Message('old-raise-syntax', node=node) - with self.assertAddsMessages(message): - self.checker.visit_raise(node) - - @python2_only - def test_raising_string(self): - node = test_utils.extract_node('raise "Test"') - message = testutils.Message('raising-string', node=node) - with self.assertAddsMessages(message): - self.checker.visit_raise(node) - - @python2_only - def test_checker_disabled_by_default(self): - node = astroid.parse(textwrap.dedent(""" - abc = 1l - raise Exception, "test" - raise "test" - `abc` - """)) - with self.assertNoMessages(): - self.walk(node) - - def test_using_cmp_argument(self): - nodes = test_utils.extract_node(""" - [].sort(cmp=lambda x: x) #@ - a = list(range(x)) - a.sort(cmp=lambda x: x) #@ - - sorted([], cmp=lambda x: x) #@ - """) - for node in nodes: - message = testutils.Message('using-cmp-argument', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) - - -@python2_only -class Python3TokenCheckerTest(testutils.CheckerTestCase): - - CHECKER_CLASS = checker.Python3TokenChecker - - def _test_token_message(self, code, symbolic_message): - tokens = testutils.tokenize_str(code) - message = testutils.Message(symbolic_message, line=1) - with self.assertAddsMessages(message): - self.checker.process_tokens(tokens) - - def test_long_suffix(self): - for code in ("1l", "1L"): - self._test_token_message(code, 'long-suffix') - - def test_old_ne_operator(self): - self._test_token_message("1 <> 2", "old-ne-operator") - - def test_old_octal_literal(self): - for octal in ("045", "055", "075", "077", "076543"): - self._test_token_message(octal, "old-octal-literal") - - # Make sure we are catching only octals. - for non_octal in ("45", "00", "085", "08", "1"): - tokens = testutils.tokenize_str(non_octal) - with self.assertNoMessages(): - self.checker.process_tokens(tokens) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_similar.py b/pymode/libs/pylint/test/unittest_checker_similar.py deleted file mode 100644 index a151ce8e..00000000 --- a/pymode/libs/pylint/test/unittest_checker_similar.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import sys -from os.path import join, dirname, abspath -import unittest - -import six - -from pylint.checkers import similar - -SIMILAR1 = join(dirname(abspath(__file__)), 'input', 'similar1') -SIMILAR2 = join(dirname(abspath(__file__)), 'input', 'similar2') - -class SimilarTC(unittest.TestCase): - """test the similar command line utility""" - - def test_ignore_comments(self): - sys.stdout = six.StringIO() - try: - similar.Run(['--ignore-comments', SIMILAR1, SIMILAR2]) - except SystemExit as ex: - self.assertEqual(ex.code, 0) - output = sys.stdout.getvalue() - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - self.assertMultiLineEqual(output.strip(), (""" -10 similar lines in 2 files -==%s:0 -==%s:0 - import one - from two import two - three - four - five - six - seven - eight - nine - ''' ten -TOTAL lines=44 duplicates=10 percent=22.73 -""" % (SIMILAR1, SIMILAR2)).strip()) - - - def test_ignore_docsrings(self): - sys.stdout = six.StringIO() - try: - similar.Run(['--ignore-docstrings', SIMILAR1, SIMILAR2]) - except SystemExit as ex: - self.assertEqual(ex.code, 0) - output = sys.stdout.getvalue() - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - self.assertMultiLineEqual(output.strip(), (""" -8 similar lines in 2 files -==%s:6 -==%s:6 - seven - eight - nine - ''' ten - ELEVEN - twelve ''' - thirteen - fourteen - -5 similar lines in 2 files -==%s:0 -==%s:0 - import one - from two import two - three - four - five -TOTAL lines=44 duplicates=13 percent=29.55 -""" % ((SIMILAR1, SIMILAR2) * 2)).strip()) - - - def test_ignore_imports(self): - sys.stdout = six.StringIO() - try: - similar.Run(['--ignore-imports', SIMILAR1, SIMILAR2]) - except SystemExit as ex: - self.assertEqual(ex.code, 0) - output = sys.stdout.getvalue() - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - self.assertMultiLineEqual(output.strip(), """ -TOTAL lines=44 duplicates=0 percent=0.00 -""".strip()) - - - def test_ignore_nothing(self): - sys.stdout = six.StringIO() - try: - similar.Run([SIMILAR1, SIMILAR2]) - except SystemExit as ex: - self.assertEqual(ex.code, 0) - output = sys.stdout.getvalue() - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - self.assertMultiLineEqual(output.strip(), (""" -5 similar lines in 2 files -==%s:0 -==%s:0 - import one - from two import two - three - four - five -TOTAL lines=44 duplicates=5 percent=11.36 -""" % (SIMILAR1, SIMILAR2)).strip()) - - def test_help(self): - sys.stdout = six.StringIO() - try: - similar.Run(['--help']) - except SystemExit as ex: - self.assertEqual(ex.code, 0) - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - - def test_no_args(self): - sys.stdout = six.StringIO() - try: - similar.Run([]) - except SystemExit as ex: - self.assertEqual(ex.code, 1) - else: - self.fail('not system exit') - finally: - sys.stdout = sys.__stdout__ - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_spelling.py b/pymode/libs/pylint/test/unittest_checker_spelling.py deleted file mode 100644 index 13f13160..00000000 --- a/pymode/libs/pylint/test/unittest_checker_spelling.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unittest for the spelling checker.""" - -import unittest - -from astroid import test_utils - -from pylint.checkers import spelling -from pylint.testutils import ( - CheckerTestCase, Message, set_config, tokenize_str, -) - -# try to create enchant dictionary -try: - import enchant -except ImportError: - enchant = None - -spell_dict = None -if enchant is not None: - try: - enchant.Dict("en_US") - spell_dict = "en_US" - except enchant.DictNotFoundError: - pass - - -class SpellingCheckerTest(CheckerTestCase): - CHECKER_CLASS = spelling.SpellingChecker - - @unittest.skipIf(spell_dict is None, - "missing python-enchant package or missing " - "spelling dictionaries") - @set_config(spelling_dict=spell_dict) - def test_check_bad_coment(self): - with self.assertAddsMessages( - Message('wrong-spelling-in-comment', line=1, - args=('coment', '# bad coment', - ' ^^^^^^', - "comet' or 'comment' or 'moment' or 'foment"))): - self.checker.process_tokens(tokenize_str("# bad coment")) - - @unittest.skipIf(spell_dict is None, - "missing python-enchant package or missing " - "spelling dictionaries") - @set_config(spelling_dict=spell_dict) - def test_check_bad_docstring(self): - stmt = test_utils.extract_node( - 'def fff():\n """bad coment"""\n pass') - with self.assertAddsMessages( - Message('wrong-spelling-in-docstring', line=2, - args=('coment', 'bad coment', - ' ^^^^^^', - "comet' or 'comment' or 'moment' or 'foment"))): - self.checker.visit_functiondef(stmt) - - stmt = test_utils.extract_node( - 'class Abc(object):\n """bad coment"""\n pass') - with self.assertAddsMessages( - Message('wrong-spelling-in-docstring', line=2, - args=('coment', 'bad coment', - ' ^^^^^^', - "comet' or 'comment' or 'moment' or 'foment"))): - self.checker.visit_classdef(stmt) - - @unittest.skipIf(spell_dict is None, - "missing python-enchant package or missing " - "spelling dictionaries") - @set_config(spelling_dict=spell_dict) - def test_invalid_docstring_characters(self): - stmt = test_utils.extract_node( - 'def fff():\n """test\\x00"""\n pass') - with self.assertAddsMessages( - Message('invalid-characters-in-docstring', line=2, - args=('test\x00',))): - self.checker.visit_functiondef(stmt) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_stdlib.py b/pymode/libs/pylint/test/unittest_checker_stdlib.py deleted file mode 100644 index 77086540..00000000 --- a/pymode/libs/pylint/test/unittest_checker_stdlib.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import contextlib -import unittest - -import astroid -from astroid import test_utils - -from pylint.checkers import stdlib -from pylint.testutils import CheckerTestCase - - -@contextlib.contextmanager -def _add_transform(manager, node, transform, predicate=None): - manager.register_transform(node, transform, predicate) - try: - yield - finally: - manager.unregister_transform(node, transform, predicate) - - -class StdlibCheckerTest(CheckerTestCase): - CHECKER_CLASS = stdlib.StdlibChecker - - def test_deprecated_no_qname_on_unexpected_nodes(self): - # Test that we don't crash on nodes which don't have - # a qname method. While this test might seem weird since - # it uses a transform, it's actually testing a crash that - # happened in production, but there was no way to retrieve - # the code for which this occurred (how an AssignAttr - # got to be the result of a function inference - # beats me..) - - def infer_func(node, context=None): - new_node = astroid.AssignAttr() - new_node.parent = node - yield new_node - - manager = astroid.MANAGER - transform = astroid.inference_tip(infer_func) - with _add_transform(manager, astroid.Name, transform): - node = test_utils.extract_node(''' - call_something() - ''') - with self.assertNoMessages(): - self.checker.visit_call(node) - - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_strings.py b/pymode/libs/pylint/test/unittest_checker_strings.py deleted file mode 100644 index d3758233..00000000 --- a/pymode/libs/pylint/test/unittest_checker_strings.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import sys -import unittest - -from astroid import test_utils - -from pylint.checkers import strings -from pylint.testutils import CheckerTestCase - - -class StringCheckerTest(CheckerTestCase): - CHECKER_CLASS = strings.StringFormatChecker - - @unittest.skipUnless(sys.version_info > (3, 0), - "Tests that the string formatting checker " - "doesn't fail when encountering a bytes " - "string with a .format call") - def test_format_bytes(self): - code = "b'test'.format(1, 2)" - node = test_utils.extract_node(code) - with self.assertNoMessages(): - self.checker.visit_call(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_typecheck.py b/pymode/libs/pylint/test/unittest_checker_typecheck.py deleted file mode 100644 index e9f79870..00000000 --- a/pymode/libs/pylint/test/unittest_checker_typecheck.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unittest for the type checker.""" -import unittest - -from astroid import test_utils -from pylint.checkers import typecheck -from pylint.testutils import CheckerTestCase, Message, set_config - - -class TypeCheckerTest(CheckerTestCase): - "Tests for pylint.checkers.typecheck" - CHECKER_CLASS = typecheck.TypeChecker - - def test_no_member_in_getattr(self): - """Make sure that a module attribute access is checked by pylint. - """ - - node = test_utils.extract_node(""" - import optparse - optparse.THIS_does_not_EXIST - """) - with self.assertAddsMessages( - Message( - 'no-member', - node=node, - args=('Module', 'optparse', 'THIS_does_not_EXIST'))): - self.checker.visit_attribute(node) - - @set_config(ignored_modules=('argparse',)) - def test_no_member_in_getattr_ignored(self): - """Make sure that a module attribute access check is omitted with a - module that is configured to be ignored. - """ - - node = test_utils.extract_node(""" - import argparse - argparse.THIS_does_not_EXIST - """) - with self.assertNoMessages(): - self.checker.visit_attribute(node) - - @set_config(ignored_classes=('xml.etree.', )) - def test_ignored_modules_invalid_pattern(self): - node = test_utils.extract_node(''' - import xml - xml.etree.Lala - ''') - message = Message('no-member', node=node, - args=('Module', 'xml.etree', 'Lala')) - with self.assertAddsMessages(message): - self.checker.visit_attribute(node) - - @set_config(ignored_modules=('xml.etree*', )) - def test_ignored_modules_patterns(self): - node = test_utils.extract_node(''' - import xml - xml.etree.portocola #@ - ''') - with self.assertNoMessages(): - self.checker.visit_attribute(node) - - @set_config(ignored_classes=('xml.*', )) - def test_ignored_classes_no_recursive_pattern(self): - node = test_utils.extract_node(''' - import xml - xml.etree.ElementTree.Test - ''') - message = Message('no-member', node=node, - args=('Module', 'xml.etree.ElementTree', 'Test')) - with self.assertAddsMessages(message): - self.checker.visit_attribute(node) - - @set_config(ignored_classes=('optparse.Values', )) - def test_ignored_classes_qualified_name(self): - """Test that ignored-classes supports qualified name for ignoring.""" - node = test_utils.extract_node(''' - import optparse - optparse.Values.lala - ''') - with self.assertNoMessages(): - self.checker.visit_attribute(node) - - @set_config(ignored_classes=('Values', )) - def test_ignored_classes_only_name(self): - """Test that ignored_classes works with the name only.""" - node = test_utils.extract_node(''' - import optparse - optparse.Values.lala - ''') - with self.assertNoMessages(): - self.checker.visit_attribute(node) - - @set_config(contextmanager_decorators=('contextlib.contextmanager', - '.custom_contextmanager')) - def test_custom_context_manager(self): - """Test that @custom_contextmanager is recognized as configured.""" - node = test_utils.extract_node(''' - from contextlib import contextmanager - def custom_contextmanager(f): - return contextmanager(f) - @custom_contextmanager - def dec(): - yield - with dec(): - pass - ''') - with self.assertNoMessages(): - self.checker.visit_with(node) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checker_variables.py b/pymode/libs/pylint/test/unittest_checker_variables.py deleted file mode 100644 index 3c8bea66..00000000 --- a/pymode/libs/pylint/test/unittest_checker_variables.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the variables checker.""" -import sys -import os -import unittest - -import astroid -from astroid import test_utils - -from pylint.checkers import variables -from pylint.testutils import CheckerTestCase, linter, set_config, Message - -class VariablesCheckerTC(CheckerTestCase): - - CHECKER_CLASS = variables.VariablesChecker - - def test_bitbucket_issue_78(self): - """ Issue 78 report a false positive for unused-module """ - module = astroid.parse(""" - from sys import path - path += ['stuff'] - def func(): - other = 1 - return len(other) - """) - with self.assertNoMessages(): - self.walk(module) - - @set_config(ignored_modules=('argparse',)) - def test_no_name_in_module_skipped(self): - """Make sure that 'from ... import ...' does not emit a - 'no-name-in-module' with a module that is configured - to be ignored. - """ - - node = test_utils.extract_node(""" - from argparse import THIS_does_not_EXIST - """) - with self.assertNoMessages(): - self.checker.visit_importfrom(node) - - def test_all_elements_without_parent(self): - node = test_utils.extract_node('__all__ = []') - node.value.elts.append(astroid.Const('test')) - root = node.root() - with self.assertNoMessages(): - self.checker.visit_module(root) - self.checker.leave_module(root) - - @set_config(callbacks=('callback_', '_callback')) - def test_custom_callback_string(self): - """ Test the --calbacks option works. """ - def cleanup(): - self.checker._to_consume = _to_consume - _to_consume = self.checker._to_consume - self.checker._to_consume = [] - self.addCleanup(cleanup) - - node = test_utils.extract_node(""" - def callback_one(abc): - ''' should not emit unused-argument. ''' - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - self.checker.leave_functiondef(node) - - node = test_utils.extract_node(""" - def two_callback(abc, defg): - ''' should not emit unused-argument. ''' - """) - with self.assertNoMessages(): - self.checker.visit_functiondef(node) - self.checker.leave_functiondef(node) - - node = test_utils.extract_node(""" - def normal_func(abc): - ''' should emit unused-argument. ''' - """) - with self.assertAddsMessages( - Message('unused-argument', node=node['abc'], args='abc')): - self.checker.visit_functiondef(node) - self.checker.leave_functiondef(node) - - node = test_utils.extract_node(""" - def cb_func(abc): - ''' Previous callbacks are overriden. ''' - """) - with self.assertAddsMessages( - Message('unused-argument', node=node['abc'], args='abc')): - self.checker.visit_functiondef(node) - self.checker.leave_functiondef(node) - - def test_redefined_builtin_ignored(self): - node = astroid.parse(''' - from future.builtins import open - ''') - with self.assertNoMessages(): - self.checker.visit_module(node) - - @set_config(redefining_builtins_modules=('os',)) - def test_redefined_builtin_custom_modules(self): - node = astroid.parse(''' - from os import open - ''') - with self.assertNoMessages(): - self.checker.visit_module(node) - - @set_config(redefining_builtins_modules=('os',)) - def test_redefined_builtin_modname_not_ignored(self): - node = astroid.parse(''' - from future.builtins import open - ''') - with self.assertAddsMessages( - Message('redefined-builtin', node=node.body[0], args='open')): - self.checker.visit_module(node) - - @set_config(redefining_builtins_modules=('os',)) - def test_redefined_builtin_in_function(self): - node = test_utils.extract_node(''' - def test(): - from os import open - ''') - with self.assertNoMessages(): - self.checker.visit_module(node.root()) - self.checker.visit_functiondef(node) - - -class MissingSubmoduleTest(CheckerTestCase): - CHECKER_CLASS = variables.VariablesChecker - - def test_package_all(self): - regr_data = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'regrtest_data') - sys.path.insert(0, regr_data) - try: - linter.check(os.path.join(regr_data, 'package_all')) - got = linter.reporter.finalize().strip() - self.assertEqual(got, "E: 3: Undefined variable name " - "'missing' in __all__") - finally: - sys.path.pop(0) - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_checkers_utils.py b/pymode/libs/pylint/test/unittest_checkers_utils.py deleted file mode 100644 index 2a20b47a..00000000 --- a/pymode/libs/pylint/test/unittest_checkers_utils.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Tests for the pylint.checkers.utils module.""" - -import unittest -import warnings - -from astroid import test_utils - -from pylint.checkers import utils -from pylint import __pkginfo__ - -class UtilsTC(unittest.TestCase): - - def test_is_builtin(self): - self.assertEqual(utils.is_builtin('min'), True) - self.assertEqual(utils.is_builtin('__builtins__'), True) - self.assertEqual(utils.is_builtin('__path__'), False) - self.assertEqual(utils.is_builtin('__file__'), False) - self.assertEqual(utils.is_builtin('whatever'), False) - self.assertEqual(utils.is_builtin('mybuiltin'), False) - - def testGetArgumentFromCall(self): - node = test_utils.extract_node('foo(bar=3)') - self.assertIsNotNone(utils.get_argument_from_call(node, keyword='bar')) - with self.assertRaises(utils.NoSuchArgumentError): - node = test_utils.extract_node('foo(3)') - utils.get_argument_from_call(node, keyword='bar') - with self.assertRaises(utils.NoSuchArgumentError): - node = test_utils.extract_node('foo(one=a, two=b, three=c)') - utils.get_argument_from_call(node, position=1) - node = test_utils.extract_node('foo(a, b, c)') - self.assertIsNotNone(utils.get_argument_from_call(node, position=1)) - node = test_utils.extract_node('foo(a, not_this_one=1, this_one=2)') - arg = utils.get_argument_from_call(node, position=2, keyword='this_one') - self.assertEqual(2, arg.value) - node = test_utils.extract_node('foo(a)') - with self.assertRaises(utils.NoSuchArgumentError): - utils.get_argument_from_call(node, position=1) - with self.assertRaises(ValueError): - utils.get_argument_from_call(node, None, None) - - name = utils.get_argument_from_call(node, position=0) - self.assertEqual(name.name, 'a') - - def test_error_of_type(self): - nodes = test_utils.extract_node(""" - try: pass - except AttributeError: #@ - pass - try: pass - except Exception: #@ - pass - except: #@ - pass - """) - self.assertTrue(utils.error_of_type(nodes[0], AttributeError)) - self.assertTrue(utils.error_of_type(nodes[0], (AttributeError, ))) - self.assertFalse(utils.error_of_type(nodes[0], Exception)) - self.assertTrue(utils.error_of_type(nodes[1], Exception)) - self.assertFalse(utils.error_of_type(nodes[2], ImportError)) - - def test_node_ignores_exception(self): - nodes = test_utils.extract_node(""" - try: - 1/0 #@ - except ZeroDivisionError: - pass - try: - 1/0 #@ - except Exception: - pass - try: - 2/0 #@ - except: - pass - try: - 1/0 #@ - except ValueError: - pass - """) - self.assertTrue(utils.node_ignores_exception(nodes[0], ZeroDivisionError)) - self.assertFalse(utils.node_ignores_exception(nodes[1], ZeroDivisionError)) - self.assertFalse(utils.node_ignores_exception(nodes[2], ZeroDivisionError)) - self.assertFalse(utils.node_ignores_exception(nodes[3], ZeroDivisionError)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_config.py b/pymode/libs/pylint/test/unittest_config.py deleted file mode 100644 index 8c764ecf..00000000 --- a/pymode/libs/pylint/test/unittest_config.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Unit tests for the config module.""" - -import re -import sre_constants -import unittest - -from pylint import config - -class ConfigValidatorTest(unittest.TestCase): - def test__regexp_validator_valid(self): - result = config._regexp_validator(None, None, "test_.*") - self.assertTrue(isinstance(result, re._pattern_type)) - self.assertEqual(result.pattern, "test_.*") - - def test__regexp_validator_invalid(self): - with self.assertRaises(sre_constants.error): - config._regexp_validator(None, None, "test_)") - - def test__csv_validator_no_spaces(self): - values = ["One", "Two", "Three"] - result = config._csv_validator(None, None, ",".join(values)) - self.assertTrue(isinstance(result, list)) - self.assertEqual(len(result), 3) - for i, value in enumerate(values): - self.assertEqual(result[i], value) - - def test__csv_validator_spaces(self): - values = ["One", "Two", "Three"] - result = config._csv_validator(None, None, ", ".join(values)) - self.assertTrue(isinstance(result, list)) - self.assertEqual(len(result), 3) - for i, value in enumerate(values): - self.assertEqual(result[i], value) - - def test__regexp_csv_validator_valid(self): - pattern_strings = ["test_.*", "foo\.bar", "^baz$"] - result = config._regexp_csv_validator(None, None, ",".join(pattern_strings)) - for i, regex in enumerate(result): - self.assertTrue(isinstance(regex, re._pattern_type)) - self.assertEqual(regex.pattern, pattern_strings[i]) - - def test__regexp_csv_validator_invalid(self): - pattern_strings = ["test_.*", "foo\.bar", "^baz)$"] - with self.assertRaises(sre_constants.error): - config._regexp_csv_validator(None, None, ",".join(pattern_strings)) - -if __name__ == "__main__": - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_lint.py b/pymode/libs/pylint/test/unittest_lint.py deleted file mode 100644 index e06d1820..00000000 --- a/pymode/libs/pylint/test/unittest_lint.py +++ /dev/null @@ -1,684 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -from contextlib import contextmanager -import sys -import os -import tempfile -from shutil import rmtree -from os import getcwd, chdir -from os.path import join, basename, dirname, isdir, abspath, sep -import unittest - -import six -from six.moves import reload_module - -from pylint import config, lint -from pylint.lint import PyLinter, Run, preprocess_options, \ - ArgumentPreprocessingError -from pylint.utils import MSG_STATE_SCOPE_CONFIG, MSG_STATE_SCOPE_MODULE, MSG_STATE_CONFIDENCE, \ - MessagesStore, PyLintASTWalker, MessageDefinition, FileState, \ - build_message_def, tokenize_module, UnknownMessage -from pylint.testutils import TestReporter, catch_warnings -from pylint.reporters import text, html -from pylint import checkers -from pylint.checkers.utils import check_messages -from pylint import interfaces - -if os.name == 'java': - if os._name == 'nt': - HOME = 'USERPROFILE' - else: - HOME = 'HOME' -else: - if sys.platform == 'win32': - HOME = 'USERPROFILE' - else: - HOME = 'HOME' - -@contextmanager -def fake_home(): - folder = tempfile.mkdtemp('fake-home') - old_home = os.environ.get(HOME) - try: - os.environ[HOME] = folder - yield - finally: - os.environ.pop('PYLINTRC', '') - if old_home is None: - del os.environ[HOME] - else: - os.environ[HOME] = old_home - rmtree(folder, ignore_errors=True) - -def remove(file): - try: - os.remove(file) - except OSError: - pass - -HERE = abspath(dirname(__file__)) -INPUTDIR = join(HERE, 'input') - - -@contextmanager -def tempdir(): - """Create a temp directory and change the current location to it. - - This is supposed to be used with a *with* statement. - """ - tmp = tempfile.mkdtemp() - - # Get real path of tempfile, otherwise test fail on mac os x - current_dir = getcwd() - chdir(tmp) - abs_tmp = abspath('.') - - try: - yield abs_tmp - finally: - chdir(current_dir) - rmtree(abs_tmp) - - -def create_files(paths, chroot='.'): - """Creates directories and files found in . - - :param paths: list of relative paths to files or directories - :param chroot: the root directory in which paths will be created - - >>> from os.path import isdir, isfile - >>> isdir('/tmp/a') - False - >>> create_files(['a/b/foo.py', 'a/b/c/', 'a/b/c/d/e.py'], '/tmp') - >>> isdir('/tmp/a') - True - >>> isdir('/tmp/a/b/c') - True - >>> isfile('/tmp/a/b/c/d/e.py') - True - >>> isfile('/tmp/a/b/foo.py') - True - """ - dirs, files = set(), set() - for path in paths: - path = join(chroot, path) - filename = basename(path) - # path is a directory path - if filename == '': - dirs.add(path) - # path is a filename path - else: - dirs.add(dirname(path)) - files.add(path) - for dirpath in dirs: - if not isdir(dirpath): - os.makedirs(dirpath) - for filepath in files: - open(filepath, 'w').close() - - -class SysPathFixupTC(unittest.TestCase): - def setUp(self): - self.orig = list(sys.path) - self.fake = [1, 2, 3] - sys.path[:] = self.fake - - def tearDown(self): - sys.path[:] = self.orig - - def test_no_args(self): - with lint.fix_import_path([]): - self.assertEqual(sys.path, self.fake) - self.assertEqual(sys.path, self.fake) - - def test_one_arg(self): - with tempdir() as chroot: - create_files(['a/b/__init__.py']) - expected = [join(chroot, 'a')] + self.fake - - cases = ( - ['a/b/'], - ['a/b'], - ['a/b/__init__.py'], - ['a/'], - ['a'], - ) - - self.assertEqual(sys.path, self.fake) - for case in cases: - with lint.fix_import_path(case): - self.assertEqual(sys.path, expected) - self.assertEqual(sys.path, self.fake) - - def test_two_similar_args(self): - with tempdir() as chroot: - create_files(['a/b/__init__.py', 'a/c/__init__.py']) - expected = [join(chroot, 'a')] + self.fake - - cases = ( - ['a/b', 'a/c'], - ['a/c/', 'a/b/'], - ['a/b/__init__.py', 'a/c/__init__.py'], - ['a', 'a/c/__init__.py'], - ) - - self.assertEqual(sys.path, self.fake) - for case in cases: - with lint.fix_import_path(case): - self.assertEqual(sys.path, expected) - self.assertEqual(sys.path, self.fake) - - def test_more_args(self): - with tempdir() as chroot: - create_files(['a/b/c/__init__.py', 'a/d/__init__.py', 'a/e/f.py']) - expected = [ - join(chroot, suffix) - for suffix in [sep.join(('a', 'b')), 'a', sep.join(('a', 'e'))] - ] + self.fake - - cases = ( - ['a/b/c/__init__.py', 'a/d/__init__.py', 'a/e/f.py'], - ['a/b/c', 'a', 'a/e'], - ['a/b/c', 'a', 'a/b/c', 'a/e', 'a'], - ) - - self.assertEqual(sys.path, self.fake) - for case in cases: - with lint.fix_import_path(case): - self.assertEqual(sys.path, expected) - self.assertEqual(sys.path, self.fake) - - -class PyLinterTC(unittest.TestCase): - - def setUp(self): - self.linter = PyLinter() - self.linter.disable('I') - self.linter.config.persistent = 0 - # register checkers - checkers.initialize(self.linter) - self.linter.set_reporter(TestReporter()) - - def init_linter(self): - linter = self.linter - linter.open() - linter.set_current_module('toto') - linter.file_state = FileState('toto') - return linter - - def test_pylint_visit_method_taken_in_account(self): - class CustomChecker(checkers.BaseChecker): - __implements__ = interfaces.IAstroidChecker - name = 'custom' - msgs = {'W9999': ('', 'custom', '')} - - @check_messages('custom') - def visit_class(self, _): - pass - - self.linter.register_checker(CustomChecker(self.linter)) - self.linter.open() - out = six.moves.StringIO() - self.linter.set_reporter(text.TextReporter(out)) - self.linter.check('abc') - - def test_enable_message(self): - linter = self.init_linter() - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('W0102')) - linter.disable('W0101', scope='package') - linter.disable('W0102', scope='module', line=1) - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertFalse(linter.is_message_enabled('W0102', 1)) - linter.set_current_module('tutu') - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('W0102')) - linter.enable('W0101', scope='package') - linter.enable('W0102', scope='module', line=1) - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('W0102', 1)) - - def test_enable_message_category(self): - linter = self.init_linter() - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('C0202')) - linter.disable('W', scope='package') - linter.disable('C', scope='module', line=1) - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('C0202')) - self.assertFalse(linter.is_message_enabled('C0202', line=1)) - linter.set_current_module('tutu') - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('C0202')) - linter.enable('W', scope='package') - linter.enable('C', scope='module', line=1) - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('C0202')) - self.assertTrue(linter.is_message_enabled('C0202', line=1)) - - def test_message_state_scope(self): - class FakeConfig(object): - confidence = ['HIGH'] - - linter = self.init_linter() - linter.disable('C0202') - self.assertEqual(MSG_STATE_SCOPE_CONFIG, - linter.get_message_state_scope('C0202')) - linter.disable('W0101', scope='module', line=3) - self.assertEqual(MSG_STATE_SCOPE_CONFIG, - linter.get_message_state_scope('C0202')) - self.assertEqual(MSG_STATE_SCOPE_MODULE, - linter.get_message_state_scope('W0101', 3)) - linter.enable('W0102', scope='module', line=3) - self.assertEqual(MSG_STATE_SCOPE_MODULE, - linter.get_message_state_scope('W0102', 3)) - linter.config = FakeConfig() - self.assertEqual( - MSG_STATE_CONFIDENCE, - linter.get_message_state_scope('this-is-bad', - confidence=interfaces.INFERENCE)) - - def test_enable_message_block(self): - linter = self.init_linter() - linter.open() - filepath = join(INPUTDIR, 'func_block_disable_msg.py') - linter.set_current_module('func_block_disable_msg') - astroid = linter.get_ast(filepath, 'func_block_disable_msg') - linter.process_tokens(tokenize_module(astroid)) - fs = linter.file_state - fs.collect_block_lines(linter.msgs_store, astroid) - # global (module level) - self.assertTrue(linter.is_message_enabled('W0613')) - self.assertTrue(linter.is_message_enabled('E1101')) - # meth1 - self.assertTrue(linter.is_message_enabled('W0613', 13)) - # meth2 - self.assertFalse(linter.is_message_enabled('W0613', 18)) - # meth3 - self.assertFalse(linter.is_message_enabled('E1101', 24)) - self.assertTrue(linter.is_message_enabled('E1101', 26)) - # meth4 - self.assertFalse(linter.is_message_enabled('E1101', 32)) - self.assertTrue(linter.is_message_enabled('E1101', 36)) - # meth5 - self.assertFalse(linter.is_message_enabled('E1101', 42)) - self.assertFalse(linter.is_message_enabled('E1101', 43)) - self.assertTrue(linter.is_message_enabled('E1101', 46)) - self.assertFalse(linter.is_message_enabled('E1101', 49)) - self.assertFalse(linter.is_message_enabled('E1101', 51)) - # meth6 - self.assertFalse(linter.is_message_enabled('E1101', 57)) - self.assertTrue(linter.is_message_enabled('E1101', 61)) - self.assertFalse(linter.is_message_enabled('E1101', 64)) - self.assertFalse(linter.is_message_enabled('E1101', 66)) - - self.assertTrue(linter.is_message_enabled('E0602', 57)) - self.assertTrue(linter.is_message_enabled('E0602', 61)) - self.assertFalse(linter.is_message_enabled('E0602', 62)) - self.assertTrue(linter.is_message_enabled('E0602', 64)) - self.assertTrue(linter.is_message_enabled('E0602', 66)) - # meth7 - self.assertFalse(linter.is_message_enabled('E1101', 70)) - self.assertTrue(linter.is_message_enabled('E1101', 72)) - self.assertTrue(linter.is_message_enabled('E1101', 75)) - self.assertTrue(linter.is_message_enabled('E1101', 77)) - - fs = linter.file_state - self.assertEqual(17, fs._suppression_mapping['W0613', 18]) - self.assertEqual(30, fs._suppression_mapping['E1101', 33]) - self.assertTrue(('E1101', 46) not in fs._suppression_mapping) - self.assertEqual(1, fs._suppression_mapping['C0302', 18]) - self.assertEqual(1, fs._suppression_mapping['C0302', 50]) - # This is tricky. While the disable in line 106 is disabling - # both 108 and 110, this is usually not what the user wanted. - # Therefore, we report the closest previous disable comment. - self.assertEqual(106, fs._suppression_mapping['E1101', 108]) - self.assertEqual(109, fs._suppression_mapping['E1101', 110]) - - def test_enable_by_symbol(self): - """messages can be controlled by symbolic names. - - The state is consistent across symbols and numbers. - """ - linter = self.init_linter() - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('unreachable')) - self.assertTrue(linter.is_message_enabled('W0102')) - self.assertTrue(linter.is_message_enabled('dangerous-default-value')) - linter.disable('unreachable', scope='package') - linter.disable('dangerous-default-value', scope='module', line=1) - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertFalse(linter.is_message_enabled('unreachable')) - self.assertFalse(linter.is_message_enabled('W0102', 1)) - self.assertFalse(linter.is_message_enabled('dangerous-default-value', 1)) - linter.set_current_module('tutu') - self.assertFalse(linter.is_message_enabled('W0101')) - self.assertFalse(linter.is_message_enabled('unreachable')) - self.assertTrue(linter.is_message_enabled('W0102')) - self.assertTrue(linter.is_message_enabled('dangerous-default-value')) - linter.enable('unreachable', scope='package') - linter.enable('dangerous-default-value', scope='module', line=1) - self.assertTrue(linter.is_message_enabled('W0101')) - self.assertTrue(linter.is_message_enabled('unreachable')) - self.assertTrue(linter.is_message_enabled('W0102', 1)) - self.assertTrue(linter.is_message_enabled('dangerous-default-value', 1)) - - def test_lint_ext_module_with_file_output(self): - self.linter.set_reporter(text.TextReporter()) - if sys.version_info < (3, 0): - strio = 'StringIO' - else: - strio = 'io' - self.linter.config.files_output = True - pylint_strio = 'pylint_%s.txt' % strio - files = [pylint_strio, 'pylint_global.txt'] - for file in files: - self.addCleanup(remove, file) - - self.linter.check(strio) - self.linter.generate_reports() - for f in files: - self.assertTrue(os.path.exists(f)) - - def test_enable_report(self): - self.assertEqual(self.linter.report_is_enabled('RP0001'), True) - self.linter.disable('RP0001') - self.assertEqual(self.linter.report_is_enabled('RP0001'), False) - self.linter.enable('RP0001') - self.assertEqual(self.linter.report_is_enabled('RP0001'), True) - - def test_report_output_format_aliased(self): - text.register(self.linter) - self.linter.set_option('output-format', 'text') - self.assertEqual(self.linter.reporter.__class__.__name__, 'TextReporter') - - def test_report_output_format_custom(self): - this_module = sys.modules[__name__] - class TestReporter(object): - pass - this_module.TestReporter = TestReporter - class_name = ".".join((this_module.__name__, 'TestReporter')) - self.linter.set_option('output-format', class_name) - self.assertEqual(self.linter.reporter.__class__.__name__, 'TestReporter') - - def test_set_option_1(self): - linter = self.linter - linter.set_option('disable', 'C0111,W0234') - self.assertFalse(linter.is_message_enabled('C0111')) - self.assertFalse(linter.is_message_enabled('W0234')) - self.assertTrue(linter.is_message_enabled('W0113')) - self.assertFalse(linter.is_message_enabled('missing-docstring')) - self.assertFalse(linter.is_message_enabled('non-iterator-returned')) - - def test_set_option_2(self): - linter = self.linter - linter.set_option('disable', ('C0111', 'W0234') ) - self.assertFalse(linter.is_message_enabled('C0111')) - self.assertFalse(linter.is_message_enabled('W0234')) - self.assertTrue(linter.is_message_enabled('W0113')) - self.assertFalse(linter.is_message_enabled('missing-docstring')) - self.assertFalse(linter.is_message_enabled('non-iterator-returned')) - - def test_enable_checkers(self): - self.linter.disable('design') - self.assertFalse('design' in [c.name for c in self.linter.prepare_checkers()]) - self.linter.enable('design') - self.assertTrue('design' in [c.name for c in self.linter.prepare_checkers()]) - - def test_errors_only(self): - linter = self.linter - self.linter.error_mode() - checkers = self.linter.prepare_checkers() - checker_names = set(c.name for c in checkers) - should_not = set(('design', 'format', 'metrics', - 'miscellaneous', 'similarities')) - self.assertSetEqual(set(), should_not & checker_names) - - def test_disable_similar(self): - self.linter.set_option('disable', 'RP0801') - self.linter.set_option('disable', 'R0801') - self.assertFalse('similarities' in [c.name for c in self.linter.prepare_checkers()]) - - def test_disable_alot(self): - """check that we disabled a lot of checkers""" - self.linter.set_option('reports', False) - self.linter.set_option('disable', 'R,C,W') - checker_names = [c.name for c in self.linter.prepare_checkers()] - for cname in ('design', 'metrics', 'similarities'): - self.assertFalse(cname in checker_names, cname) - - def test_addmessage(self): - self.linter.set_reporter(TestReporter()) - self.linter.open() - self.linter.set_current_module('0123') - self.linter.add_message('C0301', line=1, args=(1, 2)) - self.linter.add_message('line-too-long', line=2, args=(3, 4)) - self.assertEqual( - ['C: 1: Line too long (1/2)', 'C: 2: Line too long (3/4)'], - self.linter.reporter.messages) - - def test_init_hooks_called_before_load_plugins(self): - self.assertRaises(RuntimeError, - Run, ['--load-plugins', 'unexistant', '--init-hook', 'raise RuntimeError']) - self.assertRaises(RuntimeError, - Run, ['--init-hook', 'raise RuntimeError', '--load-plugins', 'unexistant']) - - - def test_analyze_explicit_script(self): - self.linter.set_reporter(TestReporter()) - self.linter.check(os.path.join(os.path.dirname(__file__), 'data', 'ascript')) - self.assertEqual( - ['C: 2: Line too long (175/100)'], - self.linter.reporter.messages) - - def test_html_reporter_missing_files(self): - output = six.StringIO() - with catch_warnings(): - self.linter.set_reporter(html.HTMLReporter(output)) - - self.linter.set_option('output-format', 'html') - self.linter.check('troppoptop.py') - self.linter.generate_reports() - value = output.getvalue() - self.assertIn('troppoptop.py', value) - self.assertIn('fatal', value) - - def test_python3_checker_disabled(self): - checker_names = [c.name for c in self.linter.prepare_checkers()] - self.assertNotIn('python3', checker_names) - - self.linter.set_option('enable', 'python3') - checker_names = [c.name for c in self.linter.prepare_checkers()] - self.assertIn('python3', checker_names) - - -class ConfigTC(unittest.TestCase): - - def setUp(self): - os.environ.pop('PYLINTRC', None) - - def test_pylint_home(self): - uhome = os.path.expanduser('~') - if uhome == '~': - expected = '.pylint.d' - else: - expected = os.path.join(uhome, '.pylint.d') - self.assertEqual(config.PYLINT_HOME, expected) - - try: - pylintd = join(tempfile.gettempdir(), '.pylint.d') - os.environ['PYLINTHOME'] = pylintd - try: - reload_module(config) - self.assertEqual(config.PYLINT_HOME, pylintd) - finally: - try: - os.remove(pylintd) - except: - pass - finally: - del os.environ['PYLINTHOME'] - - def test_pylintrc(self): - with fake_home(): - try: - self.assertEqual(config.find_pylintrc(), None) - os.environ['PYLINTRC'] = join(tempfile.gettempdir(), - '.pylintrc') - self.assertEqual(config.find_pylintrc(), None) - os.environ['PYLINTRC'] = '.' - self.assertEqual(config.find_pylintrc(), None) - finally: - reload_module(config) - - def test_pylintrc_parentdir(self): - with tempdir() as chroot: - - create_files(['a/pylintrc', 'a/b/__init__.py', 'a/b/pylintrc', - 'a/b/c/__init__.py', 'a/b/c/d/__init__.py', - 'a/b/c/d/e/.pylintrc']) - with fake_home(): - self.assertEqual(config.find_pylintrc(), None) - results = {'a' : join(chroot, 'a', 'pylintrc'), - 'a/b' : join(chroot, 'a', 'b', 'pylintrc'), - 'a/b/c' : join(chroot, 'a', 'b', 'pylintrc'), - 'a/b/c/d' : join(chroot, 'a', 'b', 'pylintrc'), - 'a/b/c/d/e' : join(chroot, 'a', 'b', 'c', 'd', 'e', '.pylintrc'), - } - for basedir, expected in results.items(): - os.chdir(join(chroot, basedir)) - self.assertEqual(config.find_pylintrc(), expected) - - def test_pylintrc_parentdir_no_package(self): - with tempdir() as chroot: - with fake_home(): - create_files(['a/pylintrc', 'a/b/pylintrc', 'a/b/c/d/__init__.py']) - self.assertEqual(config.find_pylintrc(), None) - results = {'a' : join(chroot, 'a', 'pylintrc'), - 'a/b' : join(chroot, 'a', 'b', 'pylintrc'), - 'a/b/c' : None, - 'a/b/c/d' : None, - } - for basedir, expected in results.items(): - os.chdir(join(chroot, basedir)) - self.assertEqual(config.find_pylintrc(), expected) - - -class PreprocessOptionsTC(unittest.TestCase): - def _callback(self, name, value): - self.args.append((name, value)) - - def test_value_equal(self): - self.args = [] - preprocess_options(['--foo', '--bar=baz', '--qu=ux'], - {'foo' : (self._callback, False), - 'qu' : (self._callback, True)}) - self.assertEqual( - [('foo', None), ('qu', 'ux')], self.args) - - def test_value_space(self): - self.args = [] - preprocess_options(['--qu', 'ux'], - {'qu' : (self._callback, True)}) - self.assertEqual( - [('qu', 'ux')], self.args) - - def test_error_missing_expected_value(self): - self.assertRaises( - ArgumentPreprocessingError, - preprocess_options, - ['--foo', '--bar', '--qu=ux'], - {'bar' : (None, True)}) - self.assertRaises( - ArgumentPreprocessingError, - preprocess_options, - ['--foo', '--bar'], - {'bar' : (None, True)}) - - def test_error_unexpected_value(self): - self.assertRaises( - ArgumentPreprocessingError, - preprocess_options, - ['--foo', '--bar=spam', '--qu=ux'], - {'bar' : (None, False)}) - - -class MessagesStoreTC(unittest.TestCase): - def setUp(self): - self.store = MessagesStore() - class Checker(object): - name = 'achecker' - msgs = { - 'W1234': ('message', 'msg-symbol', 'msg description.', - {'old_names': [('W0001', 'old-symbol')]}), - 'E1234': ('Duplicate keyword argument %r in %s call', - 'duplicate-keyword-arg', - 'Used when a function call passes the same keyword argument multiple times.', - {'maxversion': (2, 6)}), - } - self.store.register_messages(Checker()) - - def _compare_messages(self, desc, msg, checkerref=False): - self.assertMultiLineEqual(desc, msg.format_help(checkerref=checkerref)) - - def test_check_message_id(self): - self.assertIsInstance(self.store.check_message_id('W1234'), - MessageDefinition) - self.assertRaises(UnknownMessage, - self.store.check_message_id, 'YB12') - - def test_message_help(self): - msg = self.store.check_message_id('W1234') - self._compare_messages( - ''':msg-symbol (W1234): *message* - msg description. This message belongs to the achecker checker.''', - msg, checkerref=True) - self._compare_messages( - ''':msg-symbol (W1234): *message* - msg description.''', - msg, checkerref=False) - - def test_message_help_minmax(self): - # build the message manually to be python version independant - msg = self.store.check_message_id('E1234') - self._compare_messages( - ''':duplicate-keyword-arg (E1234): *Duplicate keyword argument %r in %s call* - Used when a function call passes the same keyword argument multiple times. - This message belongs to the achecker checker. It can't be emitted when using - Python >= 2.6.''', - msg, checkerref=True) - self._compare_messages( - ''':duplicate-keyword-arg (E1234): *Duplicate keyword argument %r in %s call* - Used when a function call passes the same keyword argument multiple times. - This message can't be emitted when using Python >= 2.6.''', - msg, checkerref=False) - - def test_list_messages(self): - sys.stdout = six.StringIO() - try: - self.store.list_messages() - output = sys.stdout.getvalue() - finally: - sys.stdout = sys.__stdout__ - # cursory examination of the output: we're mostly testing it completes - self.assertIn(':msg-symbol (W1234): *message*', output) - - def test_add_renamed_message(self): - self.store.add_renamed_message('W1234', 'old-bad-name', 'msg-symbol') - self.assertEqual('msg-symbol', - self.store.check_message_id('W1234').symbol) - self.assertEqual('msg-symbol', - self.store.check_message_id('old-bad-name').symbol) - - def test_renamed_message_register(self): - self.assertEqual('msg-symbol', - self.store.check_message_id('W0001').symbol) - self.assertEqual('msg-symbol', - self.store.check_message_id('old-symbol').symbol) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_pyreverse_diadefs.py b/pymode/libs/pylint/test/unittest_pyreverse_diadefs.py deleted file mode 100644 index e45dc356..00000000 --- a/pymode/libs/pylint/test/unittest_pyreverse_diadefs.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -""" -unittest for the extensions.diadefslib modules -""" - -import unittest -import sys - -import six - -import astroid -from astroid import MANAGER - -from pylint.pyreverse.inspector import Linker -from pylint.pyreverse.diadefslib import * - -from unittest_pyreverse_writer import Config, get_project - -PROJECT = get_project('data') -HANDLER = DiadefsHandler(Config()) - -def _process_classes(classes): - """extract class names of a list""" - return sorted([(isinstance(c.node, astroid.ClassDef), c.title) for c in classes]) - -def _process_relations(relations): - """extract relation indices from a relation list""" - result = [] - for rel_type, rels in six.iteritems(relations): - for rel in rels: - result.append( (rel_type, rel.from_object.title, - rel.to_object.title) ) - result.sort() - return result - - -class DiaDefGeneratorTC(unittest.TestCase): - def test_option_values(self): - """test for ancestor, associated and module options""" - handler = DiadefsHandler(Config()) - df_h = DiaDefGenerator(Linker(PROJECT), handler) - cl_config = Config() - cl_config.classes = ['Specialization'] - cl_h = DiaDefGenerator(Linker(PROJECT), DiadefsHandler(cl_config) ) - self.assertEqual( (0, 0), df_h._get_levels()) - self.assertEqual( False, df_h.module_names) - self.assertEqual( (-1, -1), cl_h._get_levels()) - self.assertEqual( True, cl_h.module_names) - for hndl in [df_h, cl_h]: - hndl.config.all_ancestors = True - hndl.config.all_associated = True - hndl.config.module_names = True - hndl._set_default_options() - self.assertEqual( (-1, -1), hndl._get_levels()) - self.assertEqual( True, hndl.module_names) - handler = DiadefsHandler( Config()) - df_h = DiaDefGenerator(Linker(PROJECT), handler) - cl_config = Config() - cl_config.classes = ['Specialization'] - cl_h = DiaDefGenerator(Linker(PROJECT), DiadefsHandler(cl_config) ) - for hndl in [df_h, cl_h]: - hndl.config.show_ancestors = 2 - hndl.config.show_associated = 1 - hndl.config.module_names = False - hndl._set_default_options() - self.assertEqual( (2, 1), hndl._get_levels()) - self.assertEqual( False, hndl.module_names) - #def test_default_values(self): - """test efault values for package or class diagrams""" - # TODO : should test difference between default values for package - # or class diagrams - -class DefaultDiadefGeneratorTC(unittest.TestCase): - def test_known_values1(self): - dd = DefaultDiadefGenerator(Linker(PROJECT), HANDLER).visit(PROJECT) - self.assertEqual(len(dd), 2) - keys = [d.TYPE for d in dd] - self.assertEqual(keys, ['package', 'class']) - pd = dd[0] - self.assertEqual(pd.title, 'packages No Name') - modules = sorted([(isinstance(m.node, astroid.Module), m.title) - for m in pd.objects]) - self.assertEqual(modules, [(True, 'data'), - (True, 'data.clientmodule_test'), - (True, 'data.suppliermodule_test')]) - cd = dd[1] - self.assertEqual(cd.title, 'classes No Name') - classes = _process_classes(cd.objects) - self.assertEqual(classes, [(True, 'Ancestor'), - (True, 'DoNothing'), - (True, 'Interface'), - (True, 'Specialization')] - ) - - _should_rels = [('association', 'DoNothing', 'Ancestor'), - ('association', 'DoNothing', 'Specialization'), - ('implements', 'Ancestor', 'Interface'), - ('specialization', 'Specialization', 'Ancestor')] - def test_exctract_relations(self): - """test extract_relations between classes""" - cd = DefaultDiadefGenerator(Linker(PROJECT), HANDLER).visit(PROJECT)[1] - cd.extract_relationships() - relations = _process_relations(cd.relationships) - self.assertEqual(relations, self._should_rels) - - def test_functional_relation_extraction(self): - """functional test of relations extraction; - different classes possibly in different modules""" - # XXX should be catching pyreverse environnement problem but doesn't - # pyreverse doesn't extracts the relations but this test ok - project = get_project('data') - handler = DiadefsHandler(Config()) - diadefs = handler.get_diadefs(project, Linker(project, tag=True) ) - cd = diadefs[1] - relations = _process_relations(cd.relationships) - self.assertEqual(relations, self._should_rels) - - def test_known_values2(self): - project = get_project('data.clientmodule_test') - dd = DefaultDiadefGenerator(Linker(project), HANDLER).visit(project) - self.assertEqual(len(dd), 1) - keys = [d.TYPE for d in dd] - self.assertEqual(keys, ['class']) - cd = dd[0] - self.assertEqual(cd.title, 'classes No Name') - classes = _process_classes(cd.objects) - self.assertEqual(classes, [(True, 'Ancestor'), - (True, 'DoNothing'), - (True, 'Specialization')] - ) - -class ClassDiadefGeneratorTC(unittest.TestCase): - def test_known_values1(self): - HANDLER.config.classes = ['Specialization'] - cdg = ClassDiadefGenerator(Linker(PROJECT), HANDLER) - special = 'data.clientmodule_test.Specialization' - cd = cdg.class_diagram(PROJECT, special) - self.assertEqual(cd.title, special) - classes = _process_classes(cd.objects) - self.assertEqual(classes, [(True, 'data.clientmodule_test.Ancestor'), - (True, special), - (True, 'data.suppliermodule_test.DoNothing'), - ]) - - def test_known_values2(self): - HANDLER.config.module_names = False - cd = ClassDiadefGenerator(Linker(PROJECT), HANDLER).class_diagram(PROJECT, 'data.clientmodule_test.Specialization') - self.assertEqual(cd.title, 'data.clientmodule_test.Specialization') - classes = _process_classes(cd.objects) - self.assertEqual(classes, [(True, 'Ancestor'), - (True, 'DoNothing'), - (True, 'Specialization') - ]) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_pyreverse_inspector.py b/pymode/libs/pylint/test/unittest_pyreverse_inspector.py deleted file mode 100644 index 5e6035bb..00000000 --- a/pymode/libs/pylint/test/unittest_pyreverse_inspector.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -""" - for the visitors.diadefs module -""" -import os -import unittest - -import astroid -from astroid import nodes -from astroid import bases -from astroid import manager -from astroid import test_utils - -from pylint.pyreverse import inspector -from unittest_pyreverse_writer import get_project - -MANAGER = manager.AstroidManager() - -def astroid_wrapper(func, modname): - return func(modname) - - -class LinkerTest(unittest.TestCase): - - def setUp(self): - super(LinkerTest, self).setUp() - self.project = get_project('data', 'data') - self.linker = inspector.Linker(self.project) - self.linker.visit(self.project) - - def test_class_implements(self): - klass = self.project.get_module('data.clientmodule_test')['Ancestor'] - self.assertTrue(hasattr(klass, 'implements')) - self.assertEqual(len(klass.implements), 1) - self.assertTrue(isinstance(klass.implements[0], nodes.ClassDef)) - self.assertEqual(klass.implements[0].name, "Interface") - klass = self.project.get_module('data.clientmodule_test')['Specialization'] - self.assertTrue(hasattr(klass, 'implements')) - self.assertEqual(len(klass.implements), 0) - - def test_locals_assignment_resolution(self): - klass = self.project.get_module('data.clientmodule_test')['Specialization'] - self.assertTrue(hasattr(klass, 'locals_type')) - type_dict = klass.locals_type - self.assertEqual(len(type_dict), 2) - keys = sorted(type_dict.keys()) - self.assertEqual(keys, ['TYPE', 'top']) - self.assertEqual(len(type_dict['TYPE']), 1) - self.assertEqual(type_dict['TYPE'][0].value, 'final class') - self.assertEqual(len(type_dict['top']), 1) - self.assertEqual(type_dict['top'][0].value, 'class') - - def test_instance_attrs_resolution(self): - klass = self.project.get_module('data.clientmodule_test')['Specialization'] - self.assertTrue(hasattr(klass, 'instance_attrs_type')) - type_dict = klass.instance_attrs_type - self.assertEqual(len(type_dict), 2) - keys = sorted(type_dict.keys()) - self.assertEqual(keys, ['_id', 'relation']) - self.assertTrue(isinstance(type_dict['relation'][0], bases.Instance), - type_dict['relation']) - self.assertEqual(type_dict['relation'][0].name, 'DoNothing') - self.assertIs(type_dict['_id'][0], astroid.YES) - - def test_concat_interfaces(self): - cls = test_utils.extract_node(''' - class IMachin: pass - - class Correct2: - """docstring""" - __implements__ = (IMachin,) - - class BadArgument: - """docstring""" - __implements__ = (IMachin,) - - class InterfaceCanNowBeFound: #@ - """docstring""" - __implements__ = BadArgument.__implements__ + Correct2.__implements__ - ''') - interfaces = inspector.interfaces(cls) - self.assertEqual([i.name for i in interfaces], ['IMachin']) - - def test_interfaces(self): - module = astroid.parse(''' - class Interface(object): pass - class MyIFace(Interface): pass - class AnotherIFace(Interface): pass - class Concrete0(object): - __implements__ = MyIFace - class Concrete1: - __implements__ = (MyIFace, AnotherIFace) - class Concrete2: - __implements__ = (MyIFace, AnotherIFace) - class Concrete23(Concrete1): pass - ''') - - for klass, interfaces in (('Concrete0', ['MyIFace']), - ('Concrete1', ['MyIFace', 'AnotherIFace']), - ('Concrete2', ['MyIFace', 'AnotherIFace']), - ('Concrete23', ['MyIFace', 'AnotherIFace'])): - klass = module[klass] - self.assertEqual([i.name for i in inspector.interfaces(klass)], - interfaces) - - - def test_from_directory(self): - expected = os.path.join('pylint', 'test', 'data', '__init__.py') - self.assertEqual(self.project.name, 'data') - self.assertTrue(self.project.path.endswith(expected), self.project.path) - - def test_project_node(self): - expected = [ - 'data', 'data.clientmodule_test', - 'data.suppliermodule_test', - ] - self.assertListEqual(sorted(self.project.keys()), expected) - - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_pyreverse_writer.py b/pymode/libs/pylint/test/unittest_pyreverse_writer.py deleted file mode 100644 index 4fa964c2..00000000 --- a/pymode/libs/pylint/test/unittest_pyreverse_writer.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -""" -unittest for visitors.diadefs and extensions.diadefslib modules -""" - - -import os -import sys -import codecs -from os.path import join, dirname, abspath -from difflib import unified_diff -import unittest - -from astroid import MANAGER - -from pylint.pyreverse.inspector import Linker, project_from_files -from pylint.pyreverse.diadefslib import DefaultDiadefGenerator, DiadefsHandler -from pylint.pyreverse.writer import DotWriter -from pylint.pyreverse.utils import get_visibility - - -_DEFAULTS = { - 'all_ancestors': None, 'show_associated': None, - 'module_names': None, - 'output_format': 'dot', 'diadefs_file': None, 'quiet': 0, - 'show_ancestors': None, 'classes': (), 'all_associated': None, - 'mode': 'PUB_ONLY', 'show_builtin': False, 'only_classnames': False - } - -class Config(object): - """config object for tests""" - def __init__(self): - for attr, value in _DEFAULTS.items(): - setattr(self, attr, value) - - -def _file_lines(path): - # we don't care about the actual encoding, but python3 forces us to pick one - with codecs.open(path, encoding='latin1') as stream: - lines = [line.strip() for line in stream.readlines() - if (line.find('squeleton generated by ') == -1 and - not line.startswith('__revision__ = "$Id:'))] - return [line for line in lines if line] - -def get_project(module, name="No Name"): - """return a astroid project representation""" - def _astroid_wrapper(func, modname): - return func(modname) - return project_from_files([module], _astroid_wrapper, - project_name=name) - -CONFIG = Config() - -class DotWriterTC(unittest.TestCase): - - @classmethod - def setUpClass(cls): - project = get_project(os.path.join(os.path.dirname(__file__), 'data')) - linker = Linker(project) - handler = DiadefsHandler(CONFIG) - dd = DefaultDiadefGenerator(linker, handler).visit(project) - for diagram in dd: - diagram.extract_relationships() - writer = DotWriter(CONFIG) - writer.write(dd) - - @classmethod - def tearDownClass(cls): - for fname in ('packages_No_Name.dot', 'classes_No_Name.dot',): - try: - os.remove(fname) - except: - continue - - def _test_same_file(self, generated_file): - expected_file = os.path.join(os.path.dirname(__file__), 'data', generated_file) - generated = _file_lines(generated_file) - expected = _file_lines(expected_file) - generated = '\n'.join(generated) - expected = '\n'.join(expected) - files = "\n *** expected : %s, generated : %s \n" % ( - expected_file, generated_file) - self.assertEqual(expected, generated, '%s%s' % ( - files, '\n'.join(line for line in unified_diff( - expected.splitlines(), generated.splitlines() ))) ) - os.remove(generated_file) - - def test_package_diagram(self): - self._test_same_file('packages_No_Name.dot') - - def test_class_diagram(self): - self._test_same_file('classes_No_Name.dot') - - - -class GetVisibilityTC(unittest.TestCase): - - def test_special(self): - for name in ["__reduce_ex__", "__setattr__"]: - self.assertEqual(get_visibility(name), 'special') - - def test_private(self): - for name in ["__g_", "____dsf", "__23_9"]: - got = get_visibility(name) - self.assertEqual(got, 'private', - 'got %s instead of private for value %s' % (got, name)) - - def test_public(self): - self.assertEqual(get_visibility('simple'), 'public') - - def test_protected(self): - for name in ["_","__", "___", "____", "_____", "___e__", - "_nextsimple", "_filter_it_"]: - got = get_visibility(name) - self.assertEqual(got, 'protected', - 'got %s instead of protected for value %s' % (got, name)) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_reporters_json.py b/pymode/libs/pylint/test/unittest_reporters_json.py deleted file mode 100644 index 8f503f64..00000000 --- a/pymode/libs/pylint/test/unittest_reporters_json.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -"""Test for the JSON reporter.""" - -import json -import unittest - -import six - -from pylint.lint import PyLinter -from pylint import checkers -from pylint.reporters.json import JSONReporter - - -class TestJSONReporter(unittest.TestCase): - - def test_simple_json_output(self): - output = six.StringIO() - - reporter = JSONReporter() - linter = PyLinter(reporter=reporter) - checkers.initialize(linter) - - linter.config.persistent = 0 - linter.reporter.set_output(output) - linter.open() - linter.set_current_module('0123') - linter.add_message('line-too-long', line=1, args=(1, 2)) - - # we call this method because we didn't actually run the checkers - reporter.display_messages(None) - - expected_result = [[ - ("column", 0), - ("line", 1), - ("message", "Line too long (1/2)"), - ("module", "0123"), - ("obj", ""), - ("path", "0123"), - ("symbol", "line-too-long"), - ("type", "convention"), - ]] - report_result = json.loads(output.getvalue()) - report_result = [sorted(report_result[0].items(), - key=lambda item: item[0])] - self.assertEqual(report_result, expected_result) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_reporting.py b/pymode/libs/pylint/test/unittest_reporting.py deleted file mode 100644 index efe91124..00000000 --- a/pymode/libs/pylint/test/unittest_reporting.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import os -from os.path import join, dirname, abspath -import unittest - -import six - -from pylint import __pkginfo__ -from pylint.lint import PyLinter -from pylint import checkers -from pylint.reporters import BaseReporter -from pylint.reporters.text import TextReporter, ParseableTextReporter -from pylint.reporters.html import HTMLReporter -from pylint.reporters.ureports.nodes import Section -from pylint import testutils - - -HERE = abspath(dirname(__file__)) -INPUTDIR = join(HERE, 'input') - -class PyLinterTC(unittest.TestCase): - - def setUp(self): - self.linter = PyLinter(reporter=TextReporter()) - self.linter.disable('I') - self.linter.config.persistent = 0 - # register checkers - checkers.initialize(self.linter) - os.environ.pop('PYLINTRC', None) - - def test_template_option(self): - output = six.StringIO() - self.linter.reporter.set_output(output) - self.linter.set_option('msg-template', '{msg_id}:{line:03d}') - self.linter.open() - self.linter.set_current_module('0123') - self.linter.add_message('C0301', line=1, args=(1, 2)) - self.linter.add_message('line-too-long', line=2, args=(3, 4)) - self.assertMultiLineEqual(output.getvalue(), - '************* Module 0123\n' - 'C0301:001\n' - 'C0301:002\n') - - def test_parseable_output_deprecated(self): - with testutils.catch_warnings() as cm: - ParseableTextReporter() - - self.assertEqual(len(cm), 1) - self.assertIsInstance(cm[0].message, DeprecationWarning) - - def test_html_reporter_deprecated(self): - with testutils.catch_warnings() as caught: - HTMLReporter() - - self.assertEqual(len(caught), 1) - self.assertIsInstance(caught[0].message, DeprecationWarning) - self.assertEqual(str(caught[0].message), - 'This reporter will be removed in Pylint 2.0.') - - def test_parseable_output_regression(self): - output = six.StringIO() - with testutils.catch_warnings(): - linter = PyLinter(reporter=ParseableTextReporter()) - - checkers.initialize(linter) - linter.config.persistent = 0 - linter.reporter.set_output(output) - linter.set_option('output-format', 'parseable') - linter.open() - linter.set_current_module('0123') - linter.add_message('line-too-long', line=1, args=(1, 2)) - self.assertMultiLineEqual(output.getvalue(), - '************* Module 0123\n' - '0123:1: [C0301(line-too-long), ] ' - 'Line too long (1/2)\n') - - def test_html_reporter_msg_template(self): - expected = ''' - - -
-
-

Messages

- - - - - - - - - -
categorymsg_id
warningW0332
-
-
- -'''.strip().splitlines() - output = six.StringIO() - with testutils.catch_warnings(): - linter = PyLinter(reporter=HTMLReporter()) - - checkers.initialize(linter) - linter.config.persistent = 0 - linter.reporter.set_output(output) - linter.set_option('msg-template', '{category}{msg_id}') - linter.open() - linter.set_current_module('0123') - linter.add_message('lowercase-l-suffix', line=1) - linter.reporter.display_messages(Section()) - self.assertEqual(output.getvalue().splitlines(), expected) - - @unittest.expectedFailure - def test_html_reporter_type(self): - # Integration test for issue #263 - # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems - expected = ''' - -
-
-

Messages

- - - - - - - - - - - - - - - - - -
typemoduleobjectlinecol_offsetmessage
convention0123 10Exactly one space required before comparison -a< 5: print "zero"
-
-
- - -''' - output = six.StringIO() - with testutils.catch_warnings(): - linter = PyLinter(reporter=HTMLReporter()) - - checkers.initialize(linter) - linter.config.persistent = 0 - linter.reporter.set_output(output) - linter.open() - linter.set_current_module('0123') - linter.add_message('bad-whitespace', line=1, - args=('Exactly one', 'required', 'before', - 'comparison', 'a< 5: print "zero"')) - linter.reporter.display_reports(Section()) - self.assertMultiLineEqual(output.getvalue(), expected) - - def test_display_results_is_renamed(self): - class CustomReporter(TextReporter): - def _display(self, layout): - return None - - reporter = CustomReporter() - if __pkginfo__.numversion >= (2, 0): - with self.assertRaises(AttributeError): - reporter.display_results - else: - with testutils.catch_warnings() as cm: - reporter.display_results(Section()) - - self.assertEqual(len(cm), 1) - self.assertIsInstance(cm[0].message, DeprecationWarning) - - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/test/unittest_utils.py b/pymode/libs/pylint/test/unittest_utils.py deleted file mode 100644 index 5e2a82b2..00000000 --- a/pymode/libs/pylint/test/unittest_utils.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr -# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/master/COPYING - -import re -import unittest -import warnings - -import astroid - -from pylint import __pkginfo__ -from pylint import utils -from pylint import interfaces -from pylint.checkers.utils import check_messages - - -class PyLintASTWalkerTest(unittest.TestCase): - class MockLinter(object): - def __init__(self, msgs): - self._msgs = msgs - - def is_message_enabled(self, msgid): - return self._msgs.get(msgid, True) - - class Checker(object): - def __init__(self): - self.called = set() - - @check_messages('first-message') - def visit_module(self, module): - self.called.add('module') - - @check_messages('second-message') - def visit_call(self, module): - raise NotImplementedError - - @check_messages('second-message', 'third-message') - def visit_assignname(self, module): - self.called.add('assname') - - @check_messages('second-message') - def leave_assignname(self, module): - raise NotImplementedError - - def test_check_messages(self): - linter = self.MockLinter({'first-message': True, - 'second-message': False, - 'third-message': True}) - walker = utils.PyLintASTWalker(linter) - checker = self.Checker() - walker.add_checker(checker) - walker.walk(astroid.parse("x = func()")) - self.assertEqual(set(['module', 'assname']), checker.called) - - def test_deprecated_methods(self): - class Checker(object): - def __init__(self): - self.called = False - - @check_messages('first-message') - def visit_assname(self, node): - self.called = True - - linter = self.MockLinter({'first-message': True}) - walker = utils.PyLintASTWalker(linter) - checker = Checker() - walker.add_checker(checker) - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - walker.walk(astroid.parse("x = 1")) - - if __pkginfo__.numversion < (2, 0): - expected = ('Implemented method visit_assname instead of ' - 'visit_assignname. This will be supported until ' - 'Pylint 2.0.') - self.assertEqual(len(w), 1) - self.assertIsInstance(w[0].message, PendingDeprecationWarning) - self.assertEqual(str(w[0].message), expected) - self.assertTrue(checker.called) - else: - self.assertNotEqual(len(w), 1) - self.assertFalse(checker.called) - - -class RegexBlacklistTest(unittest.TestCase): - def test__basename_in_blacklist_re_match(self): - patterns = [re.compile(".*enchilada.*"), re.compile("unittest_.*")] - self.assertTrue(utils._basename_in_blacklist_re("unittest_utils.py", patterns)) - self.assertTrue(utils._basename_in_blacklist_re("cheese_enchiladas.xml", patterns)) - - def test__basename_in_blacklist_re_nomatch(self): - patterns = [re.compile(".*enchilada.*"), re.compile("unittest_.*")] - self.assertFalse(utils._basename_in_blacklist_re("test_utils.py", patterns)) - self.assertFalse(utils._basename_in_blacklist_re("enchilad.py", patterns)) - -if __name__ == '__main__': - unittest.main() diff --git a/pymode/libs/pylint/testutils.py b/pymode/libs/pylint/testutils.py index 5e3d5386..a9d8f5b4 100644 --- a/pymode/libs/pylint/testutils.py +++ b/pymode/libs/pylint/testutils.py @@ -1,5 +1,7 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2012-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2013-2016 Claudiu Popa + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -15,9 +17,7 @@ from os.path import abspath, basename, dirname, isdir, join, splitext import sys import re -import unittest import tempfile -import warnings import tokenize import six @@ -119,16 +119,41 @@ def finalize(self): self.reset() return result + # pylint: disable=unused-argument + def on_set_current_module(self, module, filepath): + pass + # pylint: enable=unused-argument + def display_reports(self, layout): """ignore layouts""" _display = None +class MinimalTestReporter(BaseReporter): + + def handle_message(self, msg): + self.messages.append(msg) + + def on_set_current_module(self, module, filepath): + self.messages = [] + + _display = None + + class Message(collections.namedtuple('Message', - ['msg_id', 'line', 'node', 'args'])): - def __new__(cls, msg_id, line=None, node=None, args=None): - return tuple.__new__(cls, (msg_id, line, node, args)) + ['msg_id', 'line', 'node', 'args', 'confidence'])): + def __new__(cls, msg_id, line=None, node=None, args=None, confidence=None): + return tuple.__new__(cls, (msg_id, line, node, args, confidence)) + + def __eq__(self, other): + if isinstance(other, Message): + if self.confidence and other.confidence: + return super(Message, self).__eq__(other) + return self[:-1] == other[:-1] + return NotImplemented # pragma: no cover + + __hash__ = None class UnittestLinter(object): @@ -145,11 +170,10 @@ def release_messages(self): finally: self._messages = [] - def add_message(self, msg_id, line=None, node=None, args=None, - confidence=None): - self._messages.append(Message(msg_id, line, node, args)) + def add_message(self, msg_id, line=None, node=None, args=None, confidence=None): + self._messages.append(Message(msg_id, line, node, args, confidence)) - def is_message_enabled(self, *unused_args): + def is_message_enabled(self, *unused_args, **unused_kwargs): return True def add_stats(self, **kwargs): @@ -177,12 +201,12 @@ def _forward(self): return _wrapper -class CheckerTestCase(unittest.TestCase): - """A base testcase class for unittesting individual checker classes.""" +class CheckerTestCase(object): + """A base testcase class for unit testing individual checker classes.""" CHECKER_CLASS = None CONFIG = {} - def setUp(self): + def setup_method(self): self.linter = UnittestLinter() self.checker = self.CHECKER_CLASS(self.linter) # pylint: disable=not-callable for key, value in six.iteritems(self.CONFIG): @@ -208,7 +232,7 @@ def assertAddsMessages(self, *messages): msg = ('Expected messages did not match actual.\n' 'Expected:\n%s\nGot:\n%s' % ('\n'.join(repr(m) for m in messages), '\n'.join(repr(m) for m in got))) - self.assertEqual(list(messages), got, msg) + assert list(messages) == got, msg def walk(self, node): """recursive walk on the given node""" @@ -240,7 +264,7 @@ def exception_str(self, ex): # pylint: disable=unused-argument # Test classes -class LintTestUsingModule(unittest.TestCase): +class LintTestUsingModule(object): INPUT_DIR = None DEFAULT_PACKAGE = 'input' package = DEFAULT_PACKAGE @@ -249,21 +273,12 @@ class LintTestUsingModule(unittest.TestCase): depends = None output = None _TEST_TYPE = 'module' - maxDiff = None - def shortDescription(self): - values = {'mode' : self._TEST_TYPE, - 'input': self.module, - 'pkg': self.package, - 'cls': self.__class__.__name__} + # def runTest(self): + # # This is a hack to make ./test/test_func.py work under pytest. + # pass - if self.package == self.DEFAULT_PACKAGE: - msg = '%(mode)s test of input file "%(input)s" (%(cls)s)' - else: - msg = '%(mode)s test of input file "%(input)s" in "%(pkg)s" (%(cls)s)' - return msg % values - - def test_functionality(self): + def _test_functionality(self): tocheck = [self.package+'.'+self.module] # pylint: disable=not-an-iterable; can't handle boolean checks for now if self.depends: @@ -272,8 +287,7 @@ def test_functionality(self): self._test(tocheck) def _check_result(self, got): - self.assertMultiLineEqual(self._get_expected().strip()+'\n', - got.strip()+'\n') + assert self._get_expected().strip()+'\n' == got.strip()+'\n' def _test(self, tocheck): if INFO_TEST_RGX.match(self.module): @@ -305,7 +319,7 @@ class LintTestUsingFile(LintTestUsingModule): _TEST_TYPE = 'file' - def test_functionality(self): + def _test_functionality(self): importable = join(self.INPUT_DIR, self.module) # python also prefers packages over simple modules. if not isdir(importable): @@ -330,51 +344,11 @@ def _check_result(self, got): with open(self.output, 'w') as fobj: fobj.write(got) -# Callback - -def cb_test_gen(base_class): - def call(input_dir, msg_dir, module_file, messages_file, dependencies): - # pylint: disable=no-init - class LintTC(base_class): - module = module_file.replace('.py', '') - output = messages_file - depends = dependencies or None - INPUT_DIR = input_dir - MSG_DIR = msg_dir - return LintTC - return call - -# Main function - -def make_tests(input_dir, msg_dir, filter_rgx, callbacks): - """generate tests classes from test info - - return the list of generated test classes - """ - if filter_rgx: - is_to_run = re.compile(filter_rgx).search - else: - is_to_run = lambda x: 1 - tests = [] - for module_file, messages_file in ( - get_tests_info(input_dir, msg_dir, 'func_', '') - ): - if not is_to_run(module_file) or module_file.endswith(('.pyc', "$py.class")): - continue - base = module_file.replace('func_', '').replace('.py', '') - - dependencies = get_tests_info(input_dir, msg_dir, base, '.py') - - for callback in callbacks: - test = callback(input_dir, msg_dir, module_file, messages_file, - dependencies) - if test: - tests.append(test) - return tests def tokenize_str(code): return list(tokenize.generate_tokens(StringIO(code).readline)) + @contextlib.contextmanager def create_tempfile(content=None): """Create a new temporary file. @@ -406,11 +380,3 @@ def create_file_backed_module(code): module = astroid.parse(code) module.file = temp yield module - - -@contextlib.contextmanager -def catch_warnings(warnfilter="always"): - """Suppress the warnings in the surrounding block.""" - with warnings.catch_warnings(record=True) as cm: - warnings.simplefilter(warnfilter) - yield cm diff --git a/pymode/libs/pylint/utils.py b/pymode/libs/pylint/utils.py index dd214032..1ace5939 100644 --- a/pymode/libs/pylint/utils.py +++ b/pymode/libs/pylint/utils.py @@ -1,5 +1,12 @@ -# Copyright (c) 2003-2016 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr +# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) +# Copyright (c) 2012-2014 Google, Inc. +# Copyright (c) 2014 Brett Cannon +# Copyright (c) 2014-2016 Claudiu Popa +# Copyright (c) 2015 Aru Sahni +# Copyright (c) 2015 Florian Bruhin +# Copyright (c) 2016 Ashley Whetter +# Copyright (c) 2016 Glenn Matthews + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING @@ -9,31 +16,24 @@ from __future__ import print_function import collections -import itertools +from inspect import cleandoc import os from os.path import dirname, basename, splitext, exists, isdir, join, normpath import re import sys +import tokenize import warnings import textwrap -import tokenize import six from six.moves import zip # pylint: disable=redefined-builtin from astroid import nodes, Module -from astroid.modutils import modpath_from_file, get_module_files, \ - file_from_modpath, load_module_from_file +from astroid import modutils from pylint.interfaces import IRawChecker, ITokenChecker, UNDEFINED, implements from pylint.reporters.ureports.nodes import Section - - -class UnknownMessage(Exception): - """raised when a unregistered message id is encountered""" - -class EmptyReport(Exception): - """raised when a report is empty and so should not be displayed""" +from pylint.exceptions import InvalidMessageError, UnknownMessageError, EmptyReportError MSG_TYPES = { @@ -55,20 +55,6 @@ class EmptyReport(Exception): 'F' : 1 } -DEPRECATED_ALIASES = { - # New name, deprecated name. - 'repr': 'backquote', - 'expr': 'discard', - 'assignname': 'assname', - 'assignattr': 'assattr', - 'attribute': 'getattr', - 'call': 'callfunc', - 'importfrom': 'from', - 'classdef': 'class', - 'functiondef': 'function', - 'generatorexp': 'genexpr', -} - _MSG_ORDER = 'EWRCIF' MSG_STATE_SCOPE_CONFIG = 0 MSG_STATE_SCOPE_MODULE = 1 @@ -156,7 +142,7 @@ def build_message_def(checker, msgid, msg_tuple): if len(msg_tuple) > 3: (msg, symbol, descr, options) = msg_tuple elif len(msg_tuple) > 2: - (msg, symbol, descr) = msg_tuple[:3] + (msg, symbol, descr) = msg_tuple else: # messages should have a symbol, but for backward compatibility # they may not. @@ -172,9 +158,11 @@ class MessageDefinition(object): def __init__(self, checker, msgid, msg, descr, symbol, scope, minversion=None, maxversion=None, old_names=None): self.checker = checker - assert len(msgid) == 5, 'Invalid message id %s' % msgid - assert msgid[0] in MSG_TYPES, \ - 'Bad message type %s in %r' % (msgid[0], msgid) + if len(msgid) != 5: + raise InvalidMessageError('Invalid message id %r' % msgid) + if not msgid[0] in MSG_TYPES: + raise InvalidMessageError( + 'Bad message type %s in %r' % (msgid[0], msgid)) self.msgid = msgid self.msg = msg self.descr = descr @@ -231,58 +219,79 @@ def __init__(self): self.msg_status = 0 def _checker_messages(self, checker): - for checker in self._checkers[checker.lower()]: - for msgid in checker.msgs: + for known_checker in self._checkers[checker.lower()]: + for msgid in known_checker.msgs: yield msgid def disable(self, msgid, scope='package', line=None, ignore_unknown=False): """don't output message of the given id""" + self._set_msg_status(msgid, enable=False, scope=scope, + line=line, ignore_unknown=ignore_unknown) + + def enable(self, msgid, scope='package', line=None, ignore_unknown=False): + """reenable message of the given id""" + self._set_msg_status(msgid, enable=True, scope=scope, + line=line, ignore_unknown=ignore_unknown) + + def _set_msg_status(self, msgid, enable, scope='package', line=None, ignore_unknown=False): assert scope in ('package', 'module') - # handle disable=all by disabling all categories + if msgid == 'all': - for msgid in MSG_TYPES: - self.disable(msgid, scope, line) + for _msgid in MSG_TYPES: + self._set_msg_status(_msgid, enable, scope, line, ignore_unknown) + if enable and not self._python3_porting_mode: + # Don't activate the python 3 porting checker if it wasn't activated explicitly. + self.disable('python3') return + # msgid is a category? catid = category_id(msgid) if catid is not None: for _msgid in self.msgs_store._msgs_by_category.get(catid): - self.disable(_msgid, scope, line) + self._set_msg_status(_msgid, enable, scope, line) return + # msgid is a checker name? if msgid.lower() in self._checkers: msgs_store = self.msgs_store for checker in self._checkers[msgid.lower()]: for _msgid in checker.msgs: if _msgid in msgs_store._alternative_names: - self.disable(_msgid, scope, line) + self._set_msg_status(_msgid, enable, scope, line) return + # msgid is report id? if msgid.lower().startswith('rp'): - self.disable_report(msgid) + if enable: + self.enable_report(msgid) + else: + self.disable_report(msgid) return try: # msgid is a symbolic or numeric msgid. msg = self.msgs_store.check_message_id(msgid) - except UnknownMessage: + except UnknownMessageError: if ignore_unknown: return raise if scope == 'module': - self.file_state.set_msg_status(msg, line, False) - if msg.symbol != 'locally-disabled': + self.file_state.set_msg_status(msg, line, enable) + if enable: + self.add_message('locally-enabled', line=line, + args=(msg.symbol, msg.msgid)) + elif msg.symbol != 'locally-disabled': self.add_message('locally-disabled', line=line, args=(msg.symbol, msg.msgid)) - else: msgs = self._msgs_state - msgs[msg.msgid] = False + msgs[msg.msgid] = enable # sync configuration object - self.config.disable = [self._message_symbol(mid) - for mid, val in six.iteritems(msgs) - if not val] + self.config.enable = [self._message_symbol(mid) for mid, val + in sorted(six.iteritems(msgs)) if val] + self.config.disable = [self._message_symbol(mid) for mid, val + in sorted(six.iteritems(msgs)) if not val] def _message_symbol(self, msgid): """Get the message symbol of the given message id @@ -292,54 +301,9 @@ def _message_symbol(self, msgid): """ try: return self.msgs_store.check_message_id(msgid).symbol - except UnknownMessage: + except UnknownMessageError: return msgid - def enable(self, msgid, scope='package', line=None, ignore_unknown=False): - """reenable message of the given id""" - assert scope in ('package', 'module') - if msgid == 'all': - for msgid_ in MSG_TYPES: - self.enable(msgid_, scope=scope, line=line) - if not self._python3_porting_mode: - # Don't activate the python 3 porting checker if it - # wasn't activated explicitly. - self.disable('python3') - return - catid = category_id(msgid) - # msgid is a category? - if catid is not None: - for msgid in self.msgs_store._msgs_by_category.get(catid): - self.enable(msgid, scope, line) - return - # msgid is a checker name? - if msgid.lower() in self._checkers: - for checker in self._checkers[msgid.lower()]: - for msgid_ in checker.msgs: - self.enable(msgid_, scope, line) - return - # msgid is report id? - if msgid.lower().startswith('rp'): - self.enable_report(msgid) - return - - try: - # msgid is a symbolic or numeric msgid. - msg = self.msgs_store.check_message_id(msgid) - except UnknownMessage: - if ignore_unknown: - return - raise - - if scope == 'module': - self.file_state.set_msg_status(msg, line, True) - self.add_message('locally-enabled', line=line, args=(msg.symbol, msg.msgid)) - else: - msgs = self._msgs_state - msgs[msg.msgid] = True - # sync configuration object - self.config.enable = [mid for mid, val in six.iteritems(msgs) if val] - def get_message_state_scope(self, msgid, line=None, confidence=UNDEFINED): """Returns the scope at which a message was enabled/disabled.""" if self.config.confidence and confidence.name not in self.config.confidence: @@ -361,7 +325,7 @@ def is_message_enabled(self, msg_descr, line=None, confidence=None): return False try: msgid = self.msgs_store.check_message_id(msg_descr).msgid - except UnknownMessage: + except UnknownMessageError: # The linter checks for messages that are not registered # due to version mismatch, just treat them as message IDs # for now. @@ -390,11 +354,18 @@ def add_message(self, msg_descr, line=None, node=None, args=None, confidence=UND # does not apply to them. if msgid[0] not in _SCOPE_EXEMPT: if msg_info.scope == WarningScope.LINE: - assert node is None and line is not None, ( - 'Message %s must only provide line, got line=%s, node=%s' % (msgid, line, node)) + if line is None: + raise InvalidMessageError( + 'Message %s must provide line, got None' % msgid) + if node is not None: + raise InvalidMessageError( + 'Message %s must only provide line, ' + 'got line=%s, node=%s' % (msgid, line, node)) elif msg_info.scope == WarningScope.NODE: # Node-based warnings may provide an override line. - assert node is not None, 'Message %s must provide Node, got None' + if node is None: + raise InvalidMessageError( + 'Message %s must provide Node, got None' % msgid) if line is None and node is not None: line = node.fromlineno @@ -434,13 +405,16 @@ def add_message(self, msg_descr, line=None, node=None, args=None, confidence=UND Message(msgid, symbol, (abspath, path, module, obj, line or 1, col_offset or 0), msg, confidence)) - def print_full_documentation(self): + def print_full_documentation(self, stream=None): """output a full documentation in ReST format""" - print("Pylint global options and switches") - print("----------------------------------") - print("") - print("Pylint provides global options and switches.") - print("") + if not stream: + stream = sys.stdout + + print("Pylint global options and switches", file=stream) + print("----------------------------------", file=stream) + print("", file=stream) + print("Pylint provides global options and switches.", file=stream) + print("", file=stream) by_checker = {} for checker in self.get_checkers(): @@ -451,63 +425,94 @@ def print_full_documentation(self): title = 'General options' else: title = '%s options' % section.capitalize() - print(title) - print('~' * len(title)) - _rest_format_section(sys.stdout, None, options) - print("") + print(title, file=stream) + print('~' * len(title), file=stream) + _rest_format_section(stream, None, options) + print("", file=stream) else: + name = checker.name try: - by_checker[checker.name][0] += checker.options_and_values() - by_checker[checker.name][1].update(checker.msgs) - by_checker[checker.name][2] += checker.reports + by_checker[name]['options'] += checker.options_and_values() + by_checker[name]['msgs'].update(checker.msgs) + by_checker[name]['reports'] += checker.reports except KeyError: - by_checker[checker.name] = [list(checker.options_and_values()), - dict(checker.msgs), - list(checker.reports)] - - print("Pylint checkers' options and switches") - print("-------------------------------------") - print("") - print("Pylint checkers can provide three set of features:") - print("") - print("* options that control their execution,") - print("* messages that they can raise,") - print("* reports that they can generate.") - print("") - print("Below is a list of all checkers and their features.") - print("") - - for checker, (options, msgs, reports) in six.iteritems(by_checker): - title = '%s checker' % (checker.replace("_", " ").title()) - print(title) - print('~' * len(title)) - print("") - print("Verbatim name of the checker is ``%s``." % checker) - print("") - if options: - title = 'Options' - print(title) - print('^' * len(title)) - _rest_format_section(sys.stdout, None, options) - print("") - if msgs: - title = 'Messages' - print(title) - print('~' * len(title)) - for msgid, msg in sorted(six.iteritems(msgs), - key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1])): - msg = build_message_def(checker, msgid, msg) - print(msg.format_help(checkerref=False)) - print("") - if reports: - title = 'Reports' - print(title) - print('~' * len(title)) - for report in reports: - print(':%s: %s' % report[:2]) - print("") - print("") - + by_checker[name] = { + 'options': list(checker.options_and_values()), + 'msgs': dict(checker.msgs), + 'reports': list(checker.reports), + } + + print("Pylint checkers' options and switches", file=stream) + print("-------------------------------------", file=stream) + print("", file=stream) + print("Pylint checkers can provide three set of features:", file=stream) + print("", file=stream) + print("* options that control their execution,", file=stream) + print("* messages that they can raise,", file=stream) + print("* reports that they can generate.", file=stream) + print("", file=stream) + print("Below is a list of all checkers and their features.", file=stream) + print("", file=stream) + + for checker, info in six.iteritems(by_checker): + self._print_checker_doc(checker, info, stream=stream) + + @staticmethod + def _print_checker_doc(checker_name, info, stream=None): + """Helper method for print_full_documentation. + + Also used by doc/exts/pylint_extensions.py. + """ + if not stream: + stream = sys.stdout + + doc = info.get('doc') + module = info.get('module') + msgs = info.get('msgs') + options = info.get('options') + reports = info.get('reports') + + title = '%s checker' % (checker_name.replace("_", " ").title()) + + if module: + # Provide anchor to link against + print(".. _%s:\n" % module, file=stream) + print(title, file=stream) + print('~' * len(title), file=stream) + print("", file=stream) + if module: + print("This checker is provided by ``%s``." % module, file=stream) + print("Verbatim name of the checker is ``%s``." % checker_name, file=stream) + print("", file=stream) + if doc: + title = 'Documentation' + print(title, file=stream) + print('^' * len(title), file=stream) + print(cleandoc(doc), file=stream) + print("", file=stream) + if options: + title = 'Options' + print(title, file=stream) + print('^' * len(title), file=stream) + _rest_format_section(stream, None, options) + print("", file=stream) + if msgs: + title = 'Messages' + print(title, file=stream) + print('^' * len(title), file=stream) + for msgid, msg in sorted(six.iteritems(msgs), + key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1])): + msg = build_message_def(checker_name, msgid, msg) + print(msg.format_help(checkerref=False), file=stream) + print("", file=stream) + if reports: + title = 'Reports' + print(title, file=stream) + print('^' * len(title), file=stream) + for report in reports: + print(':%s: %s' % report[:2], file=stream) + print("", file=stream) + print("", file=stream) class FileState(object): """Hold internal state specific to the currently analyzed file""" @@ -529,8 +534,8 @@ def collect_block_lines(self, msgs_store, module_node): self._collect_block_lines(msgs_store, module_node, orig_state) def _collect_block_lines(self, msgs_store, node, msg_state): - """Recursivly walk (depth first) AST to collect block level options line - numbers. + """Recursively walk (depth first) AST to collect block level options + line numbers. """ for child in node.get_children(): self._collect_block_lines(msgs_store, child, msg_state) @@ -650,8 +655,8 @@ def add_renamed_message(self, old_id, old_symbol, new_symbol): """ msg = self.check_message_id(new_symbol) msg.old_names.append((old_id, old_symbol)) - self._alternative_names[old_id] = msg - self._alternative_names[old_symbol] = msg + self._register_alternative_name(msg, old_id) + self._register_alternative_name(msg, old_symbol) def register_messages(self, checker): """register a dictionary of messages @@ -663,29 +668,42 @@ def register_messages(self, checker): are the checker id and the two last the message id in this checker """ chkid = None - for msgid, msg_tuple in six.iteritems(checker.msgs): + for msgid, msg_tuple in sorted(six.iteritems(checker.msgs)): msg = build_message_def(checker, msgid, msg_tuple) - assert msg.symbol not in self._messages, \ - 'Message symbol %r is already defined' % msg.symbol # avoid duplicate / malformed ids - assert msg.msgid not in self._alternative_names, \ - 'Message id %r is already defined' % msgid - assert chkid is None or chkid == msg.msgid[1:3], \ - 'Inconsistent checker part in message id %r' % msgid + if msg.symbol in self._messages or msg.symbol in self._alternative_names: + raise InvalidMessageError( + 'Message symbol %r is already defined' % msg.symbol) + if chkid is not None and chkid != msg.msgid[1:3]: + raise InvalidMessageError( + "Inconsistent checker part in message id %r (expected 'x%sxx')" + % (msgid, chkid)) chkid = msg.msgid[1:3] self._messages[msg.symbol] = msg - self._alternative_names[msg.msgid] = msg + self._register_alternative_name(msg, msg.msgid) for old_id, old_symbol in msg.old_names: - self._alternative_names[old_id] = msg - self._alternative_names[old_symbol] = msg + self._register_alternative_name(msg, old_id) + self._register_alternative_name(msg, old_symbol) self._msgs_by_category[msg.msgid[0]].append(msg.msgid) + def _register_alternative_name(self, msg, name): + """helper for register_message()""" + if name in self._messages and self._messages[name] != msg: + raise InvalidMessageError( + 'Message symbol %r is already defined' % name) + if name in self._alternative_names and self._alternative_names[name] != msg: + raise InvalidMessageError( + 'Message %s %r is already defined' % ( + 'id' if len(name) == 5 and name[0] in MSG_TYPES else 'alternate name', + name)) + self._alternative_names[name] = msg + def check_message_id(self, msgid): """returns the Message object for this message. msgid may be either a numeric or symbolic id. - Raises UnknownMessage if the message id is not defined. + Raises UnknownMessageError if the message id is not defined. """ if msgid[1:].isdigit(): msgid = msgid.upper() @@ -694,7 +712,7 @@ def check_message_id(self, msgid): return source[msgid] except KeyError: pass - raise UnknownMessage('No such message id %s' % msgid) + raise UnknownMessageError('No such message id %s' % msgid) def get_msg_display_string(self, msgid): """Generates a user-consumable representation of a message. @@ -709,7 +727,7 @@ def help_message(self, msgids): try: print(self.check_message_id(msgid).format_help(checkerref=True)) print("") - except UnknownMessage as ex: + except UnknownMessageError as ex: print(ex) print("") continue @@ -776,7 +794,7 @@ def make_reports(self, stats, old_stats): report_sect = Section(r_title) try: r_cb(report_sect, stats, old_stats) - except EmptyReport: + except EmptyReportError: continue report_sect.report_id = reportid sect.append(report_sect) @@ -808,6 +826,13 @@ def _basename_in_blacklist_re(base_name, black_list_re): return True return False +def _modpath_from_file(filename, is_namespace): + def _is_package_cb(path, parts): + return modutils.check_modpath_has_init(path, parts) or is_namespace + + return modutils.modpath_from_file_with_callback(filename, is_package_cb=_is_package_cb) + + def expand_modules(files_or_modules, black_list, black_list_re): """take a list of files/modules/packages and return the list of tuple (file, module name) which have to be actually checked @@ -818,7 +843,7 @@ def expand_modules(files_or_modules, black_list, black_list_re): if exists(something): # this is a file or a directory try: - modname = '.'.join(modpath_from_file(something)) + modname = '.'.join(modutils.modpath_from_file(something)) except ImportError: modname = splitext(basename(something))[0] if isdir(something): @@ -829,7 +854,7 @@ def expand_modules(files_or_modules, black_list, black_list_re): # suppose it's a module or package modname = something try: - filepath = file_from_modpath(modname.split('.')) + filepath = modutils.file_from_modpath(modname.split('.')) if filepath is None: continue except (ImportError, SyntaxError) as ex: @@ -837,17 +862,37 @@ def expand_modules(files_or_modules, black_list, black_list_re): # removed as soon as possible http://bugs.python.org/issue10588 errors.append({'key': 'fatal', 'mod': modname, 'ex': ex}) continue + filepath = normpath(filepath) - result.append({'path': filepath, 'name': modname, 'isarg': True, - 'basepath': filepath, 'basename': modname}) - if not (modname.endswith('.__init__') or modname == '__init__') \ - and '__init__.py' in filepath: - for subfilepath in get_module_files(dirname(filepath), black_list): + modparts = (modname or something).split('.') + + try: + spec = modutils.file_info_from_modpath(modparts, path=sys.path) + except ImportError: + # Might not be acceptable, don't crash. + is_namespace = False + is_directory = isdir(something) + else: + is_namespace = modutils.is_namespace(spec) + is_directory = modutils.is_directory(spec) + + if not is_namespace: + result.append({'path': filepath, 'name': modname, 'isarg': True, + 'basepath': filepath, 'basename': modname}) + + has_init = (not (modname.endswith('.__init__') or modname == '__init__') + and '__init__.py' in filepath) + + if has_init or is_namespace or is_directory: + for subfilepath in modutils.get_module_files(dirname(filepath), black_list, + list_all=is_namespace): if filepath == subfilepath: continue if _basename_in_blacklist_re(basename(subfilepath), black_list_re): continue - submodname = '.'.join(modpath_from_file(subfilepath)) + + modpath = _modpath_from_file(subfilepath, is_namespace) + submodname = '.'.join(modpath) result.append({'path': subfilepath, 'name': submodname, 'isarg': False, 'basepath': filepath, 'basename': modname}) @@ -912,27 +957,11 @@ def walk(self, astroid): # In this case, favour the methods for the deprecated # alias if any, in order to maintain backwards # compatibility. - old_cid = DEPRECATED_ALIASES.get(cid) visit_events = () leave_events = () - if old_cid: - visit_events = self.visit_events.get(old_cid, ()) - leave_events = self.leave_events.get(old_cid, ()) - if visit_events or leave_events: - msg = ("Implemented method {meth}_{old} instead of {meth}_{new}. " - "This will be supported until Pylint 2.0.") - if visit_events: - warnings.warn(msg.format(meth="visit", old=old_cid, new=cid), - PendingDeprecationWarning) - if leave_events: - warnings.warn(msg.format(meth="leave", old=old_cid, new=cid), - PendingDeprecationWarning) - - visit_events = itertools.chain(visit_events, - self.visit_events.get(cid, ())) - leave_events = itertools.chain(leave_events, - self.leave_events.get(cid, ())) + visit_events = self.visit_events.get(cid, ()) + leave_events = self.leave_events.get(cid, ()) if astroid.is_statement: self.nbstatements += 1 @@ -960,7 +989,7 @@ def register_plugins(linter, directory): if extension in PY_EXTS and base != '__init__' or ( not extension and isdir(join(directory, base))): try: - module = load_module_from_file(join(directory, filename)) + module = modutils.load_module_from_file(join(directory, filename)) except ValueError: # empty module name (usually emacs auto-save files) continue @@ -1098,7 +1127,7 @@ def _format_option_value(optdict, value): # compiled regexp value = value.pattern elif optdict.get('type') == 'yn': - value = value and 'yes' or 'no' + value = 'yes' if value else 'no' elif isinstance(value, six.string_types) and value.isspace(): value = "'%s'" % value return value diff --git a/pymode/libs/wrapt/__init__.py b/pymode/libs/wrapt/__init__.py index 6e8e5e9f..4ce674b4 100644 --- a/pymode/libs/wrapt/__init__.py +++ b/pymode/libs/wrapt/__init__.py @@ -1,4 +1,4 @@ -__version_info__ = ('1', '10', '8') +__version_info__ = ('1', '10', '10') __version__ = '.'.join(__version_info__) from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, diff --git a/pymode/libs/wrapt/_wrappers.so b/pymode/libs/wrapt/_wrappers.so deleted file mode 100755 index 6b773f4da8f36c0018afc01475737f56e4c6dc37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47640 zcmeHw3w%`7)$d6lfV>h^5K(ZTyhI@h5(O1Zc+O}7k%!`gPC_z}Xh?=+BA``MAuZz+ zoBCPxYio_IT52uk>$QITyh@`|K-=2XdM#CyT&tfaMQVHjRZH%F?Y-8SbIzPe20q*0 z{oR|BoU`|TueJ7C`@Q#>y=Q*^+2P~;4I{0OVHg8&5611wFpNgHbe)NNf0|(ggUc7J zT&{wgk9;RI7$Z&t(Wsj^g26~=V}yMAa>ti*iVlBds&)zYWnSg=I2F&hZJBC>?PlFc_?_-cVUx9;~chQ=_o6JhCp+lJ9c_gxzs4NjdRy zonNrLz(&buzmHuPrg9~dsch*A2CJ)rb(_|$uBi%!BelTZ@nvatgX#w-S%pykUnw-W z!Qk2&TQy0DFDqX&7qbjucYMp3MoutTRob0>C6K3UD`ysAdwi7MRm8woFj!t1DHTNV zJJZ`aSJRq?YL~F19>+zMFBn{17q7*M@ilPfY_!SQ?X%ZuVxe;N;|>N31B5L!=Vq4V5O_$L^~AcRR-^+UM25jGh9ufk1w-E9~!SDRf`xti`}o9ZH=b<^ffE8hg9 zn2d>VDBk@@C*{Mrj47SHS8opV=D`17Ik3VXeRo;0Kl-_OU>bVb&A0fB$N+!zp!q)u z#%{^-H+Dr%_wSvjIwOBqW_^EuY|((O;v5i13Xyst!%3V+vG_Od9&p{NuI7C7v}-cY znGdGuXN9r3Ba0eaBV+urxdZ&M@W?4uTp+OZGH$ufT|<2p=q{IQw- zZFzN|nUgV}%57csLgqPJR6+S;w<{|$Itt@5lPsCbNamCC5yjrtE?lc#Sfj3KiSquq z{Cjz#vnvARVyp1%)@{TTq(|DwQ z1XAQD3yv$MJ^pCk0gwtI7C}fLx;OWYBINJb+*fj25n32MVqT=<3m~Tl29VPTrp%7+ zS9w|R)q)_U!LpxnN$h#eAN?36!GODL2KRs`Bm5}4iTDDP zOSpy{nr^N;4?&w}f4TsLReu_ET}`?^py;9*?FbFTZbuYvnOhNrct;|+fQ8YI;>qn; z3>x@UIS)^uZluU!85fXpRZp(SfeHhPcT$PR<3XKqmfvfE=uy;sspSKa{RLfrYHY0^ zE_FK|l#Yy`%FG4e$bZ#-B$g9zD;zV`>3k$X>hnEF0k?sxFOam=WFu|kF&U8h80XKA z^G~w)FC+d>Fvtr(#i;GwyP%U=P~o;A8o=T zd@(ZEAFJ=A`mkmqBvjjWwK3X1J=~ z2vB)jzKv-R*>*bQZ2j2Br1eYf$EX8wls~n< zf)xeJsZaP5x&^9Jn`e(jcIrAmkqY5+mHLdq2!%N_{g=#s2u&e#3w2}Wqi7)^T(s7 zcn>|rp;OG|;6huPiull;jub{e(^dESf>o;ecKi zISzJFEIPJjlT~aSPkMLp6h=*F`jhsb$@+s#l`?eH{d5-rIGKjNc=xbaS>^~rFNk7x z1WiUzzB7or8ox8h)zvu1t9bkUZ`5gRJ@r(`H{_~wRL>!Eh=_7eAgUA*krp3rNtHGt z=6euTDv9WK6Kx%!HNL9$oOrcvfe z^o3?rlOI#$EByXThGe5=W^Nfsol@)yRP7;SD4=ny3P8!s+8Y_6>a;()#~cN5RO`&f zbVbg)LB+2J_3xmMG0#=;)1baYskp^&K86({>a%J~hcmal408jqB1~?+o<)%~wq|bm zE0v}?aV z+IM`%3t9sjXWjwI&`iXL96TLbDeM@9eU6A}VD@+Q2}BPRM%&SrMqXDSeaQ=&cZnm7 z?;~DY0(F8SFX)84jWzVe~lW4(3OQLG_)7BU$e3#mp+RaRz1v@!3_!1ez$sG7h5J&^QyjlKQc? z(T&1%bj3d(hv-mBnT=l@CplY5b^H|}5PjGo`V&jE7NQ+{z>|4S1DUACN18vPZm&e$ zR#Ud){=Ey@i3)c=yKTyiW!yp$M;Gh^sZ|9<7wp97@)uMG-4ynr4Vw=j!DtFEQzh93 zhUon9NWy|v@?^oYk30k5X`_PoZyQcy1jhWsC=87G?S!HXCpn5bX(obBfQ6F-Jkp~bn}7e7lGK<#?vr73T-)a%T{Ek`4B9} zxJrb`{G#aJWGMczvW({VnOhEG%%d9n0fof|sgc+p9aI$kRFB2z(ACmM55+Hni-ux~ z6Js$d=U<)er=x)4LGBKW%b{Hip+>?hi1*OXn9nE^sI&P9jhdoEcXc#!njV6yK~;U# z{YXY2wtPG~x8VgS;><17@f1dHZKI(cjTqGH$B)GHY(Z`p^&G=c2hCreLp+~R1B`w^ zam!Hs7L{*N)Kod6+UJo-W}s^*byo|~T^&U#X#s;U=W?ZMP-f#Vp_voaaR=-wjDD`N z0ZnT(C22EqI}qK2E~`G%oKGgi^0uKe2fF&Paf8gW5G-az#$%-@w$Tb9`e!n&pNa-^ zh(t4BX=dXzm=U+O;~bSAUFNM2Qyuc}lxgesp^v$P%=+yZWtQ$tGq-%8$VbiR5Dd#J zRj0q#{2D>E?91HpC|Ia_bmmJgCSG0UKvENZ-rx92=9X`RFAzgAcvTe69-zn2Fw+^7-=;$D(Nr+)3%_^d!&&0X~=AMe_A%>jOXssE|7>rjYW;Tocf%0+N z>`q$uoW)_!>acfc{okL%eyYRT5QX_MatZUJt>0B)!{4D*Tvx`MC2 z!QsEBDM44pJ~cDQ8^XjhHSrEIs4L?Za<=77W8xQ-Mcan2f=M7=Mb5Uo_t1=f1y+V zeF!G~+1~me*ZMykC;Cqz{k!nd%ZcizHLFTLVzj59^*_PEuJosC{p&6LQM5~Q&PnLs zf#E}?->LsT1grFW>pwn{5}xtlSS$Uce-}beIQ^`D4{W!mpY=b%!LIcC5KQH7>5rm) zm~&1-{|@T+sr;S#??bRkzqkIroPIPFUH?uY{kzUcntp!&DeuoVQ!6M6Y`z`NLR9z3 zY(*>LwdKMvWkr|yQw}boS6ynx>3rQcNSm|TGUsM=4Q9472fdv24o<&Mw%(UL4+ef; zG|3XZj6^>fK`C*+U;AO4|0wFaPI)Hr@Al;1gHVotuf=~5Ey}#dlYd`4{`)L`>H*Ah z@T*s9t6s3Z@A_*z{UuuK0$t$)3xKZ38bC55cPb zd+R@Tx=uf8J*S`a??UJaw|~~Z2e#YO&-$O>U|0HQBAD90r9X;xYR)+c{X1v~q4w|8 ze;{HG=Pd$e71i;{G=x2!n-H!c1LiGR5# ze*~c%|J4?M4e^h+@oNtK&K%RQMR*U9UqYWyjPu7Dwi`$h{3BL%wIhSGtY{`9nnS}7 z^eJk(PV-`l`K42JPvM;JN}3bmZ*j)oVns%6U&a4jE9eZ0{|3+a>1_aga&ufyBrsXa zdzZ!n6y&W)s#K&v>^Ah5Z<%Wm36>t1J~zG*nS-hPNPlbq)}j9B0D6B4Cj9|jAo|sj zSWDsE`XK~moNAde1=g7dhuMnPnO+ZjR%WI)X)ZY-dwxwl zJo0Cihdm+0bQ1aV5h}g5XCT@0tE>~rpFFnbchK$5pBE6*N!YX6vgc+rTQmEF?0JMn z5aiEn4|}dYIeT6~1=jiVSF~jF!OZ0OBl83Od8D2gT!mVl$yWUY7Q}OjW&!kxpScrJ z+B0gAvtol!Ds~VRyMJNyn5x*bEW@rO!}=-1>=T8A&ubFfTRn|E$gd#|%XE9obeWZ6 zd;1Yuna;1L(TL5Op~>?r(Vll{ETHxe-SM2#_B?=??Aer}J*QgsOd)#?4mlBfR>oAO7E@cQF7^9{s=_gr|zVz1Boy}8;+Q5ePNV_khzWv;TU*n*~O&LS(` zz^DIe9fcx1~$HiOrn_aRt~|90zW=B?MCSx|xj;zP6^T_C5B>Rp3u8Q^}O zU{Ak&{mc6IAV#Ss$elA-{}UYSn*U7K`qx|fqiBWZobL3y$ID;RV1k4f*%Zro89+oQ zQ9s{CE795U85*Ja#6Vki^f+ElV0)g0ZpjF-rvovaggr|wdu||m&hfTK<|-K-cY%TD zPiI)7*(CbTDU=lV{A?~vW&ZbQL{}?;F0?Q6N$~f)e`aW0{wJ3FuSh-u`NZ|kopJj% zSp456{`nsE4a6JN$i$BO;zDyRp=(JfGp?i~16=%hOFTc0fPvH3-x58CL|+{c&kxnU z==1#Lc*mj^xV*reg?hY$xPOayP<;4gh~{6Hpw{t+P8&eLhfef9bwd1o>Y+2ywC+WN z(iyq~P0%cZLdfI8H0zC>>__TW|4hALO`v)>>k>lh_Orv+C;x>;pOy$-;gkKiFvJR7an<==qlDd=mY8 zKP`&QXIm&Cutu*H22;0$Bz61)k+a%PG!AX;0Fr%HWbN|@f3#Dg$V3#cf)Ov|JN_Pz z2HQ`$E|V6uqC;bBxk3fe--QB6pv+!6$`a!^Jqp={ZmQ* zKcGd@kLtzgC&_0aN!jl8`5pKF^f@sK{yZe69U?S|`vCE6KGvmnpWu_nynQ-cz399K zF`_kWwe&Qjp_(hiLVnlj&?lKq`9-4?#WUoD?7f8Tz076rS8VqFw6C&v zKkA9jmrk@j^AUuq679*}c39Q%0IcHtZL;FoPVuZlJPG-0Pw!(SzbYk zXZ>7@D5!o?&a)K*tysoUEPv|bsvnqjqfui)i8L=7`2tI+imqDn`)F+DLy#id<$XAR zjExQvdz1R8H7O#=qFsXSC24N!p|em4ZlRj1BK#wnQ7mTYOm)sTcs+qnZI5H#pEUNO zD6M_-{+;Hk{MqT{6n6s^BPL+cyxWMhc{Vvl{V04ykw^3rMbD@tVl3}kIP^izTd)ZI z7nojB>UUwraQm3>$FL$EV2%Pi80Mp(9WO(-sQyhC*CK3BqR*{V8BSh> zO&S>&pk4#>23SY_qMWhk$KuaX{C&FR$2K5~f2QL9Bh|E|@#ow4^A-P(yXD7bAuE2r z;;&22AK!mh6#Z>c^w)vt%W7xE=jN_|bamlFrN+mRH_-*JqVgasRo>{TiAnfmUQ`xF zZ<&m@C7`Rku;@7!y)GxvwE*QlPbJ=Bm?;dgTeAwIH_i-n;RDauJe6XLDPNePW%=3) zl|qZ|x9GQEE5)n2WUW0mOiI+UY*x=7sprG$`KWqQ@6VtLHQ7 zxl27;)$@7v+^wE_)N`MDzNDTso9deIvU;|u=PT;@s(QYrp8M7Fb@e=;o^PpVyL!H@ zp6{sVf2pUbo_|%(_to=n>PfwK*MyJM^Aq)?Ibqj?W9s>tdVZmv$JNt7mFt?2uAY6> zv!8knP|tztNyl@#CJa^2EcHB9Jx^E95$ZWoJx8hM+3Gn)J$>pqPCdutSwSthV;p*l z3cS)VI!2Q367mft-!k&`C0`BsK0`lHaR>Q2$@lN%`!Di6MZN>%dx?CnknbS*_L1)> z`F4?Scp7|9k}rpRkC87xzGm{3k?&seZ6x2f$hVDrcaZN9@@*vFv*fEL->c*+C*OzU zyOw-I@aQNe-?`*lNIpOLE+tDc5 zI(|UD^T~HN`SQuPm3-Hd?>6$SCtrko-y+`)k#7|F8p)SMzVDH*ANigl-xnyxir2{Z5&4dg&m>Rnh zHal)6UpD!|HRM}MzU#?HbK8!kiw+<8 zMw1V(h>VKq^Gd6#N>^8f z>|w!$_0?sO%9`q{YfHm85<9oFE@aHDsjn_~5ezrppapytrFFjQnuu?8C{*pMtgehy zmR42X94a?1olxg1jrb;neQRoJeFEkfHD!^>=lV)(*VeBKRY!bfrPY&2+E-RneN(75 z5-RsaYJ6ZaDnc83W&{%sL9Pu&N+XflV9=}fOX@--vFu`d>^KHnx-O)6*4LL-SzujFd3}`*FRv+6 z^s=hbIvrbSHS(vFGFfBG9N)V7I+gU&YF~{iD1&Lnl8f!7w1x`_cB?cY0m`kcMslmm zLJYY`7=@~-u*(^(#-U<5rmO|SrM1WaM7NrXIwiS5? zH%aA5FgVGuED+tIRrIl@B}#np$}J%*0- z{60n>n%{Q9E$(ZiHK9Sa_BHzCXBd5r{ziIBf6xaQeZzx{^zdLKt$nc3Hz&);Xdh;z z<%}@WThYv0&VU~;%^J=!(u&6z>78SYw6?F{tm*_KBWt3O)-VyeCL3wZlMSOCZt=N> zkv|1^ijm%S9`v1WK=v?n6}u(u-oS2z-P_pR%I@9l{(#*_*==F>X?AzB`!c)x*?pVc z_t`zdu0iuFTm#uXo!v3)PG)yHyO*-NklkW-uVuHK-D-9>vU>-+-(vS(cAMFKjNK>M z-No)cc3)xl0K3|1oJps~jjNsA60A2BX14?%Y$?oc2|j|OtCL-yPeG%Y-3E4B*llOG zWUQgCc6Lj~F=kgI*n>7pR};If>~^wSJYLgV*v+4yaT~iOXy#%>8sA8@s^TY^48VRpmkYivx_ZVtN~nz9p4A}8@RGrf)7{Z2X&c_!0alhEJ1RI}!1Yd6i3)ShuH-@`IhBjn_H@bjcTAqI@kVxOEo{GX25MBoZYR6K^Z5dvF>ruy zu=Zd)S63^$J`Igd#te-n)+;!?Kz!Z1Sxoi~aq=~|u#)w=u%$L&x-(lt} z>4EQa=43~MbVjJy>p2rh2fz|Ne+U$Kf`)NUG380 zFt?B0o}B#4y*XNkd51Tj?hJ1p?!;df`m*bDs&*x-2UC;OgH+>9l`o549i?!6+5K5o zQ3^``g)INKmH*s-QTeBu#b0{)FG*Fi<|{e##Q0B?d%KK3EGT#-_xq*nRu zte|AX!f@7#xl845;j+2NxVzv@!u8T z_J?zpB1Zh#Ik%=Mq5Wwj6CQBY+-01&Ir+ijP4j4LOp)565nR4095Sw4pVed$bdbUe zHkJhoWY@`p+S;00!wM%sSI||ZRrU5Ty@e*YXkKuBsLE*AnW==A%H|%Wx}mj`_7meu zQ`BW@%ZS}L6->OrMWO0YZDmd>-CZ9O(KAr=Z* zUR!U449mwCkeBNpB%tjw_(6h(W^D^uqjGG0iOR8p+O@&rQfx_DULURs8BNCe3XkxD z>hdc>n>N(cme&zWSZ6lx`U=jg2$kJP;Tu)>{K~QjQWOc`yU<}H?F|C0AuUc^9NIuZ zTWvwhG(QD5B?iZ%xnC1eKEZiap;8o^vA#JTwy>slT`BU!Sie0Uh`8eswCM1_x^PWx zB&eMtwaJR4c512)2o{u=>yjo?tAm8}Q96mRPZJi`uUn0cUj?h{YO1i6i70JON_ja2 z?so=OtH5?g;QY#)D$7+2raK(_!6=eWNBF|38lC84?%2x{FH&*M z2Gn^7wt7*QhSrtpRsoKEo*b5GZC>PM^{XSbrMmR@dofUBjOS3h7t2cOa*Xw+i&ld2<_e@ujl|s0$6m07HM+rVb%t6gYI20zbNPM;WpQXN_PE`os$sK(qBDNG zBdl2MtJB;qE(({$PDik#5L%ri%hr94aC^45IVjHj-tVAsMz`xg?zw5ls>=R^P}xTa zM)ZxUyX#C~(!IEi<(QL&dZw#Gr8h1Otx+*F^i?Iq$}wh8-$?qmIti7kPBb|JG03c_ zUXJRfy4d@jG(B#hGorzaB5d}eqXQKBb{E|uw0IHX-R4d=SyIsIK~R?La}fNcbz(xB zn@~Z9?{|a->H@L@6|{C2jfz{9o+ErQe)k2;osPhzm1Pz4YSz(aQ6e5oMx2ZNpTy9R zVJ|6L#%=W?#Pg@gO_uz*-$}p*W>VAa4Ao_~T?a11Ueyrx-UjE@R7cQJsT$P6G&P9kc-LKdvT@xOJ_XLyhq=G?N+oT;a>ADzWDmgf=^285_Ny18K&xG*nuy zy5@Er7z|*8wjMTT1TUO{IOIwT8W~19?ca{?lO26E_IO7OoV;kd5I=9D+lAUouIFgC zd+aFJl*Tk^pcDoD)KVaH{gMU+n8FFIePrw0cXw z9jo;7{;~%p{ftwUmwiNZf{n^gu*jFV^xHA%Z{U3^zhim9BA@S)w_}oTW%<8I`WcJ7 zJ-v$&XvZr3%ulD&$bQ*JBk~O{{dP?9vQLK2osqm?k#8jrE^#(N@^(z}vajYFEHBuS=WS|)$^Ld5CVAO^Luafh{ep>~ z>{o`fL-Ka4l$0RTNQ{H2F!6HxRq3IHNJ0^MAH_#u)bjg0f zBHuzDo4g$>{byA%^H>$oT|K>*NL*c;8f-1oX_JdFE~|s zIUht{xJKnCI8}K$SM(vv3l{liSN_>C<)55K8ixJGq+hVe+w*%d0_~XOselKs`7H)ioURm(l1!#8(jHk$CQ3Kr}a3?3rV`mV|_nhdBGxYx0m$WG3l4{bWgFoV3D`m z>t(;3xBD&23l{kXojq3nZO5cv&f~qq@`6*9m-Bj`i~ek_P~^id{dP?Hq z!Kupoa&-nh!}5Ytl`moWKeN1Gkq^7_-;OE&<=o>DmKQAY_VQYcKszRRIWL(tOqZWv zk+BZnB?17{~neXEb=+z!9@<`pB4%L`6bUe2YJvAp0^<>kEET`Vs+RryZNubnI}SmfVTxfRcU z!Eb(>&YAf%t9sI}3XuI-OLX9MF8WPEzf#lhVeDi4G~*J+2MFUGRs-Wccn?N+ zE8|Iwn;0)QBDuOt^s{0uza3T$5=j(xRbGbzVMLnLkC^|$ynb1zasoh zKg?L(&kq=>^~w8oA7gocPQMyM_Q?6`6^!Nmb`@iJUwwzjV;w}-Ln6=k1;+Az_-)4W zzBdEsmq?$yzn#EX-p2+Q%lp*|!6-+%zQI`De?H1s-e*21nBN!viLtydq;Ksf{qjC= z$SAgl-{(zaEbr^)3Z37#T_<#Ye^$p>-iO`A*ymH`8b4)R%y>8B2F7nNZejch<95bF z@SauKJJwLwM8@(y=Tf2b`;?_ZXS`PE{J!K?#`6B-9>(%M<8j9Fe&Tt?^1fj|V|jmY zgt5F2I1~9!_R9MHQpU1gU&UC~-(P1e>*&ei#I4r5tg zUdmY3i`NOA*KeDI&bXPetk3o^mi5+KjAi|FRQP#)aw_Tx*(2+l^BK!}Wg%l(e_YR4 z))NuNvOb6jo#*?HFqZlIvy5dvzMrv=2lS5_moOfRdaLYXJe9G`XA2q2{Irs>%s0Qm zSmuw-jAcGZzcfhk%lz&&#xh?!##rWGqfpO@U*=OY8O!|WD#kM3SFtmht>X!nX1Hn~Y_=euS}%*UvMS@%jK`8LvNOEaUSCv`dO# z&VOITSjOLL1oL=%lVBcC?qTd>{50bd#s>&vENEcd2koA)HNG;o##hGH_{zAM<$uW7 z8ebV(<11rpe8psv^tH15m5ilP5O~0FP8syYLYg z?u*Fm@zJ+7+VMmezR-o~dm-)o*SPRn7p5=cwDaHP!n9w+PX7-V-si#xT=;J;oQ48H zkdx~Rx(knW;TbMG--TDYaHR`>&4s_?!VkLe4j2Bd z3!5%%WH{4vstfyEIM;<2x^U2iH@fhhF8m`Ge$s{axbS`#e$R!!aN!~SoasBug>zl_ z3Kw4G!u2lvO&7k`g&%g|U%K#1E_~31KXKtq?EkX2FP{rfcj0^&Ug5%JE*y5@%`W_J zF8pJSVUoTEqrKCY4iCjW4EL$HPs2^$BRm}U2;67jJ`4BRxT*i5ZyP=bw-5JN+~aV6 z1^0N|6L3$&Jqb5`KQVoc@f6(W;XWVtRNU0(W#i7lor`-q?hA0wz@3NtLfjYOo{4)F z?u&6>f}6ernZEpe4sPlv^Klp8o{M`P?)kXsYq#iIlj%#71Gq28eFg49+(oz-)+|+Nc#a)5BH_!k3dG0fUY7=Vm&7+#0bSJ7NyLO|-H<)^o^`28r zO4#%obncPGp&r-aoP-eju^bS^R6dYHA@1`~62^uUZ}K>-10EGhr*y4HXB!pY1JQ654%aIVK zPtPO-$4_h|lJtp(GeggQfz_FqbLakIZ9zC=))%oA@N>?)69nn?KY|7f_5wAfJruYNBJ020yKUrjZa_M|CbCbgljg1TS;yl9O;iQvK9{M}%eS;BKNK zoPe$<N8>dI>A=O;KBUOcw6dy(UL;5o@no(44&HQe*jgo;s0^QMH*IyoGhNLnXH zdJ{?I`p9!4q1HOAn@EF@nu{ga5LV}Z69uZ}Olu-Z|1bm&uqKj95;}I@Dr-qdxN7^xq4Qki6rcAfgBojMOOWHE}#gP_*}DkiUqnM2Nt!6u(1W8-?g z7;N&MlOl%!o*cFqTncEmmQ;JPSAR5zn|9-ds>(XaE?2DTm12)vs?Iy(v6mDqE5$cN z)J$U!z8grYvYidqYc|z9df?G5g1%;``>3qnO-sTl^>&)>qk7_^pFxYO^vW!n*iKu+ zziie6uQkn{wp#sQS%lWK-A5l6Ibj`%S>|QGDr}FqJ*#7iiPiN(b=tbsCQqbhwg19d zPrM$s+G~|_Ic2BxE>9y~og9@Z_nlt#!p%L9@u0M$X}#+|`_HNeX{w*XV)tLS{?pq6jsF9m9vU_P diff --git a/pymode/libs/wrapt/arguments.py b/pymode/libs/wrapt/arguments.py index f71df257..428ffaed 100644 --- a/pymode/libs/wrapt/arguments.py +++ b/pymode/libs/wrapt/arguments.py @@ -4,6 +4,7 @@ # of the PSF license used for Python 2.7. from inspect import getargspec, ismethod +import sys def getcallargs(func, *positional, **named): """Get the mapping of arguments to values. @@ -29,7 +30,7 @@ def assign(arg, value): except StopIteration: raise ValueError('need more than %d %s to unpack' % (i, 'values' if i > 1 else 'value')) - assign(subarg,subvalue) + assign(subarg, subvalue) try: next(value) except StopIteration: @@ -37,7 +38,7 @@ def assign(arg, value): else: raise ValueError('too many values to unpack') def is_assigned(arg): - if isinstance(arg,str): + if isinstance(arg, str): return arg in arg2value return arg in assigned_tuple_params if ismethod(func) and func.im_self is not None: diff --git a/pymode/libs/wrapt/decorators.py b/pymode/libs/wrapt/decorators.py index dd6016e7..2ad34946 100644 --- a/pymode/libs/wrapt/decorators.py +++ b/pymode/libs/wrapt/decorators.py @@ -255,7 +255,7 @@ def _capture(target_wrapped): # we need to first check that use of the decorator # hadn't been disabled by a simple boolean. If it was, # the target function to be wrapped is returned instead. - + _enabled = enabled if type(_enabled) is bool: if not _enabled: @@ -424,7 +424,7 @@ def synchronized(wrapped): if hasattr(wrapped, 'acquire') and hasattr(wrapped, 'release'): # We remember what the original lock is and then return a new - # decorator which acceses and locks it. When returning the new + # decorator which accesses and locks it. When returning the new # decorator we wrap it with an object proxy so we can override # the context manager methods in case it is being used to wrap # synchronized statements with a 'with' statement. @@ -453,7 +453,7 @@ def __exit__(self, *args): # Following only apply when the lock is being created automatically # based on the context of what was supplied. In this case we supply # a final decorator, but need to use FunctionWrapper directly as we - # want to derive from it to add context manager methods in in case it is + # want to derive from it to add context manager methods in case it is # being used to wrap synchronized statements with a 'with' statement. def _synchronized_lock(context): diff --git a/pymode/libs/wrapt/importer.py b/pymode/libs/wrapt/importer.py index 1eca4b6d..7fd2d8df 100644 --- a/pymode/libs/wrapt/importer.py +++ b/pymode/libs/wrapt/importer.py @@ -9,7 +9,7 @@ PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 -if PY3: +if PY3: import importlib string_types = str, else: diff --git a/pymode/libs/wrapt/wrappers.py b/pymode/libs/wrapt/wrappers.py index 56fe15b9..be999393 100644 --- a/pymode/libs/wrapt/wrappers.py +++ b/pymode/libs/wrapt/wrappers.py @@ -18,14 +18,14 @@ def with_metaclass(meta, *bases): class _ObjectProxyMethods(object): - # We use properties to override the values of __module__ and - # __doc__. If we add these in ObjectProxy, the derived class - # __dict__ will still be setup to have string variants of these - # attributes and the rules of descriptors means that they appear to - # take precedence over the properties in the base class. To avoid - # that, we copy the properties into the derived class type itself - # via a meta class. In that way the properties will always take - # precedence. + # We use properties to override the values of __module__ and + # __doc__. If we add these in ObjectProxy, the derived class + # __dict__ will still be setup to have string variants of these + # attributes and the rules of descriptors means that they appear to + # take precedence over the properties in the base class. To avoid + # that, we copy the properties into the derived class type itself + # via a meta class. In that way the properties will always take + # precedence. @property def __module__(self): @@ -60,15 +60,15 @@ def __weakref__(self): return self.__wrapped__.__weakref__ class _ObjectProxyMetaType(type): - def __new__(cls, name, bases, dictionary): - # Copy our special properties into the class so that they - # always take precedence over attributes of the same name added - # during construction of a derived class. This is to save - # duplicating the implementation for them in all derived classes. + def __new__(cls, name, bases, dictionary): + # Copy our special properties into the class so that they + # always take precedence over attributes of the same name added + # during construction of a derived class. This is to save + # duplicating the implementation for them in all derived classes. - dictionary.update(vars(_ObjectProxyMethods)) + dictionary.update(vars(_ObjectProxyMethods)) - return type.__new__(cls, name, bases, dictionary) + return type.__new__(cls, name, bases, dictionary) class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): @@ -418,7 +418,7 @@ def __call__(self, *args, **kwargs): class _FunctionWrapperBase(ObjectProxy): __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', - '_self_binding', '_self_parent') + '_self_binding', '_self_parent') def __init__(self, wrapped, instance, wrapper, enabled=None, binding='function', parent=None): @@ -440,7 +440,7 @@ def __get__(self, instance, owner): # # The distinguishing attribute which determines whether we are # being called in an unbound or bound wrapper is the parent - # attribute. If binding has never occured, then the parent will + # attribute. If binding has never occurred, then the parent will # be None. # # First therefore, is if we are called in an unbound wrapper. In @@ -467,7 +467,7 @@ def __get__(self, instance, owner): return self - # Now we have the case of binding occuring a second time on what + # Now we have the case of binding occurring a second time on what # was already a bound function. In this case we would usually # return ourselves again. This mirrors what Python does. # @@ -702,7 +702,7 @@ def resolve_path(module, name): # to work. For the case of a class we therefore access # the __dict__ directly. To cope though with the wrong # class being given to us, or a method being moved into - # a base class, we need to walk the class heirarchy to + # a base class, we need to walk the class hierarchy to # work out exactly which __dict__ the method was defined # in, as accessing it from __dict__ will fail if it was # not actually on the class given. Fallback to using From d2dead6ce9d900b26dbf1a06c52969f4194eda64 Mon Sep 17 00:00:00 2001 From: Kirill Klenov Date: Tue, 4 Jul 2017 16:27:09 +0300 Subject: [PATCH 05/79] Update pymode. --- plugin/pymode.vim | 2 +- pymode/environment.py | 4 ++-- pymode/lint.py | 25 ++++++++++++++----------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 3833cef3..30078ce6 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -135,7 +135,7 @@ call pymode#default("g:pymode_lint_info_symbol", "II") call pymode#default("g:pymode_lint_pyflakes_symbol", "FF") " Code checkers options -call pymode#default("g:pymode_lint_options_pep8", +call pymode#default("g:pymode_lint_options_pycodestyle", \ {'max_line_length': g:pymode_options_max_line_length}) call pymode#default("g:pymode_lint_options_pylint", diff --git a/pymode/environment.py b/pymode/environment.py index c146ea6e..56f49b4a 100644 --- a/pymode/environment.py +++ b/pymode/environment.py @@ -59,7 +59,7 @@ def lines(self): return [l.decode(self.options.get('encoding')) for l in self.curbuf] @staticmethod - def var(name, to_bool=False, silence=False): + def var(name, to_bool=False, silence=False, default=None): """Get vim variable. :return vimobj: @@ -69,7 +69,7 @@ def var(name, to_bool=False, silence=False): value = vim.eval(name) except vim.error: if silence: - return None + return default raise if to_bool: diff --git a/pymode/lint.py b/pymode/lint.py index da1be109..b0f85655 100644 --- a/pymode/lint.py +++ b/pymode/lint.py @@ -15,7 +15,7 @@ pass -def code_check(): +def code_check(): # noqa """Run pylama and check current file. :return bool: @@ -25,26 +25,29 @@ def code_check(): from pylama.core import run from pylama.main import parse_options + from pylama.config import _override_options if not env.curbuf.name: return env.stop() - linters = env.var('g:pymode_lint_checkers') - env.debug(linters) - options = parse_options( - linters=linters, force=1, + force=1, ignore=env.var('g:pymode_lint_ignore'), select=env.var('g:pymode_lint_select'), ) - for linter in linters: - opts = env.var('g:pymode_lint_options_%s' % linter, silence=True) - if opts: - options.linters_params[linter] = options.linters_params.get(linter, {}) - options.linters_params[linter].update(opts) - options.linters_params['pylint']['clear_cache'] = True + linters = env.var('g:pymode_lint_checkers', default=[]) + if linters: + _override_options(options, linters=",".join(linters)) + + for linter in dict(options.linters): + opts = env.var('g:pymode_lint_options_%s' % linter, silence=True) + if opts: + options.linters_params[linter] = options.linters_params.get(linter, {}) + options.linters_params[linter].update(opts) + if 'pylint' in options.linters_params: + options.linters_params['pylint']['clear_cache'] = True env.debug(options) path = os.path.relpath(env.curbuf.name, env.curdir) From a7fb465fd184c3f4b1445df0aa74594b06a58b40 Mon Sep 17 00:00:00 2001 From: Pi Delport Date: Wed, 18 Oct 2017 14:51:11 +0200 Subject: [PATCH 06/79] (Update my name) --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index cc3de277..0a800ac5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -42,7 +42,7 @@ Contributors: * Paweł Korzeniewski (https://github.com/korzeniewskipl); * Pedro Algarvio (http://github.com/s0undt3ch); * Phillip Cloud (http://github.com/cpcloud); -* Piet Delport (http://github.com/pjdelport); +* Pi Delport (http://github.com/pjdelport); * Robert David Grant (http://github.com/bgrant); * Robin Schneider (https://github.com/ypid); * Ronald Andreu Kaiser (http://github.com/cathoderay);; From 70a39ab32ebf437cd62fe0999ca378a47ea2fbb6 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Tue, 7 Nov 2017 20:58:07 -0200 Subject: [PATCH 07/79] rearranged tests and added simple but meaningful bash script for testing --- t/test.py | 8 ---- {t => tests/old}/docs.vim | 0 {t => tests/old}/ftplugin.vim | 0 {t => tests/old}/indent.vim | 0 {t => tests/old}/lint.vim | 0 {t => tests/old}/plugin.vim | 0 {t => tests/old}/rope.vim | 0 {t => tests/old}/syntax.vim | 0 {t => tests/old}/trouble.vim | 0 {t => tests/old}/virtualenv.vim | 0 tests/test.sh | 76 +++++++++++++++++++++++++++++++++ 11 files changed, 76 insertions(+), 8 deletions(-) delete mode 100644 t/test.py rename {t => tests/old}/docs.vim (100%) rename {t => tests/old}/ftplugin.vim (100%) rename {t => tests/old}/indent.vim (100%) rename {t => tests/old}/lint.vim (100%) rename {t => tests/old}/plugin.vim (100%) rename {t => tests/old}/rope.vim (100%) rename {t => tests/old}/syntax.vim (100%) rename {t => tests/old}/trouble.vim (100%) rename {t => tests/old}/virtualenv.vim (100%) create mode 100644 tests/test.sh diff --git a/t/test.py b/t/test.py deleted file mode 100644 index ba7d5efb..00000000 --- a/t/test.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - - -def main(): - unused = 1 - -unknown() diff --git a/t/docs.vim b/tests/old/docs.vim similarity index 100% rename from t/docs.vim rename to tests/old/docs.vim diff --git a/t/ftplugin.vim b/tests/old/ftplugin.vim similarity index 100% rename from t/ftplugin.vim rename to tests/old/ftplugin.vim diff --git a/t/indent.vim b/tests/old/indent.vim similarity index 100% rename from t/indent.vim rename to tests/old/indent.vim diff --git a/t/lint.vim b/tests/old/lint.vim similarity index 100% rename from t/lint.vim rename to tests/old/lint.vim diff --git a/t/plugin.vim b/tests/old/plugin.vim similarity index 100% rename from t/plugin.vim rename to tests/old/plugin.vim diff --git a/t/rope.vim b/tests/old/rope.vim similarity index 100% rename from t/rope.vim rename to tests/old/rope.vim diff --git a/t/syntax.vim b/tests/old/syntax.vim similarity index 100% rename from t/syntax.vim rename to tests/old/syntax.vim diff --git a/t/trouble.vim b/tests/old/trouble.vim similarity index 100% rename from t/trouble.vim rename to tests/old/trouble.vim diff --git a/t/virtualenv.vim b/tests/old/virtualenv.vim similarity index 100% rename from t/virtualenv.vim rename to tests/old/virtualenv.vim diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 00000000..cd9f4165 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,76 @@ +#! /bin/bash + +# Check before starting. +set -e +which vim 1>/dev/null 2>/dev/null + +# Set variables. +export VIM_TEST_FILE=/tmp/pymode.out +export VIM_TEST_VIMRC=/tmp/pymode_vimrc +export VIM_TEST_PYFILE=/tmp/pyfile.py +export VIM_TEST_PYMODECOMMANDS=/tmp/pymode_commands.txt + +# Prepare tests. +set +e +rm $VIM_TEST_FILE $VIM_TEST_VIMRC $VIM_TEST_PYFILE $VIM_TEST_PYMODECOMMANDS 2&>/dev/null +set -e + +# Create minimal vimrc. +echo "call has('python3')" >> $VIM_TEST_VIMRC +echo "set noswapfile" >> $VIM_TEST_VIMRC +echo "set shell=bash" >> $VIM_TEST_VIMRC +echo "set ft=python" >> $VIM_TEST_VIMRC +echo -e "syntax on\nfiletype plugin indent on\nset nocompatible" >> $VIM_TEST_VIMRC +echo -e "set runtimepath+=$(dirname $PWD)\n\n" >> $VIM_TEST_VIMRC +# echo "set runtimepath+=~/.vim/packpathdir/code/start/python-mode" >> $VIM_TEST_VIMRC + +# Start tests. +echo "Starting vim tests." + +# Iterate over each Pymode command. +set +e +vim -u $VIM_TEST_VIMRC -c "redir >> $VIM_TEST_PYMODECOMMANDS" -c "silent! command" -c "xall" $VIM_TEST_PYFILE +touch $VIM_TEST_PYFILE +while IFS= read -r PYCMD +do + # Customize commands which require arguments. + if [ $PYCMD == 'PymodeDoc' ]; + then + export PYCMD="PymodeDoc unittest" + elif [ $PYCMD == 'PymodeVirtualenv' ]; + then + # export PYCMD="PymodeVirtualenv venv" + : + elif [ $PYCMD == 'PymodePython' ]; + then + export PYCMD="PymodePython print(1 + 1)" + fi + echo "--------------- Processing $PYCMD" >> $VIM_TEST_FILE + vim -n -E -u $VIM_TEST_VIMRC -c "redir >> $VIM_TEST_FILE" -c "$PYCMD" -c "xall" $VIM_TEST_PYFILE + echo "" >> $VIM_TEST_FILE + echo "---------------" >> $VIM_TEST_FILE + echo -e "\n" >> $VIM_TEST_FILE +done < <(grep -o -E "Pymode[a-zA-Z]+" $VIM_TEST_PYMODECOMMANDS) +set -e + +# echo "Test 1" >> $VIM_TEST_FILE +# vim -u $VIM_TEST_VIMRC -c "redir >> $VIM_TEST_FILE" -c "silent $PYCMD" -c "quitall" $VIM_TEST_PYFILE +# echo "" >> $VIM_TEST_FILE +# +# echo "Test 2" >> $VIM_TEST_FILE +# vim -u $VIM_TEST_VIMRC -c "redir >> $VIM_TEST_FILE" -c "scriptnames" -c "quit" +# echo "" >> $VIM_TEST_FILE + +# Print errors. +echo "Errors:" +grep -E "^E[0-9]+:" $VIM_TEST_FILE + +echo "Reched end of tests." + +# Cleanup tests. +set +e +# rm $VIM_TEST_VIMRC $VIM_TEST_PYFILE $VIM_TEST_PYMODECOMMANDS 2&>/dev/null +set -e +vim $VIM_TEST_FILE + +# vim: set fileformat=unix filetype=sh wrap tw=0: From 3e37c3c343d6302568aab8cfe27eef23df47f457 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Tue, 7 Nov 2017 23:00:30 -0200 Subject: [PATCH 08/79] updated vim files according to 2082d0b8fed7fff10b3f335cefc6a51dd25ee0b2 (various improvements) --- after/ftplugin/python.vim | 4 +- autoload/pymode.vim | 2 +- autoload/pymode/folding.vim | 140 ++++++++++++-------------- autoload/pymode/lint.vim | 4 +- autoload/pymode/motion.vim | 2 +- autoload/pymode/rope.vim | 16 +-- autoload/pymode/tools/loclist.vim | 2 +- autoload/pymode/troubleshooting.vim | 4 +- doc/pymode.txt | 16 +-- ftplugin/python/pymode.vim | 42 ++++---- plugin/pymode.vim | 146 +++++++++++++++------------- syntax/python.vim | 6 +- 12 files changed, 190 insertions(+), 194 deletions(-) diff --git a/after/ftplugin/python.vim b/after/ftplugin/python.vim index 0dec7542..4f29b753 100644 --- a/after/ftplugin/python.vim +++ b/after/ftplugin/python.vim @@ -53,6 +53,6 @@ if g:pymode_rope && g:pymode_rope_completion if tolower(g:pymode_rope_completion_bind) == '' exe "inoremap =pymode#rope#complete(0)" endif - end + endif -end +endif diff --git a/autoload/pymode.vim b/autoload/pymode.vim index 723af9b5..3127431d 100644 --- a/autoload/pymode.vim +++ b/autoload/pymode.vim @@ -71,7 +71,7 @@ endfunction "}}} fun! pymode#trim_whitespaces() "{{{ if g:pymode_trim_whitespaces let cursor_pos = getpos('.') - silent! %s/\s\+$// + silent! %s/\s\+$//e call setpos('.', cursor_pos) endif endfunction "}}} diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index 3b29aebb..24f6b530 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -1,5 +1,4 @@ " Python-mode folding functions - " Notice that folding is based on single line so complex regular expressions " that take previous line into consideration are not fit for the job. @@ -8,13 +7,13 @@ let s:def_regex = g:pymode_folding_regex let s:blank_regex = '^\s*$' " Spyder, a very popular IDE for python has a template which includes " '@author:' ; thus the regex below. -let s:decorator_regex = '^\s*@\(author:\)\@!' -let s:doc_begin_regex = '^\s*[uUrR]\=\%("""\|''''''\)' -let s:doc_end_regex = '\%("""\|''''''\)\s*$' +let s:decorator_regex = '^\s*@\(author:\)\@!' +let s:docstring_line_regex = '^\s*[uUrR]\=\("""\|''''''\).\+\1\s*$' +let s:docstring_begin_regex = '^\s*[uUrR]\=\%("""\|''''''\).*\S' +let s:docstring_end_regex = '\%("""\|''''''\)\s*$' " This one is needed for the while loop to count for opening and closing " docstrings. -let s:doc_general_regex = '\%("""\|''''''\)' -let s:doc_line_regex = '^\s*[uUrR]\=\("""\|''''''\).\+\1\s*$' +let s:docstring_general_regex = '\%("""\|''''''\)' let s:symbol = matchstr(&fillchars, 'fold:\zs.') " handles multibyte characters if s:symbol == '' let s:symbol = ' ' @@ -24,10 +23,10 @@ endif fun! pymode#folding#text() " {{{ let fs = v:foldstart - while getline(fs) !~ s:def_regex && getline(fs) !~ s:doc_begin_regex + while getline(fs) !~ s:def_regex && getline(fs) !~ s:docstring_begin_regex let fs = nextnonblank(fs + 1) endwhile - if getline(fs) =~ s:doc_end_regex && getline(fs) =~ s:doc_begin_regex + if getline(fs) =~ s:docstring_end_regex && getline(fs) =~ s:docstring_begin_regex let fs = nextnonblank(fs + 1) endif let line = getline(fs) @@ -83,7 +82,11 @@ fun! pymode#folding#expr(lnum) "{{{ if decorated return '=' else + " The line below may improve folding. return ">".(indent / &shiftwidth + 1) + " This was the previous rule. It grouped classes definitions + " together (undesired). + " return indent / &shiftwidth + 1 endif endif "}}} @@ -95,80 +98,43 @@ fun! pymode#folding#expr(lnum) "{{{ " Notice that an effect of this is that other docstring matches will not " be one liners. - if line =~ s:doc_line_regex + if line =~ s:docstring_line_regex return "=" endif - if line =~ s:doc_begin_regex - " echom 'just entering' + if line =~ s:docstring_begin_regex if s:Is_opening_folding(a:lnum) - " echom 'entering at line ' . a:lnum return ">".(indent / &shiftwidth + 1) endif endif - if line =~ s:doc_end_regex + if line =~ s:docstring_end_regex if !s:Is_opening_folding(a:lnum) - " echom 'leaving at line ' . a:lnum return "<".(indent / &shiftwidth + 1) endif endif "}}} - " Nested Definitions {{{ - " Handle nested defs but only for files shorter than - " g:pymode_folding_nest_limit lines due to performance concerns - if line('$') < g:pymode_folding_nest_limit && indent(prevnonblank(a:lnum)) - let curpos = getpos('.') - try - let last_block = s:BlockStart(a:lnum) - let last_block_indent = indent(last_block) - - " Check if last class/def is not indented and therefore can't be - " nested. - if last_block_indent - call cursor(a:lnum, 0) - let next_def = searchpos(s:def_regex, 'nW')[0] - let next_def_indent = next_def ? indent(next_def) : -1 - let last_block_end = s:BlockEnd(last_block) - - " If the next def has greater indent than the previous def, it - " is nested one level deeper and will have its own fold. If - " the class/def containing the current line is on the first - " line it can't be nested, and if this block ends on the last - " line, it contains no trailing code that should not be - " folded. Finally, if the next non-blank line after the end of - " the previous def is less indented than the previous def, it - " is not part of the same fold as that def. Otherwise, we know - " the current line is at the end of a nested def. - if next_def_indent <= last_block_indent && last_block > 1 && last_block_end < line('$') - \ && indent(nextnonblank(last_block_end)) >= last_block_indent - - " Include up to one blank line in the fold - if getline(last_block_end) =~ s:blank_regex - let fold_end = min([prevnonblank(last_block_end - 1), last_block_end]) + 1 - else - let fold_end = last_block_end - endif - if a:lnum == fold_end - return 's1' - else - return '=' - endif - endif - endif - finally - call setpos('.', curpos) - endtry - endif " }}} + " Blocks. {{{ + let save_cursor = getcurpos() + if line !~ s:blank_regex + let line_block_start = s:BlockStart(a:lnum) + let prev_line_block_start = s:BlockStart(a:lnum - 1) + call setpos('.', save_cursor) + if line_block_start == prev_line_block_start || a:lnum - line_block_start == 1 + return '=' + elseif indent < indent(prevnonblank(a:lnum - 1)) + return indent(line_block_start) / &shiftwidth + 1 + else + endif + endif + " endif " }}} " Blank Line {{{ if line =~ s:blank_regex if prev_line =~ s:blank_regex - if indent(a:lnum + 1) == 0 && next_line !~ s:blank_regex && next_line !~ s:doc_general_regex + if indent(a:lnum + 1) == 0 && next_line !~ s:blank_regex && next_line !~ s:docstring_general_regex if s:Is_opening_folding(a:lnum) - " echom a:lnum return "=" else - " echom "not " . a:lnum return 0 endif endif @@ -182,15 +148,25 @@ fun! pymode#folding#expr(lnum) "{{{ endfunction "}}} -fun! s:BlockStart(lnum) "{{{ +fun! s:BlockStart(line_number) "{{{ + " Returns the definition statement which encloses the current line. + " Note: Make sure to reset cursor position after using this function. - call cursor(a:lnum, 0) + call cursor(a:line_number, 0) " In case the end of the block is indented to a higher level than the def " statement plus one shiftwidth, we need to find the indent level at the " bottom of that if/for/try/while/etc. block. - let last_def = searchpos(s:def_regex, 'bcnW')[0] + let previous_definition = searchpos(s:def_regex, 'bcnW') + if previous_definition != [0, 0] + while previous_definition != [0, 0] && indent(previous_definition[0]) >= indent(a:line_number) + let previous_definition = searchpos(s:def_regex, 'bncW') + call cursor(previous_definition[0] - 1, 0) + endwhile + endif + let last_def = previous_definition[0] if last_def + call cursor(last_def, 0) let last_def_indent = indent(last_def) call cursor(last_def, 0) let next_stmt_at_def_indent = searchpos('\v^\s{'.last_def_indent.'}[^[:space:]#]', 'nW')[0] @@ -200,19 +176,33 @@ fun! s:BlockStart(lnum) "{{{ " Now find the class/def one shiftwidth lower than the start of the " aforementioned indent block. - if next_stmt_at_def_indent && next_stmt_at_def_indent < a:lnum + if next_stmt_at_def_indent && next_stmt_at_def_indent < a:line_number let max_indent = max([indent(next_stmt_at_def_indent) - &shiftwidth, 0]) else - let max_indent = max([indent(prevnonblank(a:lnum)) - &shiftwidth, 0]) + let max_indent = max([indent(prevnonblank(a:line_number)) - &shiftwidth, 0]) endif + + " " Debug: + return searchpos('\v^\s{,'.max_indent.'}(def |class )\w', 'bcnW')[0] + endfunction "}}} +function! Blockstart(x) + let save_cursor = getcurpos() + return s:BlockStart(a:x) + call setpos('.', save_cursor) +endfunction fun! s:BlockEnd(lnum) "{{{ " Note: Make sure to reset cursor position after using this function. call cursor(a:lnum, 0) return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1 endfunction "}}} +function! Blockend(lnum) + let save_cursor = getcurpos() + return s:BlockEnd(a:lnum) + call setpos('.', save_cursor) +endfunction function! s:Is_opening_folding(lnum) "{{{ " Helper function to see if docstring is opening or closing @@ -238,13 +228,11 @@ function! s:Is_opening_folding(lnum) "{{{ let i_line = getline(i) - if i_line =~ s:doc_line_regex - " echom "case 00 on line " . i + if i_line =~ s:docstring_line_regex continue endif - if i_line =~ s:doc_begin_regex && ! has_open_docstring - " echom "case 01 on line " . i + if i_line =~ s:docstring_begin_regex && ! has_open_docstring " This causes the loop to continue if there is a triple quote which " is not a docstring. if extra_docstrings > 0 @@ -255,15 +243,13 @@ function! s:Is_opening_folding(lnum) "{{{ let number_of_folding = number_of_folding + 1 endif " If it is an end doc and has an open docstring. - elseif i_line =~ s:doc_end_regex && has_open_docstring - " echom "case 02 on line " . i + elseif i_line =~ s:docstring_end_regex && has_open_docstring let has_open_docstring = 0 let number_of_folding = number_of_folding + 1 - elseif i_line =~ s:doc_general_regex - " echom "extra docstrings on line " . i + elseif i_line =~ s:docstring_general_regex let extra_docstrings = extra_docstrings + 1 - endif + endif endfor call add(b:fold_cache, number_of_folding % 2) diff --git a/autoload/pymode/lint.vim b/autoload/pymode/lint.vim index e7dba8b5..f6d27bf7 100644 --- a/autoload/pymode/lint.vim +++ b/autoload/pymode/lint.vim @@ -5,7 +5,7 @@ call pymode#tools#loclist#init() fun! pymode#lint#auto() "{{{ - if !pymode#save() + if ! pymode#save() return 0 endif PymodePython from pymode import auto @@ -42,7 +42,7 @@ fun! pymode#lint#toggle() "{{{ call pymode#wide_message("Code checking is enabled.") else call pymode#wide_message("Code checking is disabled.") - end + endif endfunction "}}} diff --git a/autoload/pymode/motion.vim b/autoload/pymode/motion.vim index 67e99e6b..17377c96 100644 --- a/autoload/pymode/motion.vim +++ b/autoload/pymode/motion.vim @@ -21,7 +21,7 @@ fun! pymode#motion#vmove(pattern, flags) range "{{{ call cursor(a:firstline, 0) normal! v call cursor(end) -endfunction "}}} +endfunction "}}} fun! pymode#motion#pos_le(pos1, pos2) "{{{ diff --git a/autoload/pymode/rope.vim b/autoload/pymode/rope.vim index a82a46d9..ab330f0a 100644 --- a/autoload/pymode/rope.vim +++ b/autoload/pymode/rope.vim @@ -1,5 +1,9 @@ " Python-mode Rope support -" + +if ! g:pymode_rope + finish +endif + PymodePython from pymode import rope call pymode#tools#loclist#init() @@ -12,23 +16,23 @@ endfunction fun! pymode#rope#complete(dot) if pumvisible() return "\" - end + endif if a:dot PymodePython rope.complete(True) else PymodePython rope.complete() - end + endif return pumvisible() ? "\\" : "" endfunction fun! pymode#rope#complete_on_dot() "{{{ if !exists("*synstack") return "" - end + endif for group in map(synstack(line('.'), col('.') - 1), 'synIDattr(v:val, "name")') for name in ['pythonString', 'pythonComment', 'pythonNumber', 'pythonDocstring'] if group == name - return "" + return "" endif endfor endfor @@ -73,7 +77,7 @@ fun! pymode#rope#show_doc() setlocal nomodified setlocal filetype=rst wincmd p - end + endif endfunction diff --git a/autoload/pymode/tools/loclist.vim b/autoload/pymode/tools/loclist.vim index 18b6d294..0b883bbb 100644 --- a/autoload/pymode/tools/loclist.vim +++ b/autoload/pymode/tools/loclist.vim @@ -77,5 +77,5 @@ fun! g:PymodeLocList.show() "{{{ call setwinvar(winnr(), 'quickfix_title', self._title . ' <' . self._name . '>') exe num . "wincmd w" endif - end + endif endfunction "}}} diff --git a/autoload/pymode/troubleshooting.vim b/autoload/pymode/troubleshooting.vim index 915a5c5e..09955c92 100644 --- a/autoload/pymode/troubleshooting.vim +++ b/autoload/pymode/troubleshooting.vim @@ -18,7 +18,7 @@ fun! pymode#troubleshooting#test() "{{{ call append('0', ['Pymode diagnostic', \ '===================', - \ 'VIM:' . v:version . ', OS: ' . os .', multi_byte:' . has('multi_byte') . ', pymode: ' . g:pymode_version . ', pymode-python: ' . g:pymode_python, + \ 'VIM:' . v:version . ', OS: ' . os .', multi_byte:' . has('multi_byte') . ', pymode: ' . g:pymode_version . ', pymode-python: ' . g:pymode_python, \ '']) if !exists('#filetypeplugin') @@ -85,5 +85,5 @@ EOF call append('$', 'let pymode_virtualenv = ' . string(g:pymode_virtualenv)) call append('$', 'let pymode_virtualenv_enabled = ' . string(g:pymode_virtualenv_enabled)) call append('$', 'let pymode_virtualenv_path = ' . string(g:pymode_virtualenv_path)) - + endfunction "}}} diff --git a/doc/pymode.txt b/doc/pymode.txt index 1551f119..f466508b 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -6,7 +6,7 @@ (__) (__) (__) (_) (_)(_____)(_)\_) (_/\/\_)(_____)(____/(____) ~ - Version: 0.9.2 + Version: 0.9.4 ============================================================================== CONTENTS *pymode-contents* @@ -86,7 +86,7 @@ Turn off plugin's warnings *'g:pymode_warnings'* let g:pymode_warnings = 1 Add paths to `sys.path` *'g:pymode_paths'* -Value is list of path's strings. +Value is list of path's strings. > let g:pymode_paths = [] @@ -130,10 +130,10 @@ Setup pymode |quickfix| window 2.1. Python version ~ *pymode-python-version* -By default pymode looks for current python version supported in your Vim. +By default pymode looks for current python version supported in your Vim. You could choose prefer version, but value will be tested on loading. - *'g:pymode_python'* + *'g:pymode_python'* > let g:pymode_python = 'python' @@ -196,7 +196,7 @@ Enable pymode-motion *'g:pymode_motion'* Pymode could show documentation for current word by `pydoc`. Commands: -*:PymodeDoc* — show documentation +*:PymodeDoc* — show documentation Turns on the documentation script *'g:pymode_doc'* > @@ -498,7 +498,7 @@ Offer to unresolved import object after completion. *pymode-rope-findit* By default when you press *g* on any object in your code you will be moved -to definition. +to definition. Leave empty for disable key binding. *'g:pymode_rope_goto_definition_bind'* > let g:pymode_rope_goto_definition_bind = 'g' @@ -597,7 +597,7 @@ Change function signature ~ ------------------------------------------------------------------------------ 4.4 Undo/Redo changes ~ - *pymode-rope-undo* + *pymode-rope-undo* *pymode-rope-redo* Commands: @@ -670,7 +670,7 @@ Highlight builtin types (str, list, ...) *'g:pymode_syntax_builtin_types'* > let g:pymode_syntax_builtin_types = g:pymode_syntax_all -Highlight exceptions (TypeError, ValueError, ...) +Highlight exceptions (TypeError, ValueError, ...) *'g:pymode_syntax_highlight_exceptions'* > let g:pymode_syntax_highlight_exceptions = g:pymode_syntax_all diff --git a/ftplugin/python/pymode.vim b/ftplugin/python/pymode.vim index 97daecca..79842616 100644 --- a/ftplugin/python/pymode.vim +++ b/ftplugin/python/pymode.vim @@ -110,7 +110,7 @@ if g:pymode_lint " let &l:updatetime = g:pymode_lint_async_updatetime " au! BufEnter call pymode#lint#start() " au! BufLeave call pymode#lint#stop() - end + endif endif @@ -124,7 +124,7 @@ if g:pymode_doc exe "nnoremap " g:pymode_doc_bind ":call pymode#doc#find()" exe "vnoremap " g:pymode_doc_bind ":call pymode#doc#show(@*)" -end +endif " Rope support if g:pymode_rope @@ -134,69 +134,69 @@ if g:pymode_rope endif if g:pymode_rope_show_doc_bind != "" exe "noremap " . g:pymode_rope_show_doc_bind . " :call pymode#rope#show_doc()" - end + endif if g:pymode_rope_find_it_bind != "" exe "noremap " . g:pymode_rope_find_it_bind . " :call pymode#rope#find_it()" - end + endif if g:pymode_rope_organize_imports_bind != "" exe "noremap " . g:pymode_rope_organize_imports_bind . " :call pymode#rope#organize_imports()" - end + endif if g:pymode_rope_rename_bind != "" exe "noremap " . g:pymode_rope_rename_bind . " :call pymode#rope#rename()" - end + endif if g:pymode_rope_rename_module_bind != "" exe "noremap " . g:pymode_rope_rename_module_bind . " :call pymode#rope#rename_module()" - end + endif if g:pymode_rope_extract_method_bind != "" exe "vnoremap " . g:pymode_rope_extract_method_bind . " :call pymode#rope#extract_method()" - end + endif if g:pymode_rope_extract_variable_bind != "" exe "vnoremap " . g:pymode_rope_extract_variable_bind . " :call pymode#rope#extract_variable()" - end + endif if g:pymode_rope_inline_bind != "" exe "noremap " . g:pymode_rope_inline_bind . " :call pymode#rope#inline()" - end + endif if g:pymode_rope_move_bind != "" exe "noremap " . g:pymode_rope_move_bind . " :call pymode#rope#move()" - end + endif if g:pymode_rope_change_signature_bind != "" exe "noremap " . g:pymode_rope_change_signature_bind . " :call pymode#rope#signature()" - end + endif if g:pymode_rope_use_function_bind != "" exe "noremap " . g:pymode_rope_use_function_bind . " :call pymode#rope#use_function()" - end + endif if g:pymode_rope_generate_function_bind != "" exe "noremap " . g:pymode_rope_generate_function_bind . " :call pymode#rope#generate_function()" - end + endif if g:pymode_rope_generate_package_bind != "" exe "noremap " . g:pymode_rope_generate_package_bind . " :call pymode#rope#generate_package()" - end + endif if g:pymode_rope_generate_class_bind != "" exe "noremap " . g:pymode_rope_generate_class_bind . " :call pymode#rope#generate_class()" - end + endif if g:pymode_rope_module_to_package_bind != "" exe "noremap " . g:pymode_rope_module_to_package_bind . " :call pymode#rope#module_to_package()" - end + endif if g:pymode_rope_autoimport_bind != "" exe "noremap " . g:pymode_rope_autoimport_bind . " :PymodeRopeAutoImport" - end + endif if g:pymode_rope_completion && g:pymode_rope_complete_on_dot inoremap . .=pymode#rope#complete_on_dot() - end + endif command! -buffer -nargs=? PymodeRopeNewProject call pymode#rope#new() command! -buffer PymodeRopeUndo call pymode#rope#undo() @@ -207,6 +207,6 @@ if g:pymode_rope if g:pymode_rope_autoimport command! -buffer PymodeRopeAutoImport call pymode#rope#autoimport(expand('')) - end + endif -end +endif diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 30078ce6..83127829 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -1,5 +1,5 @@ " vi: fdl=1 -let g:pymode_version = "0.9.2" +let g:pymode_version = "0.9.4" com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version com! PymodeTroubleshooting call pymode#troubleshooting#test() @@ -9,7 +9,10 @@ call pymode#default('g:pymode', 1) call pymode#default('g:pymode_debug', 0) " DESC: Disable script loading -if !g:pymode || &cp +if !g:pymode || &cp || &diff + " Update pymode status to prevent loading in other files and adding this + " condition to all of them. + let g:pymode = v:false finish endif @@ -49,7 +52,7 @@ call pymode#default("g:pymode_trim_whitespaces", 1) " Set recomended python options call pymode#default("g:pymode_options", 1) -call pymode#default("g:pymode_options_max_line_length", 80) +call pymode#default("g:pymode_options_max_line_length", 79) call pymode#default("g:pymode_options_colorcolumn", 1) " Enable/disable vertical display of python documentation @@ -135,7 +138,8 @@ call pymode#default("g:pymode_lint_info_symbol", "II") call pymode#default("g:pymode_lint_pyflakes_symbol", "FF") " Code checkers options -call pymode#default("g:pymode_lint_options_pycodestyle", +" TODO: check if most adequate name name is pep8 or pycodestyle. +call pymode#default("g:pymode_lint_options_pep8", \ {'max_line_length': g:pymode_options_max_line_length}) call pymode#default("g:pymode_lint_options_pylint", @@ -167,96 +171,98 @@ call pymode#default('g:pymode_breakpoint_cmd', '') " ROPE (refactoring, codeassist) {{{ " " Rope support -call pymode#default('g:pymode_rope', 1) +call pymode#default('g:pymode_rope', v:false) " System plugin variable -call pymode#default('g:pymode_rope_current', '') +if g:pymode_rope + call pymode#default('g:pymode_rope_current', '') -" Configurable rope project root -call pymode#default('g:pymode_rope_project_root', '') + " Configurable rope project root + call pymode#default('g:pymode_rope_project_root', '') -" Configurable rope project folder (always relative to project root) -call pymode#default('g:pymode_rope_ropefolder', '.ropeproject') + " Configurable rope project folder (always relative to project root) + call pymode#default('g:pymode_rope_ropefolder', '.ropeproject') -" If project hasnt been finded in current working directory, look at parents directory -call pymode#default('g:pymode_rope_lookup_project', 0) + " If project hasnt been finded in current working directory, look at parents directory + call pymode#default('g:pymode_rope_lookup_project', 0) -" Enable Rope completion -call pymode#default('g:pymode_rope_completion', 1) + " Enable Rope completion + call pymode#default('g:pymode_rope_completion', 1) -" Complete keywords from not imported modules (could make completion slower) -" Enable autoimport used modules -call pymode#default('g:pymode_rope_autoimport', 0) + " Complete keywords from not imported modules (could make completion slower) + " Enable autoimport used modules + call pymode#default('g:pymode_rope_autoimport', 0) -" Offer to import object after complete (if that not be imported before) -call pymode#default('g:pymode_rope_autoimport_import_after_complete', 0) + " Offer to import object after complete (if that not be imported before) + call pymode#default('g:pymode_rope_autoimport_import_after_complete', 0) -" Autoimported modules -call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime']) + " Autoimported modules + call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime']) -" Bind keys to autoimport module for object under cursor -call pymode#default('g:pymode_rope_autoimport_bind', 'ra') + " Bind keys to autoimport module for object under cursor + call pymode#default('g:pymode_rope_autoimport_bind', 'ra') -" Automatic completion on dot -call pymode#default('g:pymode_rope_complete_on_dot', 1) + " Automatic completion on dot + call pymode#default('g:pymode_rope_complete_on_dot', 1) -" Bind keys for autocomplete (leave empty for disable) -call pymode#default('g:pymode_rope_completion_bind', '') + " Bind keys for autocomplete (leave empty for disable) + call pymode#default('g:pymode_rope_completion_bind', '') -" Bind keys for goto definition (leave empty for disable) -call pymode#default('g:pymode_rope_goto_definition_bind', 'g') + " Bind keys for goto definition (leave empty for disable) + call pymode#default('g:pymode_rope_goto_definition_bind', 'g') -" set command for open definition (e, new, vnew) -call pymode#default('g:pymode_rope_goto_definition_cmd', 'new') + " set command for open definition (e, new, vnew) + call pymode#default('g:pymode_rope_goto_definition_cmd', 'new') -" Bind keys for show documentation (leave empty for disable) -call pymode#default('g:pymode_rope_show_doc_bind', 'd') + " Bind keys for show documentation (leave empty for disable) + call pymode#default('g:pymode_rope_show_doc_bind', 'd') -" Bind keys for find occurencies (leave empty for disable) -call pymode#default('g:pymode_rope_find_it_bind', 'f') + " Bind keys for find occurencies (leave empty for disable) + call pymode#default('g:pymode_rope_find_it_bind', 'f') -" Bind keys for organize imports (leave empty for disable) -call pymode#default('g:pymode_rope_organize_imports_bind', 'ro') + " Bind keys for organize imports (leave empty for disable) + call pymode#default('g:pymode_rope_organize_imports_bind', 'ro') -" Bind keys for rename variable/method/class in the project (leave empty for disable) -call pymode#default('g:pymode_rope_rename_bind', 'rr') + " Bind keys for rename variable/method/class in the project (leave empty for disable) + call pymode#default('g:pymode_rope_rename_bind', 'rr') -" Bind keys for rename module -call pymode#default('g:pymode_rope_rename_module_bind', 'r1r') + " Bind keys for rename module + call pymode#default('g:pymode_rope_rename_module_bind', 'r1r') -" Bind keys for convert module to package -call pymode#default('g:pymode_rope_module_to_package_bind', 'r1p') + " Bind keys for convert module to package + call pymode#default('g:pymode_rope_module_to_package_bind', 'r1p') -" Creates a new function or method (depending on the context) from the selected lines -call pymode#default('g:pymode_rope_extract_method_bind', 'rm') + " Creates a new function or method (depending on the context) from the selected lines + call pymode#default('g:pymode_rope_extract_method_bind', 'rm') -" Creates a variable from the selected lines -call pymode#default('g:pymode_rope_extract_variable_bind', 'rl') + " Creates a variable from the selected lines + call pymode#default('g:pymode_rope_extract_variable_bind', 'rl') -" Inline refactoring -call pymode#default('g:pymode_rope_inline_bind', 'ri') + " Inline refactoring + call pymode#default('g:pymode_rope_inline_bind', 'ri') -" Move refactoring -call pymode#default('g:pymode_rope_move_bind', 'rv') + " Move refactoring + call pymode#default('g:pymode_rope_move_bind', 'rv') -" Generate function -call pymode#default('g:pymode_rope_generate_function_bind', 'rnf') + " Generate function + call pymode#default('g:pymode_rope_generate_function_bind', 'rnf') -" Generate class -call pymode#default('g:pymode_rope_generate_class_bind', 'rnc') + " Generate class + call pymode#default('g:pymode_rope_generate_class_bind', 'rnc') -" Generate package -call pymode#default('g:pymode_rope_generate_package_bind', 'rnp') + " Generate package + call pymode#default('g:pymode_rope_generate_package_bind', 'rnp') -" Change signature -call pymode#default('g:pymode_rope_change_signature_bind', 'rs') + " Change signature + call pymode#default('g:pymode_rope_change_signature_bind', 'rs') -" Tries to find the places in which a function can be used and changes the -" code to call it instead -call pymode#default('g:pymode_rope_use_function_bind', 'ru') + " Tries to find the places in which a function can be used and changes the + " code to call it instead + call pymode#default('g:pymode_rope_use_function_bind', 'ru') -" Regenerate project cache on every save -call pymode#default('g:pymode_rope_regenerate_on_write', 1) + " Regenerate project cache on every save + call pymode#default('g:pymode_rope_regenerate_on_write', 1) +endif " }}} @@ -299,12 +305,12 @@ elseif g:pymode_python == 'python3' else - let g:pymode_doc = 0 - let g:pymode_lint = 0 - let g:pymode_path = 0 - let g:pymode_rope = 0 - let g:pymode_run = 0 - let g:pymode_virtualenv = 0 + let g:pymode_doc = v:false + let g:pymode_lint = v:false + let g:pymode_path = v:false + let g:pymode_rope = v:false + let g:pymode_run = v:false + let g:pymode_virtualenv = v:false command! -nargs=1 PymodePython echo diff --git a/syntax/python.vim b/syntax/python.vim index 090e9be1..e94877ee 100644 --- a/syntax/python.vim +++ b/syntax/python.vim @@ -118,7 +118,7 @@ endif if g:pymode_syntax_highlight_stars_operator syn match pythonExtraOperator "\%(\*\|\*\*\)" endif - + if g:pymode_syntax_highlight_self syn keyword pythonSelf self cls endif @@ -271,8 +271,8 @@ endif syn keyword pythonBuiltinObj True False Ellipsis None NotImplemented syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ endif - - if g:pymode_syntax_builtin_types + + if g:pymode_syntax_builtin_types syn keyword pythonBuiltinType type object syn keyword pythonBuiltinType str basestring unicode buffer bytearray bytes chr unichr syn keyword pythonBuiltinType dict int long bool float complex set frozenset list tuple From c9f1c3e6e58fcded7660526ced72f340087e1f85 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Tue, 7 Nov 2017 23:04:49 -0200 Subject: [PATCH 09/79] updated files in root folder according to 2082d0b8fed7fff10b3f335cefc6a51dd25ee0b2 (various improvements) --- .bumpversion.cfg | 2 +- .gitignore | 2 ++ Changelog.rst | 57 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3b087e6f..e29f1ee9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,6 +1,6 @@ [bumpversion] commit = True -current_version = 0.9.2 +current_version = 0.9.5 files = plugin/pymode.vim tag = True tag_name = {new_version} diff --git a/.gitignore b/.gitignore index f5674a78..40ca63ba 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ test.py todo.txt vendor vim.py +vim_session_*.vim +__*/ diff --git a/Changelog.rst b/Changelog.rst index e396eb69..af249a25 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -1,6 +1,48 @@ Changelog ========= + +## TODO +------- +* Move changelog rst syntax to markdown +* pymode_rope: check disables +* When loading a file without a history, substituting a word (eg 'cw') moves + the cursor to position 0 (equivalent to 'cw' then '0l') + * Fixed on `917e484` +* Inspect why files starting with: +~~~~~~ +def main(): + pass + + +if __name__ == '__main__': + main() +~~~~~~ +do not get loaded. + + +## 2017-07-xxx 0.9.5 +-------------------- +* pylama: migrated to submodule + + +## 2017-07-11 0.9.4 +-------------------- +* pylama: fixed erratic behavior of `skip` option causing unintended skipping + of lint checkers +* PEP257 requires `snowbalstemmer`: added as submodule +* Fixed handling of `g:pymode_lint_ignore` and `g:pymode_lint_select`: from + strings to list +* Migrated modules from `pymode/libs` to `submodules/ `__ + * Rationale: no need to single handedly update each module; removes burden + from developers +* Improved folding accuracy + * Improved nested definitions folding + * Improved block delimiting + + +## (changelog poorly maintained) 0.8.2 +-------------------------------------- * Pylama updated to version 5.0.5 * Rope libs updated * Add wdb to debugger list in breakpoint cmd @@ -140,7 +182,7 @@ Changelog -------------------- * Dont raise an exception when Logger has no message handler (c) nixon * Improve performance of white space removal (c) Dave Smith -* Improve ropemode support (c) s0undt3ch +* Improve ropemode support (c) s0undt3ch * Add `g:pymode_updatetime` option * Update autopep8 to version 0.8.1 @@ -151,7 +193,7 @@ Changelog ## 2012-09-06 0.6.8 ------------------- -* Add PEP8 indentation ":help 'pymode_indent'" +* Add PEP8 indentation ":help 'pymode_indent'" ## 2012-08-15 0.6.7 ------------------- @@ -165,7 +207,7 @@ Changelog * Fixed virtualenv support for windows users * Added pymode modeline ':help PythonModeModeline' * Added diagnostic tool ':call pymode#troubleshooting#Test()' -* Added `PyLintAuto` command ':help PyLintAuto' +* Added `PyLintAuto` command ':help PyLintAuto' * Code checking is async operation now * More, more fast the pymode folding * Repaired execution of python code @@ -191,12 +233,12 @@ Changelog ## 2012-03-13 0.6.0 ------------------- -* Add 'pymode_lint_hold' option +* Add 'pymode_lint_hold' option * Improve pymode loading speed * Add pep8, mccabe lint checkers * Now g:pymode_lint_checker can have many values Ex. "pep8,pyflakes,mccabe" -* Add 'pymode_lint_ignore' and 'pymode_lint_select' options +* Add 'pymode_lint_ignore' and 'pymode_lint_select' options * Fix rope keys * Fix python motion in visual mode * Add folding 'pymode_folding' @@ -258,7 +300,10 @@ Changelog ------------------- * Enable all syntax highlighting For old settings set in your vimrc: - let g:pymode_syntax_builtin_objs = 0 + + :: + +2082d0b8fed7fff10b3f335cefc6a51dd25ee0b2 let g:pymode_syntax_builtin_objs = 2 let g:pymode_syntax_builtin_funcs = 0 * Change namespace of syntax variables From b848f6294ca5858fd17eaf14783fa2042e8142b7 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Tue, 7 Nov 2017 23:12:02 -0200 Subject: [PATCH 10/79] updated pymode/pyfiles files according to 2082d0b8fed7fff10b3f335cefc6a51dd25ee0b2 (various improvements) --- pymode/__init__.py | 14 +++++++++----- pymode/lint.py | 44 +++++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/pymode/__init__.py b/pymode/__init__.py index d5e63ba3..6fbdd9e0 100644 --- a/pymode/__init__.py +++ b/pymode/__init__.py @@ -1,4 +1,4 @@ -""" Pymode support functions. """ +"""Pymode support functions.""" from __future__ import absolute_import @@ -7,14 +7,18 @@ def auto(): - """ Fix PEP8 erorrs in current buffer. """ + """Fix PEP8 erorrs in current buffer. + + pymode: uses it in command PymodeLintAuto with pymode#lint#auto() + + """ from .autopep8 import fix_file class Options(object): - aggressive = 2 + aggressive = 1 diff = False experimental = True - ignore = vim.eval('g:pymode_lint_ignore') + ignore = vim.eval('g:pymode_lint_ignore').split(',') in_place = True indent_size = int(vim.eval('&tabstop')) line_range = None @@ -28,7 +32,7 @@ class Options(object): def get_documentation(): - """ Search documentation and append to current buffer. """ + """Search documentation and append to current buffer.""" from ._compat import StringIO sys.stdout, _ = StringIO(), sys.stdout diff --git a/pymode/lint.py b/pymode/lint.py index b0f85655..25f2414c 100644 --- a/pymode/lint.py +++ b/pymode/lint.py @@ -15,7 +15,7 @@ pass -def code_check(): # noqa +def code_check(): """Run pylama and check current file. :return bool: @@ -24,32 +24,38 @@ def code_check(): # noqa with silence_stderr(): from pylama.core import run - from pylama.main import parse_options - from pylama.config import _override_options + from pylama.config import parse_options if not env.curbuf.name: return env.stop() + linters = env.var('g:pymode_lint_checkers') + env.debug(linters) + + # Fixed in v0.9.3: these two parameters may be passed as strings. + # DEPRECATE: v:0.10.0: need to be set as lists. + if isinstance(env.var('g:pymode_lint_ignore'), str): + ignore = env.var('g:pymode_lint_ignore').split(',') + else: + ignore = env.var('g:pymode_lint_ignore') + if isinstance(env.var('g:pymode_lint_select'), str): + select = env.var('g:pymode_lint_select').split(',') + else: + select = env.var('g:pymode_lint_select') options = parse_options( - force=1, - ignore=env.var('g:pymode_lint_ignore'), - select=env.var('g:pymode_lint_select'), + linters=linters, force=1, + ignore=ignore, + select=select, ) - - linters = env.var('g:pymode_lint_checkers', default=[]) - if linters: - _override_options(options, linters=",".join(linters)) - - for linter in dict(options.linters): - opts = env.var('g:pymode_lint_options_%s' % linter, silence=True) - if opts: - options.linters_params[linter] = options.linters_params.get(linter, {}) - options.linters_params[linter].update(opts) - - if 'pylint' in options.linters_params: - options.linters_params['pylint']['clear_cache'] = True env.debug(options) + for linter in linters: + opts = env.var('g:pymode_lint_options_%s' % linter, silence=True) + if opts: + options.linters_params[linter] = options.linters_params.get( + linter, {}) + options.linters_params[linter].update(opts) + path = os.path.relpath(env.curbuf.name, env.curdir) env.debug("Start code check: ", path) From 43c052e88f901acabd658d37aa6322e22e1c762a Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Mon, 13 Nov 2017 23:11:03 -0200 Subject: [PATCH 11/79] reverted v:false to 0 due to vim7 incompatibility --- plugin/pymode.vim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 83127829..a9b195fc 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -12,7 +12,7 @@ call pymode#default('g:pymode_debug', 0) if !g:pymode || &cp || &diff " Update pymode status to prevent loading in other files and adding this " condition to all of them. - let g:pymode = v:false + let g:pymode = 0 finish endif @@ -171,7 +171,7 @@ call pymode#default('g:pymode_breakpoint_cmd', '') " ROPE (refactoring, codeassist) {{{ " " Rope support -call pymode#default('g:pymode_rope', v:false) +call pymode#default('g:pymode_rope', 0) " System plugin variable if g:pymode_rope @@ -305,12 +305,12 @@ elseif g:pymode_python == 'python3' else - let g:pymode_doc = v:false - let g:pymode_lint = v:false - let g:pymode_path = v:false - let g:pymode_rope = v:false - let g:pymode_run = v:false - let g:pymode_virtualenv = v:false + let g:pymode_doc = 0 + let g:pymode_lint = 0 + let g:pymode_path = 0 + let g:pymode_rope = 0 + let g:pymode_run = 0 + let g:pymode_virtualenv = 0 command! -nargs=1 PymodePython echo From cc11bc3073a0ad3b37f36c90caf3ac47397550d6 Mon Sep 17 00:00:00 2001 From: alphaCTzo7G Date: Mon, 13 Nov 2017 17:28:51 -0800 Subject: [PATCH 12/79] Slack now has tonnes of unanswered question Better to redirect to Stackoverflow as very few people log into the slack channel to reply. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 0706f0c6..3596967d 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ *The project needs contributors* -** Python-mode Slack Channel is here: https://python-mode.herokuapp.com/ ** +** Please use Python-mode tag on Stackoverflow to ask questions: https://stackoverflow.com/questions/tagged/python-mode ** ----- From a2ecfc33c0de075fcde1fd5c778a1be4f85f16e0 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Wed, 15 Nov 2017 20:31:39 -0200 Subject: [PATCH 13/79] changed readme.rst to readme.md according to issues #805 and #813 --- README.rst | 367 ----------------------------------------------------- readme.md | 172 +++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 367 deletions(-) delete mode 100644 README.rst create mode 100644 readme.md diff --git a/README.rst b/README.rst deleted file mode 100644 index 3596967d..00000000 --- a/README.rst +++ /dev/null @@ -1,367 +0,0 @@ -|logo| Python-mode, Python in VIM -################################# - -.. image:: https://travis-ci.org/python-mode/python-mode.png?branch=develop - :target: https://travis-ci.org/python-mode/python-mode - ------ - -*The project needs contributors* - -** Please use Python-mode tag on Stackoverflow to ask questions: https://stackoverflow.com/questions/tagged/python-mode ** - ------ - -| -| Src: https://github.com/python-mode/python-mode -| Homepage: https://klen.github.io/python-mode/ -| Docs: https://github.com/python-mode/python-mode/blob/develop/doc/pymode.txt -| - -Python-mode is a vim plugin that helps you to create python code very quickly -by utilizing libraries including -`pylint`_, `rope`_, pydoc_, `pyflakes`_, `pep8`_, `autopep8`_, -`pep257`_ and `mccabe`_ -for features like static analysis, refactoring, folding, completion, -documentation, and more. - -The plugin contains all you need to develop python applications in Vim. - -There is no need to install `pylint`_, `rope`_ -or any other `Python Libraries`_ on your system. - -- Support Python version 2.6+ and 3.2+ -- Syntax highlighting -- Virtualenv support -- Run python code (``r``) -- Add/remove breakpoints (``b``) -- Improved Python indentation -- Python folding -- Python motions and operators (``]]``, ``3[[``, ``]]M``, ``vaC``, ``viM``, - ``daC``, ``ciM``, ...) -- Code checking (pylint_, pyflakes_, pylama_, ...) that can be run - simultaneously (``:PymodeLint``) -- Autofix PEP8 errors (``:PymodeLintAuto``) -- Search in python documentation (``K``) -- Code refactoring (rope_) -- Strong code completion (rope_) -- Go to definition (``g`` for `:RopeGotoDefinition`) -- And more, more ... - -See (very old) screencast here: http://www.youtube.com/watch?v=67OZNp9Z0CQ -(sorry for quality, this is my first screencast) Another old presentation here: -http://www.youtube.com/watch?v=YhqsjUUHj6g - -**To read python-mode documentation in Vim, see** ``:help pymode`` - - -.. contents:: - - -Requirements -============ - -- VIM >= 7.3 (mostly features needed `+python` or `+python3` support) - (also ``--with-features=big`` if you want ``g:pymode_lint_signs``) - - -How to install -============== - -Using pathogen (recommended) ----------------------------- -:: - - % cd ~/.vim - % mkdir -p bundle && cd bundle - % git clone https://github.com/python-mode/python-mode.git - -- Enable `pathogen `_ - in your ``~/.vimrc``: :: - - " Pathogen load - filetype off - - call pathogen#infect() - call pathogen#helptags() - - filetype plugin indent on - syntax on - - -Manually --------- -:: - - % git clone https://github.com/python-mode/python-mode.git - % cd python-mode - % cp -R * ~/.vim - -Then rebuild **helptags** in vim:: - - :helptags ~/.vim/doc/ - - -.. note:: **filetype-plugin** (``:help filetype-plugin-on``) and - **filetype-indent** (``:help filetype-indent-on``) - must be enabled to use python-mode. - - -Debian packages ---------------- -|Repository URL: https://klen.github.io/python-mode/deb/ - -Install with commands: - -:: - - add-apt-repository https://klen.github.io/python-mode/deb main - apt-get update - apt-get install vim-python-mode - -If you are getting the message: "The following signatures couldn't be verified because the public key is not available": :: - - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B5DF65307000E266 - -`vim-python-mode` using `vim-addons`, so after installation just enable -`python-mode` with command: :: - - vim-addons install python-mode - - -Troubleshooting -=============== - -If your python-mode doesn't work: - -1. Load Vim with only python-mode enabled (use `debug.vim` from pymode): :: - - vim -u /debug.vim - -And try to repeat your case. If no error occurs, seems like problem isn't in the -plugin. - -2. Type `:PymodeTroubleshooting` - -And fix any warnings or copy the output and send it to me. (For example, by -creating a `new github issue `_ -if one does not already exist for the problem). - - -Customization -============= - -You can override the default key bindings by redefining them in your `.vimrc`, for example: :: - - " Override go-to.definition key shortcut to Ctrl-] - let g:pymode_rope_goto_definition_bind = "" - - " Override run current python file key shortcut to Ctrl-Shift-e - let g:pymode_run_bind = "" - - " Override view python doc key shortcut to Ctrl-Shift-d - let g:pymode_doc_bind = "" - - -Frequent Problems -================= - -Read this section before opening an issue on the tracker. - -Python 3 Syntax ---------------- - -By default python-mode uses python 2 syntax checking. To enable python 3 -syntax checking (e.g. for async) add:: - - let g:pymode_python = 'python3' - -To your vimrc or exrc file - - -Documentation -============= - -Documentation is available in your vim ``:help pymode`` - - -Bugtracker -=========== - -If you have any suggestions, bug reports or -annoyances please report them to the issue tracker -at https://github.com/python-mode/python-mode/issues - - -Contributing -============ - -* Kirill Klenov (horneds@gmail.com) -* Bryce Guinta (https://github.com/brycepg) - -Also see the `AUTHORS` file. - -Development of python-mode happens at github: -https://github.com/python-mode/python-mode - -Please make a pull request to `development` branch and add yourself to -`AUTHORS`. - -Source Links -=================== -- `doc/pymode.txt - `__ - -- ``:help pymode`` -- `plugin/pymode.vim - `__ - -- python-mode VIM plugin -- `syntax/python.vim - `__ - -- python-mode ``python.vim`` VIM syntax -- `syntax/pyrex.vim - `__ - -- ``pyrex.vim`` VIM syntax (pyrex, Cython) -- `t/ - `__ - -- ``*.vim`` more python-mode VIM configuration -- `pymode/ - `__ - -- ``*.py`` -- python-mode Python module -- `pymode/libs/ - `__ - -- ``*.py`` -- `Python Libraries <#python-libraries>`__ - - -Python Libraries ------------------- -Vendored Python modules are located -mostly in -`pymode/libs/ `__. - - -====== -rope -====== -| PyPI: https://pypi.python.org/pypi/rope -| Src: https://github.com/python-rope/rope -| Docs: https://github.com/python-rope/rope/blob/master/docs/overview.rst -| Docs: https://github.com/python-rope/rope/blob/master/docs/library.rst - -======================== -ropemode -======================== -| PyPI: https://pypi.python.org/pypi/ropemode -| Src: https://github.com/python-rope/ropemode - -========= -ropevim -========= -| PyPI: https://pypi.python.org/pypi/ropevim -| Src: https://github.com/python-rope/ropevim -| Docs: https://github.com/python-rope/ropevim/blob/master/doc/ropevim.txt - -======= -pylama -======= -| PyPI: https://pypi.python.org/pypi/pylama -| Src: https://github.com/klen/pylama - -======== -pylint -======== -| PyPI: https://pypi.python.org/pypi/pylint -| Src: https://bitbucket.org/logilab/pylint -| Homepage: http://www.pylint.org/ -| Docs: http://docs.pylint.org/ -| Docs: http://docs.pylint.org/message-control.html -| Docs: http://docs.pylint.org/faq.html#message-control -| ErrCodes: http://pylint-messages.wikidot.com/all-codes -| ErrCodes: http://pylint-messages.wikidot.com/all-messages - -========== -pyflakes -========== -| PyPI: https://pypi.python.org/pypi/pyflakes -| Src: https://github.com/pyflakes/pyflakes -| ErrCodes: https://flake8.readthedocs.org/en/latest/warnings.html - -====== -pep8 -====== -| PyPI: https://pypi.python.org/pypi/pep8 -| Src: http://github.com/jcrocholl/pep8 -| PEP 8: http://www.python.org/dev/peps/pep-0008/ -| PEP 8: http://legacy.python.org/dev/peps/pep-0008/ -| Docs: https://pep8.readthedocs.org/en/latest/ -| Docs: https://pep8.readthedocs.org/en/latest/intro.html#configuration -| ErrCodes: https://pep8.readthedocs.org/en/latest/intro.html#error-codes - -========= -autopep8 -========= -| PyPI: https://pypi.python.org/pypi/autopep8 -| Src: https://github.com/hhatto/autopep8 - -======= -pep257 -======= -| PyPI: https://pypi.python.org/pypi/pep257 -| Src: http://github.com/GreenSteam/pep257 -| Docs: https://pep257.readthedocs.org/en/latest/ -| PEP 257: http://www.python.org/dev/peps/pep-0257/ -| ErrCodes: https://pep257.readthedocs.org/en/latest/error_codes.html - -======= -mccabe -======= -| PyPI: https://pypi.python.org/pypi/mccabe -| Src: https://github.com/flintwork/mccabe -| Docs: https://en.wikipedia.org/wiki/Cyclomatic_complexity - - -Vim Libraries ---------------- -Vendored Vim modules are located mostly in ``t/``. - -====================== -Python syntax for vim -====================== -| Src: http://www.hlabs.spb.ru/vim/python.vim - - -===================== -PEP8 VIM indentation -===================== -| Src: http://github.com/hynek/vim-python-pep8-indent - - - -Copyright -========= - -Copyright © 2013-2015 Kirill Klenov (klen_) - -License -======= - -Licensed under a `GNU lesser general public license`_. - -If you like this plugin, I would very appreciated if you kindly send me a postcard :) -My address is here: "Russia, 143500, MO, Istra, pos. Severny 8-3" to "Kirill Klenov". -**Thanks for support!** - -.. _GNU lesser general public license: http://www.gnu.org/copyleft/lesser.html -.. _klen: https://klen.github.com/ -.. _pydoc: http://docs.python.org/library/pydoc.html -.. _pathogen: https://github.com/tpope/vim-pathogen -.. _rope_: https://pypi.python.org/pypi/rope -.. _pylama_: https://github.com/klen/pylama -.. _pylint_: https://bitbucket.org/logilab/pylint -.. _pyflakes_: https://pypi.python.org/pypi/pyflakes -.. _autopep8_: https://github.com/hhatto/autopep8 -.. _pep257_: http://github.com/GreenSteam/pep257 -.. _mccabe_: https://github.com/flintwork/mccabe -.. _pythonvim: http://www.hlabs.spb.ru/vim/python.vim -.. _pep8_: http://github.com/jcrocholl/pep8 -.. _pep8indent: http://github.com/hynek/vim-python-pep8-indent -.. |logo| image:: https://raw.github.com/python-mode/python-mode/develop/logo.png diff --git a/readme.md b/readme.md new file mode 100644 index 00000000..4798a99c --- /dev/null +++ b/readme.md @@ -0,0 +1,172 @@ +![](https://raw.github.com/python-mode/python-mode/develop/logo.png) +# Python-mode, a Python IDE for Vim + +------------------------------------------------------------------------------- + +*This project needs contributors.* + +**Please use python-mode tag on Stackoverflow to ask questions:** + + +------------------------------------------------------------------------------- + +Python-mode is a Vim plugin that magically converts Vim into a Python IDE. + +Why Python-mode? + +1. **Be more productive**: Pymode saves time by bring all tools necessary for + professional developers so that you can focus on bigger things. It has been + finely tuned based on decades of experience working with Vim and is + constantly kept uptodate. +2. **Get smart assistance**: Pymode knows all about your code. We use the + best-in-class intellisense code completion, on-the-fly error checking and + quick-fixes; easy project navigation and much more. +3. **Use the full power and capabilities of Vim**: Unlike traditional IDEs + which can only provide a small subset of Vim functionalities, you can do + everything and anything that you can in Vim. +4. **Modular structure**: We attempt to be create Python-mode in the same + principles of python: i.e. have a modular structure, so that as and when + better libraries evolve, we can provide you the best experience, while + abstracting the details so that you can get back to what you do best. +5. **Written mostly in Python**: 96.1% written in Python. Well we love Python + :) + +The plugin contains all you need to develop python applications in Vim. + +* Support Python version 2.6+ and 3.2+ +* Syntax highlighting +* Virtualenv support +* Run python code (`r`) +* Add/remove breakpoints (`b`) +* Improved Python indentation +* Python motions and operators (`]]`, `3[[`, `]]M`, `vaC`, `viM`, + `daC`, `ciM`, ...) +* Improved Python folding +* Run multiple code checkers simultaneously (`:PymodeLint`) +* Autofix PEP8 errors (`:PymodeLintAuto`) +* Search in python documentation (`K`) +* Code refactoring +* Intellisense code-completion +* Go to definition (`g`) +* And more, more ... + +See a screencast here: +Another old presentation here: + +**To read python-mode documentation in Vim, use** `:help pymode`. + +# Requirements + +Vim >= 7.3 (most features needed +python or +python3 support) (also +`--with-features=big` if you want `g:pymode_lint_signs`). + +# How to install + +## Manually (according to vim's package structure) + +As of vim8 there is an officially supported way of adding plugins. See `:tab +help packages` in vim for details. + + cd ~/.vim/pack/foo/start + git clone https://github.com/python-mode/python-mode.git + cd python-mode + git submodule update --init --recursive + + +## Using pathogen + + % cd ~/.vim + % mkdir -p bundle && cd bundle + % git clone https://github.com/python-mode/python-mode.git + +Enable [pathogen](https://github.com/tpope/vim-pathogen) in your `~/.vimrc`: + + " Pathogen load + filetype off + + call pathogen#infect() + call pathogen#helptags() + + filetype plugin indent on + syntax on + +## Manually + + % git clone https://github.com/python-mode/python-mode.git + % cd python-mode + % cp -R * ~/.vim + +Then rebuild **helptags** in vim: + + :helptags ~/.vim/doc/ + +**filetype-plugin** (`:help filetype-plugin-on`) and **filetype-indent** +(`:help filetype-indent-on`) must be enabled to use python-mode. + +# Troubleshooting + +If your python-mode doesn't work: + +1. Load Vim with only python-mode enabled (use debug.vim from pymode): + + vim -u /debug.vim + + And try to repeat your case. If no error occurs, seems like problem isn't in + the plugin. + +2. Type `:PymodeTroubleshooting` and fix any warnings or copy the output and + send it to me. (For example, by creating a [new github issue]( + https://github.com/python-mode/python-mode/issues/new) if one does + not already exist for the problem). + +# Frequent problems + +Read this section before opening an issue on the tracker. + +## Python 3 syntax + +By default python-mode uses python 2 syntax checking. To enable python 3 syntax +checking (e.g. for async) add: + + let g:pymode_python = 'python3' + +To your vimrc or exrc file. + +# Documentation + +Documentation is available in your vim `:help pymode`. + +# Bugtracker + +If you have any suggestions, bug reports or annoyances please report them to +the issue tracker at: + + +# Contributing + +* Kirill Klenov () +* Felipe Vieira () + +Also see the AUTHORS file. + +Development of python-mode happens at github: + + +Please make a pull request to development branch and add yourself to AUTHORS. + +### Python libraries + +Vendored Python modules are located mostly in +[pymode/libs/](https://github.com/python-mode/python-mode/tree/develop/pymode/libs). + +# Copyright + +Copyright © 2013-2015 Kirill Klenov (). + +# License + +Licensed under a [GNU lesser general public license](). + +If you like this plugin, I would very appreciated if you kindly send me +a postcard :) My address is here: "Russia, 143500, MO, Istra, pos. Severny 8-3" +to "Kirill Klenov". **Thanks for support!** From 5a2919217e5bfcd29123cca42b70d0df420c3a19 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Wed, 15 Nov 2017 20:59:17 -0200 Subject: [PATCH 14/79] updated authors --- AUTHORS | 7 +++++-- Changelog.rst | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index cc3de277..a917a124 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,8 +1,10 @@ -Maintainers: +Author: * Kirill Klenov -* Bryce Guinta (https://github.com/brycepg) +Maintainers: + +* Felipe M. Vieira (https://github.com/fmv1992) Contributors: @@ -15,6 +17,7 @@ Contributors: * Boris Filippov (http://github.com/frenzykryger); * Brad Mease (http://github.com/bmease) * Brendan Maguire (https://github.com/brendanmaguire) +* Bryce Guinta (https://github.com/brycepg) * Daniel Hahler (http://github.com/blueyed) * David Vogt (http://github.com/winged); * Denis Kasak (http://github.com/dkasak); diff --git a/Changelog.rst b/Changelog.rst index af249a25..158c4db5 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -303,7 +303,7 @@ do not get loaded. :: -2082d0b8fed7fff10b3f335cefc6a51dd25ee0b2 let g:pymode_syntax_builtin_objs = 2 + let g:pymode_syntax_builtin_objs = 0 let g:pymode_syntax_builtin_funcs = 0 * Change namespace of syntax variables From 6d497a405a66096ef5c0b51fd7ce260236ea5fda Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 19:57:23 -0200 Subject: [PATCH 15/79] changed troubleshooting mechanism and updated documentation on development guidelines --- autoload/pymode.vim | 21 +- autoload/pymode/debug.vim | 57 +++++ autoload/pymode/folding.vim | 3 - autoload/pymode/troubleshooting.vim | 89 ------- debug.vim | 13 - debugvimrc.vim | 21 ++ doc/pymode.txt | 376 +++++++++++++++------------- ftplugin/python/pymode.vim | 37 +++ plugin/pymode.vim | 1 - readme.md | 18 +- syntax/python.vim | 6 - 11 files changed, 339 insertions(+), 303 deletions(-) create mode 100644 autoload/pymode/debug.vim delete mode 100644 autoload/pymode/troubleshooting.vim delete mode 100644 debug.vim create mode 100644 debugvimrc.vim diff --git a/autoload/pymode.vim b/autoload/pymode.vim index 3127431d..6beb89a8 100644 --- a/autoload/pymode.vim +++ b/autoload/pymode.vim @@ -76,7 +76,6 @@ fun! pymode#trim_whitespaces() "{{{ endif endfunction "}}} - fun! pymode#save() "{{{ if &modifiable && &modified try @@ -120,9 +119,25 @@ fun! pymode#buffer_post_write() "{{{ endfunction "}}} fun! pymode#debug(msg) "{{{ + " Pymode's debug function. + " Should be called by other pymode's functions to report outputs. See + " the function PymodeDebugFolding for example. + " TODO: why echom here creates a problem? + " echom '' . a:msg + '|||||||||||' + + let l:info_separator = repeat('-', 79) + if g:pymode_debug - let g:pymode_debug += 1 - echom string(g:pymode_debug) . ': ' . string(a:msg) + if ! exists('g:pymode_debug_counter') + let g:pymode_debug_counter = 0 + endif + let g:pymode_debug_counter += 1 + " NOTE: Print a separator for every message except folding ones (since + " they could be many). + if a:msg !~ 'has folding:' + echom l:info_separator + endif + echom '' . 'pymode debug msg ' . g:pymode_debug_counter . ': ' . a:msg endif endfunction "}}} diff --git a/autoload/pymode/debug.vim b/autoload/pymode/debug.vim new file mode 100644 index 00000000..c24a5ee4 --- /dev/null +++ b/autoload/pymode/debug.vim @@ -0,0 +1,57 @@ +" Set debugging functions. + +" DESC: Get debug information about pymode problem. +fun! pymode#debug#sysinfo() "{{{ + " OS info. {{{ + let l:os_name = "Unknown" + if has('win16') || has('win32') || has('win64') + let l:os_name = "Windows" + else + let l:os_name = substitute(system('uname'), "\n", "", "") + endif + call pymode#debug("Operating system: " . l:os_name) + " }}} + " Loaded scripts info. {{{ + call pymode#debug("Scriptnames:") + let l:scriptnames_var = execute('scriptnames') + " }}} + " Variables info. {{{ + " Drop verbose file temporarily to prevent the 'let' from showing up. + let l:tmp = &verbosefile + set verbosefile= + let l:all_variables = filter( + \ split(execute('let', 'silent!'), '\n'), + \ 'v:val =~ "^pymode"') + let &verbosefile = l:tmp + " NOTE: echom does not display multiline messages. Thus a for loop is + " needed. + call pymode#debug("Pymode variables:") + for pymodevar in sort(l:all_variables) + echom pymodevar + endfor + " }}} + " Github commit info. {{{ + " Find in the scriptnames the first occurence of 'python-mode'. Then parse + " the result outputting its path. This is in turn fed into the git command. + call pymode#debug("Git commit: ") + let l:pymode_folder = substitute( + \ filter( + \ split(l:scriptnames_var, '\n'), + \ 'v:val =~ "/python-mode/"')[0], + \ '\(^\s\+[0-9]\+:\s\+\)\([/~].*python-mode\/\)\(.*\)', + \ '\2', + \ '') + let l:git_head_sha1 = system('git -C ' . expand(l:pymode_folder). ' rev-parse HEAD ' ) + echom join(filter(split(l:git_head_sha1, '\zs'), 'v:val =~? "[0-9A-Fa-f]"'), '') + " }}} + call pymode#debug("End of pymode#debug#sysinfo") +endfunction "}}} + +" DESC: Define debug folding function. +function! pymode#debug#foldingexpr(lnum) "{{{ + let l:get_folding_result = pymode#folding#expr(a:lnum) + " NOTE: the 'has folding:' expression is special in the pymode#debug. + call pymode#debug('line ' . a:lnum . ' has folding:' . l:get_folding_result) + return pymode#folding#expr(a:lnum) +endfunction +" }}} diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index 24f6b530..ca98b5c9 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -20,7 +20,6 @@ if s:symbol == '' endif " '''''''' - fun! pymode#folding#text() " {{{ let fs = v:foldstart while getline(fs) !~ s:def_regex && getline(fs) !~ s:docstring_begin_regex @@ -182,8 +181,6 @@ fun! s:BlockStart(line_number) "{{{ let max_indent = max([indent(prevnonblank(a:line_number)) - &shiftwidth, 0]) endif - " " Debug: - return searchpos('\v^\s{,'.max_indent.'}(def |class )\w', 'bcnW')[0] endfunction "}}} diff --git a/autoload/pymode/troubleshooting.vim b/autoload/pymode/troubleshooting.vim deleted file mode 100644 index 09955c92..00000000 --- a/autoload/pymode/troubleshooting.vim +++ /dev/null @@ -1,89 +0,0 @@ -" DESC: Get debug information about pymode problem -fun! pymode#troubleshooting#test() "{{{ - new - setlocal buftype=nofile bufhidden=delete noswapfile nowrap - - let os = "Unknown" - if has('win16') || has('win32') || has('win64') - let os = "Windows" - else - let os = substitute(system('uname'), "\n", "", "") - endif - - if !pymode#default('g:pymode_init', 1) - call pymode#init(expand(':p:h'), g:pymode_paths) - call pymode#virtualenv#init() - call pymode#breakpoint#init() - endif - - call append('0', ['Pymode diagnostic', - \ '===================', - \ 'VIM:' . v:version . ', OS: ' . os .', multi_byte:' . has('multi_byte') . ', pymode: ' . g:pymode_version . ', pymode-python: ' . g:pymode_python, - \ '']) - - if !exists('#filetypeplugin') - call append('$', ['WARNING: ', 'Python-mode required :filetype plugin indent on', '']) - endif - - call append('$', ['+python: ' . has('python')]) - call append('$', ['+python3: ' . has('python3'), '']) - - if g:pymode_python == 'disable' - - if !has('python') && !has('python3') - - call append('$', ['WARNING: Python-mode required vim compiled with +python or +python3.', - \ '"lint, rope, run, doc, virtualenv" features disabled.', '']) - - else - - call append('$', ['WARNING: Python is disabled by `pymode_python` option.', - \ '"lint, rope, run, doc, virtualenv" features disabled.', '']) - - endif - - else - - call append('$', 'VIM python paths:') - call append('$', '-----------------') - PymodePython << EOF -import vim -vim.command('let l:output = %s' % repr(sys.path)) -EOF - call append('$', output) - call append('$', '') - - endif - - call append('$', 'Pymode variables:') - call append('$', '-------------------') - call append('$', 'let pymode = ' . string(g:pymode)) - call append('$', 'let pymode_breakpoint = ' . string(g:pymode_breakpoint)) - call append('$', 'let pymode_breakpoint_bind = ' . string(g:pymode_breakpoint_bind)) - call append('$', 'let pymode_doc = ' . string(g:pymode_doc)) - call append('$', 'let pymode_doc_bind = ' . string(g:pymode_doc_bind)) - call append('$', 'let pymode_folding = ' . string(g:pymode_folding)) - call append('$', 'let pymode_indent = ' . string(g:pymode_indent)) - call append('$', 'let pymode_lint = ' . string(g:pymode_lint)) - call append('$', 'let pymode_lint_checkers = ' . string(g:pymode_lint_checkers)) - call append('$', 'let pymode_lint_cwindow = ' . string(g:pymode_lint_cwindow)) - call append('$', 'let pymode_lint_ignore = ' . string(g:pymode_lint_ignore)) - call append('$', 'let pymode_lint_message = ' . string(g:pymode_lint_message)) - call append('$', 'let pymode_lint_on_fly = ' . string(g:pymode_lint_on_fly)) - call append('$', 'let pymode_lint_on_write = ' . string(g:pymode_lint_on_write)) - call append('$', 'let pymode_lint_select = ' . string(g:pymode_lint_select)) - call append('$', 'let pymode_lint_signs = ' . string(g:pymode_lint_signs)) - call append('$', 'let pymode_motion = ' . string(g:pymode_motion)) - call append('$', 'let pymode_options = ' . string(g:pymode_options)) - call append('$', 'let pymode_paths = ' . string(g:pymode_paths)) - call append('$', 'let pymode_quickfix_maxheight = ' . string(g:pymode_quickfix_maxheight)) - call append('$', 'let pymode_quickfix_minheight = ' . string(g:pymode_quickfix_minheight)) - call append('$', 'let pymode_rope = ' . string(g:pymode_rope)) - call append('$', 'let pymode_run = ' . string(g:pymode_run)) - call append('$', 'let pymode_run_bind = ' . string(g:pymode_run_bind)) - call append('$', 'let pymode_trim_whitespaces = ' . string(g:pymode_trim_whitespaces)) - call append('$', 'let pymode_virtualenv = ' . string(g:pymode_virtualenv)) - call append('$', 'let pymode_virtualenv_enabled = ' . string(g:pymode_virtualenv_enabled)) - call append('$', 'let pymode_virtualenv_path = ' . string(g:pymode_virtualenv_path)) - -endfunction "}}} diff --git a/debug.vim b/debug.vim deleted file mode 100644 index c7d32661..00000000 --- a/debug.vim +++ /dev/null @@ -1,13 +0,0 @@ -" Use this settings for testing the plugin. -" Run vim with command -" -" $ vim -u debug.py -" -" Only python-mode will be loaded. - - -execute('set rtp+='. expand(':p:h')) -set rtp -=$HOME/.vim -set rtp -=$HOME/.vim/after -set nocp -syntax enable diff --git a/debugvimrc.vim b/debugvimrc.vim new file mode 100644 index 00000000..750062b6 --- /dev/null +++ b/debugvimrc.vim @@ -0,0 +1,21 @@ +" Use this settings for testing the plugin. +" +" Run vim with command: +" +" $ vim -u ./debug.vim /my/py/file.py +" +" Only python-mode will be loaded. + +" Modify vimrc configuration. +execute('set rtp+='. expand(':p:h')) +set rtp -=$HOME/.vim +set rtp -=$HOME/.vim/after +set nocompatible + +" Activate debugging. +let g:pymode_debug = 1 + +" Define a common shell for non Windows systems. +if ! (has('win16') || has('win32') || has('win64')) + set shell=/bin/bash +endif diff --git a/doc/pymode.txt b/doc/pymode.txt index f466508b..4a29d6ce 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -1,4 +1,4 @@ -*pymode.txt* *python-mode.txt* *pymode* *python-mode* +*pymode.txt* For Vim Version 8.0 Last change: 2017 November 11 ____ _ _ ____ _ _ _____ _ _ __ __ _____ ____ ____ ~ ( _ \( \/ )(_ _)( )_( )( _ )( \( )___( \/ )( _ )( _ \( ___) ~ @@ -8,34 +8,39 @@ Version: 0.9.4 -============================================================================== -CONTENTS *pymode-contents* - - 1.Intro.......................................................|pymode-intro| - 2.Common functionality.......................................|pymode-common| - 2.1 Python version...............................|pymode-python-version| - 2.2 Python indentation...................................|pymode-indent| - 2.3 Python folding......................................|pymode-folding| - 2.4 Vim motion...........................................|pymode-motion| - 2.5 Show documentation............................|pymode-documentation| - 2.6 Support virtualenv...............................|pymode-virtualenv| - 2.7 Run code................................................|pymode-run| - 2.8 Breakpoints.....................................|pymode-breakpoints| - 3. Code checking...............................................|pymode-lint| - 3.1 Code checkers options..........................|pymode-lint-options| - 4. Rope support................................................|pymode-rope| - 4.1 Code completion..................................|pymode-completion| - 4.2 Find definition.................................|pymode-rope-findit| - 4.3 Refactoring................................|pymode-rope-refactoring| - 4.4 Undo/Redo changes.................................|pymode-rope-undo| - 5. Syntax....................................................|pymode-syntax| - 6.FAQ...........................................................|pymode-faq| - 7.Credits...................................................|pymode-credits| - 8.License...................................................|pymode-license| - -============================================================================== +=============================================================================== +CONTENTS *pymode-contents* + +1. Intro...........................................................|pymode-intro| +2. Common functionality...........................................|pymode-common| + 2.1 Python version....................................|pymode-python-version| + 2.2 Python indentation........................................|pymode-indent| + 2.3 Python folding...........................................|pymode-folding| + 2.4 Vim motion................................................|pymode-motion| + 2.5 Show documentation.................................|pymode-documentation| + 2.6 Support virtualenv....................................|pymode-virtualenv| + 2.7 Run code.....................................................|pymode-run| + 2.8 Breakpoints..........................................|pymode-breakpoints| +3. Code checking....................................................|pymode-lint| + 3.1 Code checkers options...............................|pymode-lint-options| +4. Rope support.....................................................|pymode-rope| + 4.1 Code completion.......................................|pymode-completion| + 4.2 Find definition......................................|pymode-rope-findit| + 4.3 Refactoring.....................................|pymode-rope-refactoring| + 4.4 Undo/Redo changes......................................|pymode-rope-undo| +5. Syntax.........................................................|pymode-syntax| +6. FAQ...............................................................|pymode-faq| +7. Development...............................................|pymode-development| +8. Credits.......................................................|pymode-credits| +9. License.......................................................|pymode-license| + +=============================================================================== 1. Intro ~ - *pymode-intro* + *pymode-intro* + +XXX IMPORTANT: As of 2017-11-18 python-mode is going through a major redesign. +Thus some of its functionality may not work as expected. Please be patient and +do report bugs or inconsistencies in its documentation. Python-mode is a vim plugin that allows you to use the pylint, rope, and pydoc libraries in vim to provide features like python code bug checking, @@ -46,7 +51,7 @@ need to install the pylint or rope libraries on your system. Python-mode contains all you need to develop python applications in Vim. -Features: *pymode-features* +Features: *pymode-features* - Support Python version 2.6+ and 3.2+ - Syntax highlighting @@ -67,34 +72,34 @@ Features: *pymode-features* - And more, more ... -============================================================================== +=============================================================================== 2. Common functionality ~ - *pymode-common* + *pymode-common* This script provides the following options that can customizes the behavior of -PythonMode. These options should be set in your |vimrc|. +python-mode. These options should be set in your |vimrc|. - Below shows the default values. +Find below the default values: -Turn on the whole plugin *'g:pymode'* +Turn on the whole plugin. *'g:pymode'* > let g:pymode = 1 -Turn off plugin's warnings *'g:pymode_warnings'* +Turn off plugin's warnings. *'g:pymode_warnings'* > let g:pymode_warnings = 1 -Add paths to `sys.path` *'g:pymode_paths'* +Add paths to `sys.path` *'g:pymode_paths'* Value is list of path's strings. > let g:pymode_paths = [] -Trim unused white spaces on save *'g:pymode_trim_whitespaces'* +Trim unused white spaces on save. *'g:pymode_trim_whitespaces'* > let g:pymode_trim_whitespaces = 1 -Setup default python options *'g:pymode_options'* +Setup default python options. *'g:pymode_options'* > let g:pymode_options = 1 @@ -111,29 +116,29 @@ python buffers: > setlocal commentstring=#%s setlocal define=^\s*\\(def\\\\|class\\) -Setup max line length *'g:pymode_options_max_line_length'* +Setup max line length *'g:pymode_options_max_line_length'* > let g:pymode_options_max_line_length = 79 -Enable colorcolumn display at max_line_length *'g:pymode_options_colorcolumn'* +Enable colorcolumn display at max_line_length. *'g:pymode_options_colorcolumn'* > let g:pymode_options_colorcolumn = 1 -Setup pymode |quickfix| window +Setup pymode |quickfix| window. - *'g:pymode_quickfix_maxheight'* *'g:pymode_quickfix_minheight'* + *'g:pymode_quickfix_maxheight'* *'g:pymode_quickfix_minheight'* > let g:pymode_quickfix_minheight = 3 let g:pymode_quickfix_maxheight = 6 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.1. Python version ~ - *pymode-python-version* + *pymode-python-version* By default pymode looks for current python version supported in your Vim. You could choose prefer version, but value will be tested on loading. - *'g:pymode_python'* + *'g:pymode_python'* > let g:pymode_python = 'python' @@ -143,73 +148,73 @@ python-features of **pymode** will be disabled. Set value to `python3` if you are working with python3 projects. You could use |exrc| ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.2 Python indentation ~ - *pymode-indent* + *pymode-indent* Pymode supports PEP8-compatible python indent. -Enable pymode indentation *'g:pymode_indent'* +Enable pymode indentation *'g:pymode_indent'* > let g:pymode_indent = 1 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.3 Python folding ~ - *pymode-folding* + *pymode-folding* Fast and usual python folding in Vim. -Enable pymode folding *'g:pymode_folding'* +Enable pymode folding *'g:pymode_folding'* > let g:pymode_folding = 1 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.4 Vim motion ~ - *pymode-motion* + *pymode-motion* Support Vim motion (See |operator|) for python objects (such as functions, class and methods). `C` — means class `M` — means method or function - *pymode-motion-keys* - -================ ============================ -Key Command -================ ============================ -[[ Jump to previous class or function (normal, visual, operator modes) -]] Jump to next class or function (normal, visual, operator modes) -[M Jump to previous class or method (normal, visual, operator modes) -]M Jump to next class or method (normal, visual, operator modes) -aC Select a class. Ex: vaC, daC, yaC, caC (normal, operator modes) -iC Select inner class. Ex: viC, diC, yiC, ciC (normal, operator modes) -aM Select a function or method. Ex: vaM, daM, yaM, caM (normal, operator modes) -iM Select inner function or method. Ex: viM, diM, yiM, ciM (normal, operator modes) -================ ============================ - -Enable pymode-motion *'g:pymode_motion'* + *pymode-motion-keys* + +==== ============================ +Key Command +==== ============================ +[[ Jump to previous class or function (normal, visual, operator modes) +]] Jump to next class or function (normal, visual, operator modes) +[M Jump to previous class or method (normal, visual, operator modes) +]M Jump to next class or method (normal, visual, operator modes) +aC Select a class. Ex: vaC, daC, yaC, caC (normal, operator modes) +iC Select inner class. Ex: viC, diC, yiC, ciC (normal, operator modes) +aM Select a function or method. Ex: vaM, daM, yaM, caM (normal, operator modes) +iM Select inner function or method. Ex: viM, diM, yiM, ciM (normal, operator modes) +==== ============================ + +Enable pymode-motion *'g:pymode_motion'* > let g:pymode_motion = 1 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.5 Show documentation ~ - *pymode-documentation* + *pymode-documentation* Pymode could show documentation for current word by `pydoc`. Commands: *:PymodeDoc* — show documentation -Turns on the documentation script *'g:pymode_doc'* +Turns on the documentation script *'g:pymode_doc'* > let g:pymode_doc = 1 Bind keys to show documentation for current word (selection) - *'g:pymode_doc_bind'* + *'g:pymode_doc_bind'* > let g:pymode_doc_bind = 'K' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.6 Support virtualenv ~ - *pymode-virtualenv* + *pymode-virtualenv* Commands: *:PymodeVirtualenv* -- Activate virtualenv (path can be absolute or @@ -219,33 +224,33 @@ Enable automatic virtualenv detection *'g:pymode_virtualenv' > let g:pymode_virtualenv = 1 -Set path to virtualenv manually *'g:pymode_virtualenv_path'* +Set path to virtualenv manually *'g:pymode_virtualenv_path'* > let g:pymode_virtualenv_path = $VIRTUAL_ENV ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.7 Run code ~ - *pymode-run* + *pymode-run* Commands: *:PymodeRun* -- Run current buffer or selection -Turn on the run code script *'g:pymode_run'* +Turn on the run code script *'g:pymode_run'* > let g:pymode_run = 1 -Binds keys to run python code *'g:pymode_run_bind'* +Binds keys to run python code *'g:pymode_run_bind'* > let g:pymode_run_bind = 'r' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 2.8 Breakpoints ~ - *pymode-breakpoints* + *pymode-breakpoints* Pymode automatically detects available debugger (like pdb, ipdb, pudb) and user can set/unset breakpoint with one key and without code checking and etc. -Enable functionality *'g:pymode_breakpoint'* +Enable functionality *'g:pymode_breakpoint'* > let g:pymode_breakpoint = 1 @@ -258,9 +263,9 @@ Manually set breakpoint command (leave empty for automatic detection) let g:pymode_breakpoint_cmd = '' -============================================================================== +=============================================================================== 3. Code checking ~ - *pymode-lint* + *pymode-lint* Pymode supports `pylint`, `pep257`, `pep8`, `pyflakes`, `mccabe` code checkers. You could run several similar checkers. @@ -277,44 +282,45 @@ Commands: *:PymodeLintToggle* -- Toggle code checking *:PymodeLintAuto* -- Fix PEP8 errors in current buffer automatically -Turn on code checking *'g:pymode_lint'* +Turn on code checking *'g:pymode_lint'* > let g:pymode_lint = 1 -Check code on every save (if file has been modified) *'g:pymode_lint_on_write'* +Check code on every save (if file has been modified) *'g:pymode_lint_on_write'* > let g:pymode_lint_on_write = 1 -Check code on every save (every) *'g:pymode_lint_unmodified'* +Check code on every save (every) *'g:pymode_lint_unmodified'* > let g:pymode_lint_unmodified = 0 -Check code when editing (on the fly) *'g:pymode_lint_on_fly'* +Check code when editing (on the fly) *'g:pymode_lint_on_fly'* > let g:pymode_lint_on_fly = 0 -Show error message if cursor placed at the error line *'g:pymode_lint_message'* +Show error message if cursor placed at the error line *'g:pymode_lint_message'* > let g:pymode_lint_message = 1 -Default code checkers (you could set several) *'g:pymode_lint_checkers'* +Default code checkers (you could set several) *'g:pymode_lint_checkers'* > let g:pymode_lint_checkers = ['pyflakes', 'pep8', 'mccabe'] Values may be chosen from: `pylint`, `pep8`, `mccabe`, `pep257`, `pyflakes`. -Skip errors and warnings *'g:pymode_lint_ignore'* -E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors that starts with E2) and etc +Skip errors and warnings *'g:pymode_lint_ignore'* +E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors that starts with E2) and +etc > let g:pymode_lint_ignore = "E501,W" -Select some error or warnings. *'g:pymode_lint_select'* +Select some error or warnings. *'g:pymode_lint_select'* By example you disable all warnings starting from 'W', but want to see warning 'W0011' and warning 'W430' > let g:pymode_lint_select = "E501,W0011,W430" -Sort errors by relevance *'g:pymode_lint_sort'* +Sort errors by relevance *'g:pymode_lint_sort'* If not empty, errors will be sort by defined relevance E.g. let g:pymode_lint_sort = ['E', 'C', 'I'] " Errors first 'E', after them 'C' and ... @@ -322,11 +328,11 @@ after them 'C' and ... let g:pymode_lint_sort = [] Auto open cwindow (quickfix) if any errors have been found - *'g:pymode_lint_cwindow'* + *'g:pymode_lint_cwindow'* > let g:pymode_lint_cwindow = 1 -Place error |signs| *'g:pymode_signs'* +Place error |signs| *'g:pymode_signs'* > let g:pymode_lint_signs = 1 @@ -339,13 +345,13 @@ Definitions for |signs| let g:pymode_lint_info_symbol = 'II' let g:pymode_lint_pyflakes_symbol = 'FF' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 3.1 Set code checkers options ~ - *pymode-lint-options* + *pymode-lint-options* Pymode has the ability to set code checkers options from pymode variables: -Set PEP8 options *'g:pymode_lint_options_pep8'* +Set PEP8 options *'g:pymode_lint_options_pep8'* > let g:pymode_lint_options_pep8 = \ {'max_line_length': g:pymode_options_max_line_length}) @@ -353,19 +359,19 @@ Set PEP8 options *'g:pymode_lint_options_pep8'* See https://pep8.readthedocs.org/en/1.4.6/intro.html#configuration for more info. -Set Pyflakes options *'g:pymode_lint_options_pyflakes'* +Set Pyflakes options *'g:pymode_lint_options_pyflakes'* > let g:pymode_lint_options_pyflakes = { 'builtins': '_' } -Set mccabe options *'g:pymode_lint_options_mccabe'* +Set mccabe options *'g:pymode_lint_options_mccabe'* > let g:pymode_lint_options_mccabe = { 'complexity': 12 } -Set pep257 options *'g:pymode_lint_options_pep257'* +Set pep257 options *'g:pymode_lint_options_pep257'* > let g:pymode_lint_options_pep257 = {} -Set pylint options *'g:pymode_lint_options_pylint'* +Set pylint options *'g:pymode_lint_options_pylint'* > let g:pymode_lint_options_pylint = \ {'max-line-length': g:pymode_options_max_line_length}) @@ -373,10 +379,9 @@ Set pylint options *'g:pymode_lint_options_pylint'* See http://docs.pylint.org/features.html#options for more info. - -============================================================================== -3. Rope support ~ - *pymode-rope* +=============================================================================== +4. Rope support ~ + *pymode-rope* Pymode supports Rope refactoring operations, code completion and code assists. @@ -390,12 +395,12 @@ Commands: |:PymodeRopeUndo| -- Undo changes from last refactoring -Turn on the rope script *'g:pymode_rope'* +Turn on the rope script *'g:pymode_rope'* > let g:pymode_rope = 1 .ropeproject Folder ~ - *.ropeproject* + *.ropeproject* *:PymodeRopeNewProject* [] -- Open new Rope project in the given path *:PymodeRopeRegenerate* -- Regenerate the project cache @@ -422,13 +427,13 @@ all its child directories, which may slow scanning down (because of many, possibly unrelated, files) Enable searching for |.ropeproject| in parent directories - *'g:pymode_rope_lookup_project'* + *'g:pymode_rope_lookup_project'* > let g:pymode_rope_lookup_project = 0 You can also manually set the rope project directory. If not specified rope will use the current directory. - *'g:pymode_rope_project_root'* + *'g:pymode_rope_project_root'* > let g:pymode_rope_project_root = "" @@ -438,15 +443,14 @@ keep it outside of your project root. The rope library treats this folder as a project resource, so the path will always be relative to your project root (a leading '/' will be ignored). You may use `'..'` path segments to place the folder outside of your project root. - *'g:pymode_rope_ropefolder'* + *'g:pymode_rope_ropefolder'* > let g:pymode_rope_ropefolder='.ropeproject' - Show documentation for element under cursor ~ -Show documentation for object under cursor. *'g:pymode_rope_show_doc_bind'* +Show documentation for object under cursor. *'g:pymode_rope_show_doc_bind'* Leave empty to disable the key binding. > let g:pymode_rope_show_doc_bind = 'd' @@ -455,9 +459,9 @@ Regenerate project cache on every save (if file has been modified) > let g:pymode_rope_regenerate_on_write = 1 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.1 Completion ~ - *pymode-completion* + *pymode-completion* By default you can use for autocompletion. The first entry will be automatically selected and you can press to insert the entry in @@ -466,25 +470,25 @@ your code. and / works too. Autocompletion is also called by typing a period in |Insert| mode by default. -Turn on code completion support in the plugin *'g:pymode_rope_completion'* +Turn on code completion support in the plugin *'g:pymode_rope_completion'* > let g:pymode_rope_completion = 1 Turn on autocompletion when typing a period - *'g:pymode_rope_complete_on_dot'* + *'g:pymode_rope_complete_on_dot'* > let g:pymode_rope_complete_on_dot = 1 -Keymap for autocomplete *'g:pymode_rope_completion_bind'* +Keymap for autocomplete *'g:pymode_rope_completion_bind'* > let g:pymode_rope_completion_bind = '' Extended autocompletion (rope could complete objects which have not been -imported) from project *'g:pymode_rope_autoimport'* +imported) from project *'g:pymode_rope_autoimport'* > let g:pymode_rope_autoimport = 0 -Load modules to autoimport by default *'g:pymode_rope_autoimport_modules'* +Load modules to autoimport by default *'g:pymode_rope_autoimport_modules'* > let g:pymode_rope_autoimport_modules = ['os', 'shutil', 'datetime'] @@ -493,24 +497,24 @@ Offer to unresolved import object after completion. let g:pymode_rope_autoimport_import_after_complete = 0 ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.2 Find definition ~ - *pymode-rope-findit* + *pymode-rope-findit* By default when you press *g* on any object in your code you will be moved to definition. -Leave empty for disable key binding. *'g:pymode_rope_goto_definition_bind'* +Leave empty for disable key binding. *'g:pymode_rope_goto_definition_bind'* > let g:pymode_rope_goto_definition_bind = 'g' Command for open window when definition has been found -Values are (`e`, `new`, `vnew`) *'g:pymode_rope_goto_definition_cmd'* +Values are (`e`, `new`, `vnew`) *'g:pymode_rope_goto_definition_cmd'* > let g:pymode_rope_goto_definition_cmd = 'new' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.3 Refactoring ~ - *pymode-rope-refactoring* + *pymode-rope-refactoring* Rename method/function/class/variable in the project ~ @@ -518,7 +522,7 @@ Pymode can rename everything: classes, functions, modules, packages, methods, variables and keyword arguments. Keymap for rename method/function/class/variables under cursor - *'g:pymode_rope_rename_bind'* + *'g:pymode_rope_rename_bind'* > let g:pymode_rope_rename_bind = 'rr' @@ -527,7 +531,7 @@ Rename a current module/package ~ *:PymodeRopeRenameModule* -- Rename current module -Keymap for rename current module *'g:pymode_rope_rename_module_bind'* +Keymap for rename current module *'g:pymode_rope_rename_module_bind'* > let g:pymode_rope_rename_module_bind = 'r1r' @@ -538,18 +542,18 @@ Imports ~ Organize imports sorts imports, too. It does that according to PEP8. Unused imports will be dropped. -Keymap *'g:pymode_rope_organize_imports_bind'* +Keymap *'g:pymode_rope_organize_imports_bind'* > let g:pymode_rope_organize_imports_bind = 'ro' -Insert import for current word under cursor *'g:pymode_rope_autoimport_bind'* +Insert import for current word under cursor *'g:pymode_rope_autoimport_bind'* Should be enabled |'g:pymode_rope_autoimport'| > let g:pymode_rope_autoimport_bind = 'ra' Convert module to package ~ - *'g:pymode_rope_module_to_package_bind'* + *'g:pymode_rope_module_to_package_bind'* *:PymodeRopeModuleToPackage* -- convert current module to package @@ -559,19 +563,19 @@ Keybinding: Extract method/variable ~ - *pymode-rope-extract* + *pymode-rope-extract* Extract method/variable from selected lines. - *'g:pymode_rope_extract_method_bind'* - *'g:pymode_rope_extract_variable_bind'* + *'g:pymode_rope_extract_method_bind'* + *'g:pymode_rope_extract_variable_bind'* > let g:pymode_rope_extract_method_bind = 'rm' let g:pymode_rope_extract_variable_bind = 'rl' Use function ~ - *pymode-rope-use* + *pymode-rope-use* It tries to find the places in which a function can be used and changes the code to call it instead. @@ -580,7 +584,7 @@ code to call it instead. Move method/fields ~ - *pymode-rope-move* + *pymode-rope-move* It happens when you perform move refactoring on a method of a class. In this refactoring, a method of a class is moved to the class of one of its @@ -595,10 +599,10 @@ Change function signature ~ let g:pymode_rope_change_signature_bind = 'rs' ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- 4.4 Undo/Redo changes ~ - *pymode-rope-undo* - *pymode-rope-redo* + *pymode-rope-undo* + *pymode-rope-redo* Commands: @@ -606,90 +610,95 @@ Commands: *:PymodeRopeRedo* -- Redo last changes in the project -============================================================================== +=============================================================================== 5. Syntax ~ - *pymode-syntax* + *pymode-syntax* -Turn on pymode syntax *'g:pymode_syntax'* +Turn on pymode syntax *'g:pymode_syntax'* > let g:pymode_syntax = 1 Slower syntax synchronization that is better at handling code blocks in docstrings. Consider disabling this on slower hardware. - *'g:pymode_syntax_slow_sync'* + *'g:pymode_syntax_slow_sync'* > let g:pymode_syntax_slow_sync = 1 -Enable all python highlights *'g:pymode_syntax_all'* +Enable all python highlights *'g:pymode_syntax_all'* > let g:pymode_syntax_all = 1 -Highlight "print" as a function *'g:pymode_syntax_print_as_function'* +Highlight "print" as a function *'g:pymode_syntax_print_as_function'* > let g:pymode_syntax_print_as_function = 0 -Highlight "async/await" keywords *'g:pymode_syntax_highlight_async_await'* +Highlight "async/await" keywords *'g:pymode_syntax_highlight_async_await'* > let g:pymode_syntax_highlight_async_await = g:pymode_syntax_all -Highlight '=' operator *'g:pymode_syntax_highlight_equal_operator'* +Highlight '=' operator *'g:pymode_syntax_highlight_equal_operator'* > let g:pymode_syntax_highlight_equal_operator = g:pymode_syntax_all -Highlight '*' operator *'g:pymode_syntax_highlight_stars_operator'* +Highlight '*' operator *'g:pymode_syntax_highlight_stars_operator'* > let g:pymode_syntax_highlight_stars_operator = g:pymode_syntax_all -Highlight 'self' keyword *'g:pymode_syntax_highlight_self'* +Highlight 'self' keyword *'g:pymode_syntax_highlight_self'* > let g:pymode_syntax_highlight_self = g:pymode_syntax_all -Highlight indent's errors *'g:pymode_syntax_indent_errors'* +Highlight indent's errors *'g:pymode_syntax_indent_errors'* > let g:pymode_syntax_indent_errors = g:pymode_syntax_all -Highlight space's errors *'g:pymode_syntax_space_errors'* +Highlight space's errors *'g:pymode_syntax_space_errors'* > let g:pymode_syntax_space_errors = g:pymode_syntax_all Highlight string formatting *'g:pymode_syntax_string_formatting'* - *'g:pymode_syntax_string_format'* - *'g:pymode_syntax_string_templates'* - *'g:pymode_syntax_doctests'* + *'g:pymode_syntax_string_format'* + *'g:pymode_syntax_string_templates'* + *'g:pymode_syntax_doctests'* > let g:pymode_syntax_string_formatting = g:pymode_syntax_all let g:pymode_syntax_string_format = g:pymode_syntax_all let g:pymode_syntax_string_templates = g:pymode_syntax_all let g:pymode_syntax_doctests = g:pymode_syntax_all -Highlight builtin objects (True, False, ...) *'g:pymode_syntax_builtin_objs'* +Highlight builtin objects (True, False, ...) *'g:pymode_syntax_builtin_objs'* > let g:pymode_syntax_builtin_objs = g:pymode_syntax_all -Highlight builtin types (str, list, ...) *'g:pymode_syntax_builtin_types'* +Highlight builtin types (str, list, ...) *'g:pymode_syntax_builtin_types'* > let g:pymode_syntax_builtin_types = g:pymode_syntax_all Highlight exceptions (TypeError, ValueError, ...) - *'g:pymode_syntax_highlight_exceptions'* + *'g:pymode_syntax_highlight_exceptions'* > let g:pymode_syntax_highlight_exceptions = g:pymode_syntax_all Highlight docstrings as pythonDocstring (otherwise as pythonString) - *'g:pymode_syntax_docstrings'* + *'g:pymode_syntax_docstrings'* > let g:pymode_syntax_docstrings = g:pymode_syntax_all -============================================================================== +=============================================================================== 6. FAQ ~ - *pymode-faq* + *pymode-faq* Python-mode doesn't work ------------------------ -Open any python file and run ":call pymode#troubleshooting#test()", -fix the warning or send me the output. +Start python mode with: +`vim -u /debugvimrc.vim` +Reproduce the error and submit your python mode debug file. You check its +location with `:messages` for something like: +`pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt` +Please submit the entire content of the file along with a reasoning of why the +plugin seems broken. Rope completion is very slow *pymode-rope-slow* @@ -715,7 +724,6 @@ You may also set |'g:pymode_rope_project_root'| to manually specify the project root path. - Pylint check is very slow ------------------------- @@ -726,7 +734,6 @@ modules if possible. Try using another code checker: see You may set |exrc| and |secure| in your |vimrc| to auto-set custom settings from `.vimrc` from your projects directories. - OSX cannot import urandom ------------------------- @@ -742,9 +749,23 @@ The sequence of commands that fixed this: brew link python < -============================================================================== -7. Credits ~ - *pymode-credits* +=============================================================================== +7. Development~ + *pymode-development* + +This section briefly defines development guidelines for python-mode. + +1. This help file uses vim's conventions defined at |help-writing|. +2. The name of the plugin shall be referred to as 'python-mode' throughout +documentation (except as a first word in a sentence in which case is +'Python-mode'). +3. All defined functions should use vim's conventions and start with 'Pymode'. +4. Special marks for project development are `XXX` and `TODO`. They provide a +easy way for developers to check pending issues. + +=============================================================================== +8. Credits ~ + *pymode-credits* Kirill Klenov http://klen.github.com/ http://github.com/klen/ @@ -778,19 +799,20 @@ The sequence of commands that fixed this: http://github.com/hynek/vim-python-pep8-indent -============================================================================== -8. License ~ - *pymode-license* +=============================================================================== +9. License ~ + *pymode-license* Python-mode is released under the GNU lesser general public license. See: http://www.gnu.org/copyleft/lesser.html -If you like this plugin, I would very appreciated if you kindly send me a postcard :) +If you like this plugin, I would very appreciated if you kindly send me a +postcard :) -My address is: "Russia, 143500, MO, Istra, pos. Severny 8-3" to "Kirill Klenov". -Thanks for your support! +My address is: "Russia, 143500, MO, Istra, pos. Severny 8-3" to "Kirill +Klenov". Thanks for your support! ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- - vim:tw=78:ts=8:ft=help:norl: + vim:tw=79:ts=8:ft=help:norl: diff --git a/ftplugin/python/pymode.vim b/ftplugin/python/pymode.vim index 79842616..11dba3c4 100644 --- a/ftplugin/python/pymode.vim +++ b/ftplugin/python/pymode.vim @@ -210,3 +210,40 @@ if g:pymode_rope endif endif + + +if g:pymode_debug + " Redefine functions to be debugged here functions here. + + " NOTE: The redraw seems to be necessary to force messages to get echoed to + " the screen. See: + " https://groups.google.com/forum/#!topic/vim_use/EfcXOjq_rKE + " for details. + " silent! redraw! + " TODO: when loading with 'vim -u ./debug.vim' the messages shown in vim + " are unduly cleared. Need a fix. + + " Start debbuging environment. {{{ + if ! &verbosefile + " Get a system independent temporary filename. The 'marker' variable is + " used to get rid of a null character getting inserted at position. + " substitute() was not able to remove it. + let g:pymode_debug_tempfile=matchstr( + \ execute( + \ g:pymode_python + \ . " import os;import tempfile; marker='|';" + \ . " print(marker, tempfile.gettempdir(), os.sep, " + \ . "'pymode_debug_file.txt', marker, sep='', end='')"), + \ '|\zs.*\ze|') + execute "set verbosefile=" . g:pymode_debug_tempfile + endif + call pymode#debug('Starting debug on: ' + \ . strftime("\%Y-\%m-\%d \%H:\%M:\%S") + \ . ' with file ' . &verbosefile) + " }}} + if g:pymode_folding + setlocal foldexpr=pymode#debug#foldingexpr(v:lnum) + endif + call pymode#debug#sysinfo() + +endif diff --git a/plugin/pymode.vim b/plugin/pymode.vim index a9b195fc..ea96ed19 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -2,7 +2,6 @@ let g:pymode_version = "0.9.4" com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version -com! PymodeTroubleshooting call pymode#troubleshooting#test() " Enable pymode by default :) call pymode#default('g:pymode', 1) diff --git a/readme.md b/readme.md index 4798a99c..8e2b450b 100644 --- a/readme.md +++ b/readme.md @@ -107,17 +107,13 @@ Then rebuild **helptags** in vim: If your python-mode doesn't work: -1. Load Vim with only python-mode enabled (use debug.vim from pymode): - - vim -u /debug.vim - - And try to repeat your case. If no error occurs, seems like problem isn't in - the plugin. - -2. Type `:PymodeTroubleshooting` and fix any warnings or copy the output and - send it to me. (For example, by creating a [new github issue]( - https://github.com/python-mode/python-mode/issues/new) if one does - not already exist for the problem). +1. **(From the FAQ)** Start python mode with: + `vim -u /debugvimrc.vim` + Reproduce the error and submit your python mode debug file. You check its + location with `:messages` for something like: + `pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt`. + Please submit the entire content of the file along with a reasoning of why + the plugin seems broken. # Frequent problems diff --git a/syntax/python.vim b/syntax/python.vim index e94877ee..89f6d929 100644 --- a/syntax/python.vim +++ b/syntax/python.vim @@ -62,7 +62,6 @@ call pymode#default('g:pymode_syntax_slow_sync', 1) " }}} - " For version 5.x: Clear all syntax items if version < 600 syntax clear @@ -125,7 +124,6 @@ endif " }}} - " Decorators {{{ " ============== @@ -135,7 +133,6 @@ endif " }}} - " Comments {{{ " ============ @@ -146,7 +143,6 @@ endif " }}} - " Errors {{{ " ========== @@ -167,7 +163,6 @@ endif " }}} - " Strings {{{ " =========== @@ -321,7 +316,6 @@ endif " }}} - if g:pymode_syntax_slow_sync syn sync minlines=2000 else From fe9c27061d6da83b58d453661bc4b0a66b444fb3 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 21:23:40 -0200 Subject: [PATCH 16/79] improved debugging function with history output --- debugvimrc.vim | 11 +++++++++++ doc/pymode.txt | 7 +++++-- ftplugin/python/pymode.vim | 10 +++++++++- readme.md | 17 +++++++++-------- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/debugvimrc.vim b/debugvimrc.vim index 750062b6..a8b3f188 100644 --- a/debugvimrc.vim +++ b/debugvimrc.vim @@ -6,6 +6,14 @@ " " Only python-mode will be loaded. +" Disable all persistence between sessions. +let skip_defaults_vim=1 +" TODO XXX: this nevertheless keeps viminfo enabled. As a workaround the flag +" '-i NONE' should be added to vim's loading. +set viminfo= +set nobackup +set noswapfile + " Modify vimrc configuration. execute('set rtp+='. expand(':p:h')) set rtp -=$HOME/.vim @@ -19,3 +27,6 @@ let g:pymode_debug = 1 if ! (has('win16') || has('win32') || has('win64')) set shell=/bin/bash endif + +" IMPORTANT: Do note that the history of this session is saved on the log file. +" See the augroup in ./ftplugin/python/pymode.vim file. diff --git a/doc/pymode.txt b/doc/pymode.txt index 4a29d6ce..8568397c 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -693,13 +693,16 @@ Python-mode doesn't work ------------------------ Start python mode with: -`vim -u /debugvimrc.vim` -Reproduce the error and submit your python mode debug file. You check its +`vim -i NONE -u /debugvimrc.vim` +Reproduce the error and submit your python mode debug file. You can check its location with `:messages` for something like: `pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt` Please submit the entire content of the file along with a reasoning of why the plugin seems broken. + *Underlined do check for sensitive information in the file before + *Underlined submitting! + Rope completion is very slow *pymode-rope-slow* ---------------------------- diff --git a/ftplugin/python/pymode.vim b/ftplugin/python/pymode.vim index 11dba3c4..2f8e661f 100644 --- a/ftplugin/python/pymode.vim +++ b/ftplugin/python/pymode.vim @@ -241,9 +241,17 @@ if g:pymode_debug \ . strftime("\%Y-\%m-\%d \%H:\%M:\%S") \ . ' with file ' . &verbosefile) " }}} + " Redefine folding expression. {{{ if g:pymode_folding setlocal foldexpr=pymode#debug#foldingexpr(v:lnum) endif call pymode#debug#sysinfo() + " }}} + " Define auto commands for vim. {{{ + augroup augroup_save_issue_commands + autocmd! + autocmd VimLeave *.py | call pymode#debug('Session history:') | silent! history + augroup END + " }}} -endif + endif diff --git a/readme.md b/readme.md index 8e2b450b..9369139e 100644 --- a/readme.md +++ b/readme.md @@ -103,17 +103,18 @@ Then rebuild **helptags** in vim: **filetype-plugin** (`:help filetype-plugin-on`) and **filetype-indent** (`:help filetype-indent-on`) must be enabled to use python-mode. -# Troubleshooting +# Troubleshooting/Debugging If your python-mode doesn't work: -1. **(From the FAQ)** Start python mode with: - `vim -u /debugvimrc.vim` - Reproduce the error and submit your python mode debug file. You check its - location with `:messages` for something like: - `pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt`. - Please submit the entire content of the file along with a reasoning of why - the plugin seems broken. +**(From the FAQ)** Start python mode with: +`vim -i NONE -u /debugvimrc.vim` +Reproduce the error and submit your python mode debug file. You can check its +location with `:messages` for something like: +`pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt`. +Please submit the entire content of the file along with a reasoning of why the +plugin seems broken. +***Do check for sensitive information in the file before submitting.*** # Frequent problems From 65c68eae06ae127741652da666425454a811b118 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 22:14:56 -0200 Subject: [PATCH 17/79] fixed breakpoint_cmd being improperly reset (gh issue 795) --- autoload/pymode/breakpoint.vim | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/autoload/pymode/breakpoint.vim b/autoload/pymode/breakpoint.vim index c3189aad..b9e09fb2 100644 --- a/autoload/pymode/breakpoint.vim +++ b/autoload/pymode/breakpoint.vim @@ -1,17 +1,11 @@ fun! pymode#breakpoint#init() "{{{ - if !g:pymode_breakpoint + " If breakpoints are either disabled or already defined do nothing. + if ! g:pymode_breakpoint || g:pymode_breakpoint_cmd != '' return - endif - - if g:pymode_breakpoint_cmd == '' - let g:pymode_breakpoint_cmd = 'import pdb; pdb.set_trace() # XXX BREAKPOINT' - - if g:pymode_python == 'disable' - return - endif - endif + " Else go for a 'smart scan' of the defaults. + else PymodePython << EOF @@ -26,6 +20,7 @@ for module in ('wdb', 'pudb', 'ipdb'): continue EOF + endif endfunction "}}} From 76c582b9df2c3895cc34ef7b238ff0ddfabeea1e Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 22:34:04 -0200 Subject: [PATCH 18/79] enforced list data type for pymode_lint_ignore (gh issue 786) --- doc/pymode.txt | 5 ++--- pymode/lint.py | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/pymode.txt b/doc/pymode.txt index 8568397c..ac3a0fa9 100644 --- a/doc/pymode.txt +++ b/doc/pymode.txt @@ -309,10 +309,9 @@ Default code checkers (you could set several) *'g:pymode_lint_checkers' Values may be chosen from: `pylint`, `pep8`, `mccabe`, `pep257`, `pyflakes`. Skip errors and warnings *'g:pymode_lint_ignore'* -E.g. "E501,W002", "E2,W" (Skip all Warnings and Errors that starts with E2) and -etc +E.g. ["W", "E2"] (Skip all Warnings and the Errors starting with E2) etc. > - let g:pymode_lint_ignore = "E501,W" + let g:pymode_lint_ignore = ["E501", "W",] Select some error or warnings. *'g:pymode_lint_select'* By example you disable all warnings starting from 'W', but want to see warning diff --git a/pymode/lint.py b/pymode/lint.py index 25f2414c..01b0b527 100644 --- a/pymode/lint.py +++ b/pymode/lint.py @@ -35,10 +35,12 @@ def code_check(): # Fixed in v0.9.3: these two parameters may be passed as strings. # DEPRECATE: v:0.10.0: need to be set as lists. if isinstance(env.var('g:pymode_lint_ignore'), str): + raise ValueError ('g:pymode_lint_ignore should have a list type') ignore = env.var('g:pymode_lint_ignore').split(',') else: ignore = env.var('g:pymode_lint_ignore') if isinstance(env.var('g:pymode_lint_select'), str): + raise ValueError ('g:pymode_lint_ignore should have a list type') select = env.var('g:pymode_lint_select').split(',') else: select = env.var('g:pymode_lint_select') From c7e6baa189d6da94941276cdcf84d1b83f7a2406 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 23:03:01 -0200 Subject: [PATCH 19/79] fixed folding issue when definition was on first line (gh issue 808) --- autoload/pymode/folding.vim | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index ca98b5c9..12825da5 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -1,4 +1,4 @@ -" Python-mode folding functions +k" Python-mode folding function2 " Notice that folding is based on single line so complex regular expressions " that take previous line into consideration are not fit for the job. @@ -156,10 +156,14 @@ fun! s:BlockStart(line_number) "{{{ " In case the end of the block is indented to a higher level than the def " statement plus one shiftwidth, we need to find the indent level at the " bottom of that if/for/try/while/etc. block. - let previous_definition = searchpos(s:def_regex, 'bcnW') + " Flags from searchpos() (same as search()): + " b: search Backward instead of forward + " n: do Not move the cursor + " W: don't Wrap around the end of the file + let previous_definition = searchpos(s:def_regex, 'bnW') if previous_definition != [0, 0] while previous_definition != [0, 0] && indent(previous_definition[0]) >= indent(a:line_number) - let previous_definition = searchpos(s:def_regex, 'bncW') + let previous_definition = searchpos(s:def_regex, 'bnW') call cursor(previous_definition[0] - 1, 0) endwhile endif From 7d376f1d57bbc5be11b61bd6cefb5f6def616350 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 23:21:27 -0200 Subject: [PATCH 20/79] adapted readme.md to development guidelines --- readme.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 9369139e..9905c8a4 100644 --- a/readme.md +++ b/readme.md @@ -114,6 +114,7 @@ location with `:messages` for something like: `pymode debug msg 1: Starting debug on: 2017-11-18 16:44:13 with file /tmp/pymode_debug_file.txt`. Please submit the entire content of the file along with a reasoning of why the plugin seems broken. + ***Do check for sensitive information in the file before submitting.*** # Frequent problems @@ -141,8 +142,11 @@ the issue tracker at: # Contributing -* Kirill Klenov () -* Felipe Vieira () +The contributing guidelines for this plugin are outlined at +`:help pymode-development`. + +* Author: Kirill Klenov () +* Maintainer: Felipe Vieira () Also see the AUTHORS file. From 97351299bbd66393a28f33d2dd21549a6ac01786 Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sat, 18 Nov 2017 23:42:02 -0200 Subject: [PATCH 21/79] removed travis test as they were abandoned long ago; the testing issue still persists --- .ruby-gemset | 1 - .ruby-version | 1 - .travis.yml | 8 +- Gemfile | 3 - Makefile | 98 ----------------- Rakefile | 11 -- python-mode.yaml | 268 ----------------------------------------------- 7 files changed, 2 insertions(+), 388 deletions(-) delete mode 100644 .ruby-gemset delete mode 100644 .ruby-version delete mode 100644 Gemfile delete mode 100644 Makefile delete mode 100644 Rakefile delete mode 100644 python-mode.yaml diff --git a/.ruby-gemset b/.ruby-gemset deleted file mode 100644 index 5ded393e..00000000 --- a/.ruby-gemset +++ /dev/null @@ -1 +0,0 @@ -vim-flavor diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 67b8bc0d..00000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -ruby-1.9.3 diff --git a/.travis.yml b/.travis.yml index e10ed9f1..af733524 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,2 @@ -language: ruby -python: "2.7" -rvm: - - 1.9.3 -script: - - make travis +# Deactivated. +# This plugin needs a robust test suite. diff --git a/Gemfile b/Gemfile deleted file mode 100644 index a87f4e1a..00000000 --- a/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' - -gem 'vim-flavor', '~> 1.1' diff --git a/Makefile b/Makefile deleted file mode 100644 index 5e5a0990..00000000 --- a/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -PYMODE = $(CURDIR)/pymode -LIBS = $(PYMODE)/libs -PYLAMA = $(LIBS)/pylama - -.PHONY: clean -clean: - find $(CURDIR) -name "*.pyc" -delete - rm -rf $(CURDIR)/build - rm -rf *.deb - -VERSION?=minor -# target: release - Bump version -release: - git fetch origin - git checkout master - git rebase - git merge develop - bumpversion $(VERSION) - git checkout develop - git rebase - git merge master - git push origin develop master - git push --tags - -.PHONY: minor -minor: release - -.PHONY: patch -patch: - make release VERSION=patch - -.PHONY: major -major: - make release VERSION=major - -# Temporary disable rope tests on Travis -.PHONY: travis -travis: - rake test - -.PHONY: test t -test: - bundle install - rm -rf $(CURDIR)/.ropeproject - rake test -t: test - -.PHONY: pylama -pylama: - rm -rf $(PYLAMA) - make $(PYLAMA) - make $(PYLAMA)/lint/pylama_pylint - @pip install --upgrade --force-reinstall --target=$(LIBS) pydocstyle - @pip install --upgrade --force-reinstall --target=$(LIBS) pycodestyle - @pip install --upgrade --force-reinstall --target=$(LIBS) pyflakes - @pip install --upgrade --force-reinstall --target=$(LIBS) mccabe - @pip install --upgrade --force-reinstall --target=$(LIBS) pylint - @find $(LIBS) -name *.dist-info -type d | xargs rm -rf - @find $(LIBS) -name *.egg-info -type d | xargs rm -rf - @find $(LIBS) -name test* -type d | xargs rm -rf - -.PHONY: rope -rope: - @git clone https://github.com/python-rope/rope.git $(CURDIR)/_/rope - @rm -rf $(CURDIR)/pymode/libs/rope - @cp -r $(CURDIR)/_/rope/rope $(CURDIR)/pymode/libs/. - -$(PYLAMA): - cp -r $$PRJDIR/pylama/pylama $(PYLAMA) - -$(PYLAMA)/lint/pylama_pylint: - cp -r $$PRJDIR/pylama/plugins/pylama_pylint/pylama_pylint/ $(PYLAMA)/lint/pylama_pylint - -$(CURDIR)/build: - mkdir -p $(CURDIR)/build/usr/share/vim/addons - mkdir -p $(CURDIR)/build/usr/share/vim/registry - cp -r after autoload doc ftplugin plugin pymode syntax $(CURDIR)/build/usr/share/vim/addons/. - cp -r python-mode.yaml $(CURDIR)/build/usr/share/vim/registry/. - -PACKAGE_VERSION?=$(shell git describe --tags `git rev-list master --tags --max-count=1`) -PACKAGE_NAME="vim-python-mode" -PACKAGE_MAINTAINER="Kirill Klenov " -PACKAGE_URL=http://github.com/klen/python-mode -deb: clean $(CURDIR)/build - @fpm -s dir -t deb -a all \ - -n $(PACKAGE_NAME) \ - -v $(PACKAGE_VERSION) \ - -m $(PACKAGE_MAINTAINER) \ - --url $(PACKAGE_URL) \ - --license "GNU lesser general public license" \ - --description "Vim-Swissknife for python" \ - --deb-user root \ - --deb-group root \ - -C $(CURDIR)/build \ - -d "python2.7" \ - -d "vim-addon-manager" \ - usr - @mv *.deb ~/Dropbox/projects/deb/load diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 63a3a361..00000000 --- a/Rakefile +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env rake - -task :ci => [:dump, :test] - -task :dump do - sh 'vim --version' -end - -task :test do - sh 'bundle exec vim-flavor test' -end diff --git a/python-mode.yaml b/python-mode.yaml deleted file mode 100644 index b5635e68..00000000 --- a/python-mode.yaml +++ /dev/null @@ -1,268 +0,0 @@ -addon: python-mode -description: "swissknife for python" -files: - - after/ftplugin/pyrex.vim - - after/ftplugin/python.vim - - after/indent/pyrex.vim - - after/indent/python.vim - - autoload/pymode/breakpoint.vim - - autoload/pymode/doc.vim - - autoload/pymode/folding.vim - - autoload/pymode/indent.vim - - autoload/pymode/lint.vim - - autoload/pymode/motion.vim - - autoload/pymode/rope.vim - - autoload/pymode/run.vim - - autoload/pymode/tools/loclist.vim - - autoload/pymode/tools/signs.vim - - autoload/pymode/troubleshooting.vim - - autoload/pymode/virtualenv.vim - - autoload/pymode.vim - - ftplugin/pyrex.vim - - ftplugin/python/pymode.vim - - plugin/pymode.vim - - syntax/pyrex.vim - - syntax/python.vim - - pymode/__init__.py - - pymode/async.py - - pymode/autopep8.py - - pymode/environment.py - - pymode/libs/pylama/__init__.py - - pymode/libs/pylama/config.py - - pymode/libs/pylama/core.py - - pymode/libs/pylama/hook.py - - pymode/libs/pylama/libs/__init__.py - - pymode/libs/pylama/libs/importlib.py - - pymode/libs/pylama/libs/inirama.py - - pymode/libs/pylama/lint/__init__.py - - pymode/libs/pylama/lint/extensions.py - - pymode/libs/pylama/lint/pylama_mccabe/__init__.py - - pymode/libs/pylama/lint/pylama_mccabe/mccabe.py - - pymode/libs/pylama/lint/pylama_pep257/__init__.py - - pymode/libs/pylama/lint/pylama_pep257/pep257.py - - pymode/libs/pylama/lint/pylama_pep8/__init__.py - - pymode/libs/pylama/lint/pylama_pep8/pep8.py - - pymode/libs/pylama/lint/pylama_pyflakes/__init__.py - - pymode/libs/pylama/lint/pylama_pyflakes/pyflakes/__init__.py - - pymode/libs/pylama/lint/pylama_pyflakes/pyflakes/checker.py - - pymode/libs/pylama/lint/pylama_pyflakes/pyflakes/messages.py - - pymode/libs/pylama/lint/pylama_pylint/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/main.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/__pkginfo__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/__pkginfo__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/as_string.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/bases.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/builder.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/exceptions.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/inference.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/manager.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/mixins.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/node_classes.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/nodes.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/protocols.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/raw_building.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/rebuilder.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/scoped_nodes.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/astroid/utils.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/base.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/classes.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/design_analysis.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/exceptions.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/format.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/imports.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/logging.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/misc.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/newstyle.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/raw_metrics.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/similar.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/stdlib.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/strings.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/typecheck.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/utils.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/checkers/variables.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/config.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/interfaces.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/lint.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/__pkginfo__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/changelog.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/compat.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/configuration.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/decorators.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/deprecation.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/graph.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/interface.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/modutils.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/optik_ext.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/textutils.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/tree.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/ureports/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/ureports/docbook_writer.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/ureports/html_writer.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/ureports/nodes.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/ureports/text_writer.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/logilab/common/visitor.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/reporters/__init__.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/reporters/guireporter.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/reporters/html.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/reporters/text.py - - pymode/libs/pylama/lint/pylama_pylint/pylint/utils.py - - pymode/libs/pylama/main.py - - pymode/libs/pylama/tasks.py - - pymode/libs/pylama/utils.py - - pymode/libs2/rope/__init__.py - - pymode/libs2/rope/base/__init__.py - - pymode/libs2/rope/base/arguments.py - - pymode/libs2/rope/base/ast.py - - pymode/libs2/rope/base/astutils.py - - pymode/libs2/rope/base/builtins.py - - pymode/libs2/rope/base/change.py - - pymode/libs2/rope/base/codeanalyze.py - - pymode/libs2/rope/base/default_config.py - - pymode/libs2/rope/base/evaluate.py - - pymode/libs2/rope/base/exceptions.py - - pymode/libs2/rope/base/fscommands.py - - pymode/libs2/rope/base/history.py - - pymode/libs2/rope/base/libutils.py - - pymode/libs2/rope/base/oi/__init__.py - - pymode/libs2/rope/base/oi/doa.py - - pymode/libs2/rope/base/oi/memorydb.py - - pymode/libs2/rope/base/oi/objectdb.py - - pymode/libs2/rope/base/oi/objectinfo.py - - pymode/libs2/rope/base/oi/runmod.py - - pymode/libs2/rope/base/oi/soa.py - - pymode/libs2/rope/base/oi/soi.py - - pymode/libs2/rope/base/oi/transform.py - - pymode/libs2/rope/base/prefs.py - - pymode/libs2/rope/base/project.py - - pymode/libs2/rope/base/pycore.py - - pymode/libs2/rope/base/pynames.py - - pymode/libs2/rope/base/pynamesdef.py - - pymode/libs2/rope/base/pyobjects.py - - pymode/libs2/rope/base/pyobjectsdef.py - - pymode/libs2/rope/base/pyscopes.py - - pymode/libs2/rope/base/resourceobserver.py - - pymode/libs2/rope/base/resources.py - - pymode/libs2/rope/base/simplify.py - - pymode/libs2/rope/base/stdmods.py - - pymode/libs2/rope/base/taskhandle.py - - pymode/libs2/rope/base/utils.py - - pymode/libs2/rope/base/worder.py - - pymode/libs2/rope/contrib/__init__.py - - pymode/libs2/rope/contrib/autoimport.py - - pymode/libs2/rope/contrib/changestack.py - - pymode/libs2/rope/contrib/codeassist.py - - pymode/libs2/rope/contrib/finderrors.py - - pymode/libs2/rope/contrib/findit.py - - pymode/libs2/rope/contrib/fixmodnames.py - - pymode/libs2/rope/contrib/fixsyntax.py - - pymode/libs2/rope/contrib/generate.py - - pymode/libs2/rope/refactor/__init__.py - - pymode/libs2/rope/refactor/change_signature.py - - pymode/libs2/rope/refactor/encapsulate_field.py - - pymode/libs2/rope/refactor/extract.py - - pymode/libs2/rope/refactor/functionutils.py - - pymode/libs2/rope/refactor/importutils/__init__.py - - pymode/libs2/rope/refactor/importutils/actions.py - - pymode/libs2/rope/refactor/importutils/importinfo.py - - pymode/libs2/rope/refactor/importutils/module_imports.py - - pymode/libs2/rope/refactor/inline.py - - pymode/libs2/rope/refactor/introduce_factory.py - - pymode/libs2/rope/refactor/introduce_parameter.py - - pymode/libs2/rope/refactor/localtofield.py - - pymode/libs2/rope/refactor/method_object.py - - pymode/libs2/rope/refactor/move.py - - pymode/libs2/rope/refactor/multiproject.py - - pymode/libs2/rope/refactor/occurrences.py - - pymode/libs2/rope/refactor/patchedast.py - - pymode/libs2/rope/refactor/rename.py - - pymode/libs2/rope/refactor/restructure.py - - pymode/libs2/rope/refactor/similarfinder.py - - pymode/libs2/rope/refactor/sourceutils.py - - pymode/libs2/rope/refactor/suites.py - - pymode/libs2/rope/refactor/topackage.py - - pymode/libs2/rope/refactor/usefunction.py - - pymode/libs2/rope/refactor/wildcards.py - - pymode/libs3/rope/__init__.py - - pymode/libs3/rope/base/__init__.py - - pymode/libs3/rope/base/arguments.py - - pymode/libs3/rope/base/ast.py - - pymode/libs3/rope/base/astutils.py - - pymode/libs3/rope/base/builtins.py - - pymode/libs3/rope/base/change.py - - pymode/libs3/rope/base/codeanalyze.py - - pymode/libs3/rope/base/default_config.py - - pymode/libs3/rope/base/evaluate.py - - pymode/libs3/rope/base/exceptions.py - - pymode/libs3/rope/base/fscommands.py - - pymode/libs3/rope/base/history.py - - pymode/libs3/rope/base/libutils.py - - pymode/libs3/rope/base/oi/__init__.py - - pymode/libs3/rope/base/oi/doa.py - - pymode/libs3/rope/base/oi/memorydb.py - - pymode/libs3/rope/base/oi/objectdb.py - - pymode/libs3/rope/base/oi/objectinfo.py - - pymode/libs3/rope/base/oi/runmod.py - - pymode/libs3/rope/base/oi/soa.py - - pymode/libs3/rope/base/oi/soi.py - - pymode/libs3/rope/base/oi/transform.py - - pymode/libs3/rope/base/prefs.py - - pymode/libs3/rope/base/project.py - - pymode/libs3/rope/base/pycore.py - - pymode/libs3/rope/base/pynames.py - - pymode/libs3/rope/base/pynamesdef.py - - pymode/libs3/rope/base/pyobjects.py - - pymode/libs3/rope/base/pyobjectsdef.py - - pymode/libs3/rope/base/pyscopes.py - - pymode/libs3/rope/base/resourceobserver.py - - pymode/libs3/rope/base/resources.py - - pymode/libs3/rope/base/simplify.py - - pymode/libs3/rope/base/stdmods.py - - pymode/libs3/rope/base/taskhandle.py - - pymode/libs3/rope/base/utils.py - - pymode/libs3/rope/base/worder.py - - pymode/libs3/rope/contrib/__init__.py - - pymode/libs3/rope/contrib/autoimport.py - - pymode/libs3/rope/contrib/changestack.py - - pymode/libs3/rope/contrib/codeassist.py - - pymode/libs3/rope/contrib/finderrors.py - - pymode/libs3/rope/contrib/findit.py - - pymode/libs3/rope/contrib/fixmodnames.py - - pymode/libs3/rope/contrib/fixsyntax.py - - pymode/libs3/rope/contrib/generate.py - - pymode/libs3/rope/refactor/__init__.py - - pymode/libs3/rope/refactor/change_signature.py - - pymode/libs3/rope/refactor/encapsulate_field.py - - pymode/libs3/rope/refactor/extract.py - - pymode/libs3/rope/refactor/functionutils.py - - pymode/libs3/rope/refactor/importutils/__init__.py - - pymode/libs3/rope/refactor/importutils/actions.py - - pymode/libs3/rope/refactor/importutils/importinfo.py - - pymode/libs3/rope/refactor/importutils/module_imports.py - - pymode/libs3/rope/refactor/inline.py - - pymode/libs3/rope/refactor/introduce_factory.py - - pymode/libs3/rope/refactor/introduce_parameter.py - - pymode/libs3/rope/refactor/localtofield.py - - pymode/libs3/rope/refactor/method_object.py - - pymode/libs3/rope/refactor/move.py - - pymode/libs3/rope/refactor/multiproject.py - - pymode/libs3/rope/refactor/occurrences.py - - pymode/libs3/rope/refactor/patchedast.py - - pymode/libs3/rope/refactor/rename.py - - pymode/libs3/rope/refactor/restructure.py - - pymode/libs3/rope/refactor/similarfinder.py - - pymode/libs3/rope/refactor/sourceutils.py - - pymode/libs3/rope/refactor/suites.py - - pymode/libs3/rope/refactor/topackage.py - - pymode/libs3/rope/refactor/usefunction.py - - pymode/libs3/rope/refactor/wildcards.py - - pymode/lint.py - - pymode/rope.py - - pymode/run.py - - pymode/utils.py - - pymode/virtualenv.py - - pymode/libs/pylama/lint/pylama_pylint/pylint.rc From c224a04237c4ebfc986d4166ed46bf48971cce1d Mon Sep 17 00:00:00 2001 From: "Felipe M. Vieira" Date: Sun, 19 Nov 2017 00:46:33 -0200 Subject: [PATCH 22/79] changed modules from pymode/libs to submodules --- .gitmodules | 28 + pymode/autopep8.py | 3886 +---------------- pymode/libs/_markerlib/__init__.py | 16 + pymode/libs/_markerlib/markers.py | 119 + ...ts.functools_lru_cache-1.3-py3.5-nspkg.pth | 1 - .../libs/backports/configparser/__init__.py | 1390 ------ pymode/libs/backports/configparser/helpers.py | 171 - pymode/libs/backports/functools_lru_cache.py | 184 - .../libs/configparser-3.5.0-py2.7-nspkg.pth | 1 - pymode/libs/configparser.py | 52 - pymode/libs/easy_install.py | 5 + pymode/libs/isort/__init__.py | 28 - pymode/libs/isort/__main__.py | 3 - pymode/libs/isort/hooks.py | 82 - pymode/libs/isort/isort.py | 969 ---- pymode/libs/isort/main.py | 296 -- pymode/libs/isort/natural.py | 47 - pymode/libs/isort/pie_slice.py | 594 --- pymode/libs/isort/pylama_isort.py | 29 - pymode/libs/isort/settings.py | 256 -- pymode/libs/lazy_object_proxy/__init__.py | 20 - pymode/libs/lazy_object_proxy/cext.c | 1421 ------ pymode/libs/lazy_object_proxy/compat.py | 9 - pymode/libs/lazy_object_proxy/simple.py | 246 -- pymode/libs/lazy_object_proxy/slots.py | 414 -- pymode/libs/lazy_object_proxy/utils.py | 13 - pymode/libs/logilab/__init__.py | 1 + pymode/libs/logilab/common/__init__.py | 184 + pymode/libs/logilab/common/cache.py | 114 + pymode/libs/logilab/common/changelog.py | 238 + pymode/libs/logilab/common/clcommands.py | 334 ++ pymode/libs/logilab/common/compat.py | 78 + pymode/libs/logilab/common/configuration.py | 1105 +++++ pymode/libs/logilab/common/daemon.py | 101 + pymode/libs/logilab/common/date.py | 335 ++ pymode/libs/logilab/common/debugger.py | 214 + pymode/libs/logilab/common/decorators.py | 281 ++ pymode/libs/logilab/common/deprecation.py | 189 + pymode/libs/logilab/common/fileutils.py | 404 ++ pymode/libs/logilab/common/graph.py | 282 ++ pymode/libs/logilab/common/interface.py | 71 + pymode/libs/logilab/common/logging_ext.py | 195 + pymode/libs/logilab/common/modutils.py | 713 +++ pymode/libs/logilab/common/optik_ext.py | 392 ++ pymode/libs/logilab/common/optparser.py | 92 + pymode/libs/logilab/common/proc.py | 277 ++ pymode/libs/logilab/common/pytest.py | 1202 +++++ pymode/libs/logilab/common/registry.py | 1125 +++++ pymode/libs/logilab/common/shellutils.py | 462 ++ pymode/libs/logilab/common/sphinx_ext.py | 87 + pymode/libs/logilab/common/sphinxutils.py | 122 + pymode/libs/logilab/common/table.py | 929 ++++ pymode/libs/logilab/common/tasksqueue.py | 101 + pymode/libs/logilab/common/testlib.py | 1338 ++++++ pymode/libs/logilab/common/textutils.py | 537 +++ pymode/libs/logilab/common/tree.py | 369 ++ pymode/libs/logilab/common/umessage.py | 194 + .../libs/logilab/common/ureports/__init__.py | 172 + .../logilab/common/ureports/docbook_writer.py | 140 + .../logilab/common/ureports/html_writer.py | 133 + pymode/libs/logilab/common/ureports/nodes.py | 203 + .../logilab/common/ureports/text_writer.py | 145 + pymode/libs/logilab/common/urllib2ext.py | 89 + pymode/libs/logilab/common/vcgutils.py | 216 + pymode/libs/logilab/common/visitor.py | 109 + pymode/libs/logilab/common/xmlutils.py | 61 + .../libs/logilab_common-1.0.2-py2.7-nspkg.pth | 1 + .../DESCRIPTION.rst | 153 + .../logilab_common-1.0.2.dist-info/METADATA | 169 + .../logilab_common-1.0.2.dist-info/RECORD | 87 + .../libs/logilab_common-1.0.2.dist-info/WHEEL | 5 + .../metadata.json | 1 + .../namespace_packages.txt | 1 + .../top_level.txt | 1 + pymode/libs/mccabe.py | 348 +- pymode/libs/pkg_resources/__init__.py | 3113 +++++++++++++ .../_vendor}/__init__.py | 0 .../_vendor/packaging/__about__.py | 31 + .../_vendor/packaging/__init__.py | 24 + .../_vendor/packaging/_compat.py | 40 + .../_vendor/packaging/_structures.py | 78 + .../_vendor/packaging/specifiers.py | 784 ++++ .../_vendor/packaging/version.py | 403 ++ pymode/libs/pycodestyle.py | 2328 +--------- pymode/libs/pydocstyle | 1 + pymode/libs/pydocstyle/__init__.py | 7 - pymode/libs/pydocstyle/__main__.py | 19 - pymode/libs/pydocstyle/checker.py | 711 --- pymode/libs/pydocstyle/cli.py | 94 - pymode/libs/pydocstyle/config.py | 614 --- pymode/libs/pydocstyle/data/imperatives.txt | 232 - .../pydocstyle/data/imperatives_blacklist.txt | 100 - pymode/libs/pydocstyle/parser.py | 594 --- pymode/libs/pydocstyle/utils.py | 27 - pymode/libs/pydocstyle/violations.py | 246 -- pymode/libs/pydocstyle/wordlists.py | 39 - pymode/libs/pyflakes | 1 + pymode/libs/pyflakes/__init__.py | 1 - pymode/libs/pyflakes/__main__.py | 5 - pymode/libs/pyflakes/api.py | 187 - pymode/libs/pyflakes/checker.py | 1355 ------ pymode/libs/pyflakes/messages.py | 233 - pymode/libs/pyflakes/reporter.py | 81 - pymode/libs/pyflakes/scripts/pyflakes.py | 8 - pymode/libs/pylama | 1 + pymode/libs/pylama/__init__.py | 10 - pymode/libs/pylama/__main__.py | 6 - pymode/libs/pylama/async.py | 75 - pymode/libs/pylama/config.py | 265 -- pymode/libs/pylama/core.py | 207 - pymode/libs/pylama/errors.py | 113 - pymode/libs/pylama/hook.py | 110 - pymode/libs/pylama/libs/__init__.py | 1 - pymode/libs/pylama/libs/importlib.py | 38 - pymode/libs/pylama/libs/inirama.py | 405 -- pymode/libs/pylama/lint/__init__.py | 19 - pymode/libs/pylama/lint/extensions.py | 47 - pymode/libs/pylama/lint/pylama_mccabe.py | 26 - pymode/libs/pylama/lint/pylama_pycodestyle.py | 66 - pymode/libs/pylama/lint/pylama_pydocstyle.py | 33 - pymode/libs/pylama/lint/pylama_pyflakes.py | 51 - .../pylama/lint/pylama_pylint/__init__.py | 12 - pymode/libs/pylama/lint/pylama_pylint/main.py | 110 - .../libs/pylama/lint/pylama_pylint/pylint.rc | 23 - pymode/libs/pylama/lint/pylama_radon.py | 31 - pymode/libs/pylama/main.py | 105 - pymode/libs/pylama/pytest.py | 87 - pymode/libs/six.py | 74 +- pymode/libs/snowballstemmer | 1 + pymode/libs/snowballstemmer/__init__.py | 57 - pymode/libs/snowballstemmer/among.py | 15 - pymode/libs/snowballstemmer/basestemmer.py | 351 -- pymode/libs/snowballstemmer/danish_stemmer.py | 364 -- pymode/libs/snowballstemmer/dutch_stemmer.py | 699 --- .../libs/snowballstemmer/english_stemmer.py | 1115 ----- .../libs/snowballstemmer/finnish_stemmer.py | 853 ---- pymode/libs/snowballstemmer/french_stemmer.py | 1307 ------ pymode/libs/snowballstemmer/german_stemmer.py | 619 --- .../libs/snowballstemmer/hungarian_stemmer.py | 1061 ----- .../libs/snowballstemmer/italian_stemmer.py | 1033 ----- .../libs/snowballstemmer/norwegian_stemmer.py | 308 -- pymode/libs/snowballstemmer/porter_stemmer.py | 789 ---- .../snowballstemmer/portuguese_stemmer.py | 965 ---- .../libs/snowballstemmer/romanian_stemmer.py | 900 ---- .../libs/snowballstemmer/russian_stemmer.py | 636 --- .../libs/snowballstemmer/spanish_stemmer.py | 1032 ----- .../libs/snowballstemmer/swedish_stemmer.py | 304 -- .../libs/snowballstemmer/turkish_stemmer.py | 2601 ----------- pymode/libs/wrapt/__init__.py | 19 - pymode/libs/wrapt/arguments.py | 96 - pymode/libs/wrapt/decorators.py | 512 --- pymode/libs/wrapt/importer.py | 228 - pymode/libs/wrapt/wrappers.py | 899 ---- submodules/autopep8 | 1 + submodules/mccabe | 1 + submodules/pycodestyle | 1 + submodules/pydocstyle | 1 + submodules/pyflakes | 1 + submodules/pylama | 1 + submodules/snowball_py | 1 + 160 files changed, 18429 insertions(+), 35993 deletions(-) create mode 100644 .gitmodules mode change 100644 => 120000 pymode/autopep8.py create mode 100644 pymode/libs/_markerlib/__init__.py create mode 100644 pymode/libs/_markerlib/markers.py delete mode 100644 pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth delete mode 100644 pymode/libs/backports/configparser/__init__.py delete mode 100644 pymode/libs/backports/configparser/helpers.py delete mode 100644 pymode/libs/backports/functools_lru_cache.py delete mode 100644 pymode/libs/configparser-3.5.0-py2.7-nspkg.pth delete mode 100644 pymode/libs/configparser.py create mode 100644 pymode/libs/easy_install.py delete mode 100644 pymode/libs/isort/__init__.py delete mode 100644 pymode/libs/isort/__main__.py delete mode 100644 pymode/libs/isort/hooks.py delete mode 100644 pymode/libs/isort/isort.py delete mode 100644 pymode/libs/isort/main.py delete mode 100644 pymode/libs/isort/natural.py delete mode 100644 pymode/libs/isort/pie_slice.py delete mode 100644 pymode/libs/isort/pylama_isort.py delete mode 100644 pymode/libs/isort/settings.py delete mode 100644 pymode/libs/lazy_object_proxy/__init__.py delete mode 100644 pymode/libs/lazy_object_proxy/cext.c delete mode 100644 pymode/libs/lazy_object_proxy/compat.py delete mode 100644 pymode/libs/lazy_object_proxy/simple.py delete mode 100644 pymode/libs/lazy_object_proxy/slots.py delete mode 100644 pymode/libs/lazy_object_proxy/utils.py create mode 100644 pymode/libs/logilab/__init__.py create mode 100644 pymode/libs/logilab/common/__init__.py create mode 100644 pymode/libs/logilab/common/cache.py create mode 100644 pymode/libs/logilab/common/changelog.py create mode 100644 pymode/libs/logilab/common/clcommands.py create mode 100644 pymode/libs/logilab/common/compat.py create mode 100644 pymode/libs/logilab/common/configuration.py create mode 100644 pymode/libs/logilab/common/daemon.py create mode 100644 pymode/libs/logilab/common/date.py create mode 100644 pymode/libs/logilab/common/debugger.py create mode 100644 pymode/libs/logilab/common/decorators.py create mode 100644 pymode/libs/logilab/common/deprecation.py create mode 100644 pymode/libs/logilab/common/fileutils.py create mode 100644 pymode/libs/logilab/common/graph.py create mode 100644 pymode/libs/logilab/common/interface.py create mode 100644 pymode/libs/logilab/common/logging_ext.py create mode 100644 pymode/libs/logilab/common/modutils.py create mode 100644 pymode/libs/logilab/common/optik_ext.py create mode 100644 pymode/libs/logilab/common/optparser.py create mode 100644 pymode/libs/logilab/common/proc.py create mode 100644 pymode/libs/logilab/common/pytest.py create mode 100644 pymode/libs/logilab/common/registry.py create mode 100644 pymode/libs/logilab/common/shellutils.py create mode 100644 pymode/libs/logilab/common/sphinx_ext.py create mode 100644 pymode/libs/logilab/common/sphinxutils.py create mode 100644 pymode/libs/logilab/common/table.py create mode 100644 pymode/libs/logilab/common/tasksqueue.py create mode 100644 pymode/libs/logilab/common/testlib.py create mode 100644 pymode/libs/logilab/common/textutils.py create mode 100644 pymode/libs/logilab/common/tree.py create mode 100644 pymode/libs/logilab/common/umessage.py create mode 100644 pymode/libs/logilab/common/ureports/__init__.py create mode 100644 pymode/libs/logilab/common/ureports/docbook_writer.py create mode 100644 pymode/libs/logilab/common/ureports/html_writer.py create mode 100644 pymode/libs/logilab/common/ureports/nodes.py create mode 100644 pymode/libs/logilab/common/ureports/text_writer.py create mode 100644 pymode/libs/logilab/common/urllib2ext.py create mode 100644 pymode/libs/logilab/common/vcgutils.py create mode 100644 pymode/libs/logilab/common/visitor.py create mode 100644 pymode/libs/logilab/common/xmlutils.py create mode 100644 pymode/libs/logilab_common-1.0.2-py2.7-nspkg.pth create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/DESCRIPTION.rst create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/METADATA create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/RECORD create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/WHEEL create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/metadata.json create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/namespace_packages.txt create mode 100644 pymode/libs/logilab_common-1.0.2.dist-info/top_level.txt mode change 100644 => 120000 pymode/libs/mccabe.py create mode 100644 pymode/libs/pkg_resources/__init__.py rename pymode/libs/{pyflakes/scripts => pkg_resources/_vendor}/__init__.py (100%) create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/__about__.py create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/__init__.py create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/_compat.py create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/_structures.py create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 pymode/libs/pkg_resources/_vendor/packaging/version.py mode change 100644 => 120000 pymode/libs/pycodestyle.py create mode 120000 pymode/libs/pydocstyle delete mode 100644 pymode/libs/pydocstyle/__init__.py delete mode 100644 pymode/libs/pydocstyle/__main__.py delete mode 100644 pymode/libs/pydocstyle/checker.py delete mode 100644 pymode/libs/pydocstyle/cli.py delete mode 100644 pymode/libs/pydocstyle/config.py delete mode 100644 pymode/libs/pydocstyle/data/imperatives.txt delete mode 100644 pymode/libs/pydocstyle/data/imperatives_blacklist.txt delete mode 100644 pymode/libs/pydocstyle/parser.py delete mode 100644 pymode/libs/pydocstyle/utils.py delete mode 100644 pymode/libs/pydocstyle/violations.py delete mode 100644 pymode/libs/pydocstyle/wordlists.py create mode 120000 pymode/libs/pyflakes delete mode 100644 pymode/libs/pyflakes/__init__.py delete mode 100644 pymode/libs/pyflakes/__main__.py delete mode 100644 pymode/libs/pyflakes/api.py delete mode 100644 pymode/libs/pyflakes/checker.py delete mode 100644 pymode/libs/pyflakes/messages.py delete mode 100644 pymode/libs/pyflakes/reporter.py delete mode 100644 pymode/libs/pyflakes/scripts/pyflakes.py create mode 120000 pymode/libs/pylama delete mode 100644 pymode/libs/pylama/__init__.py delete mode 100644 pymode/libs/pylama/__main__.py delete mode 100644 pymode/libs/pylama/async.py delete mode 100644 pymode/libs/pylama/config.py delete mode 100644 pymode/libs/pylama/core.py delete mode 100644 pymode/libs/pylama/errors.py delete mode 100644 pymode/libs/pylama/hook.py delete mode 100644 pymode/libs/pylama/libs/__init__.py delete mode 100644 pymode/libs/pylama/libs/importlib.py delete mode 100644 pymode/libs/pylama/libs/inirama.py delete mode 100644 pymode/libs/pylama/lint/__init__.py delete mode 100644 pymode/libs/pylama/lint/extensions.py delete mode 100644 pymode/libs/pylama/lint/pylama_mccabe.py delete mode 100644 pymode/libs/pylama/lint/pylama_pycodestyle.py delete mode 100644 pymode/libs/pylama/lint/pylama_pydocstyle.py delete mode 100644 pymode/libs/pylama/lint/pylama_pyflakes.py delete mode 100644 pymode/libs/pylama/lint/pylama_pylint/__init__.py delete mode 100644 pymode/libs/pylama/lint/pylama_pylint/main.py delete mode 100644 pymode/libs/pylama/lint/pylama_pylint/pylint.rc delete mode 100644 pymode/libs/pylama/lint/pylama_radon.py delete mode 100644 pymode/libs/pylama/main.py delete mode 100644 pymode/libs/pylama/pytest.py create mode 120000 pymode/libs/snowballstemmer delete mode 100644 pymode/libs/snowballstemmer/__init__.py delete mode 100644 pymode/libs/snowballstemmer/among.py delete mode 100644 pymode/libs/snowballstemmer/basestemmer.py delete mode 100644 pymode/libs/snowballstemmer/danish_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/dutch_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/english_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/finnish_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/french_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/german_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/hungarian_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/italian_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/norwegian_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/porter_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/portuguese_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/romanian_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/russian_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/spanish_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/swedish_stemmer.py delete mode 100644 pymode/libs/snowballstemmer/turkish_stemmer.py delete mode 100644 pymode/libs/wrapt/__init__.py delete mode 100644 pymode/libs/wrapt/arguments.py delete mode 100644 pymode/libs/wrapt/decorators.py delete mode 100644 pymode/libs/wrapt/importer.py delete mode 100644 pymode/libs/wrapt/wrappers.py create mode 160000 submodules/autopep8 create mode 160000 submodules/mccabe create mode 160000 submodules/pycodestyle create mode 160000 submodules/pydocstyle create mode 160000 submodules/pyflakes create mode 160000 submodules/pylama create mode 160000 submodules/snowball_py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..a40c4d6c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,28 @@ +[submodule "submodules/autopep8"] + path = submodules/autopep8 + url = https://github.com/hhatto/autopep8 + ignore = dirty +[submodule "submodules/pycodestyle"] + path = submodules/pycodestyle + url = https://github.com/PyCQA/pycodestyle + ignore = dirty +[submodule "submodules/pydocstyle"] + path = submodules/pydocstyle + url = https://github.com/PyCQA/pydocstyle/ + ignore = dirty +[submodule "submodules/mccabe"] + path = submodules/mccabe + url = https://github.com/PyCQA/mccabe + ignore = dirty +[submodule "submodules/pyflakes"] + path = submodules/pyflakes + url = https://github.com/PyCQA/pyflakes + ignore = dirty +[submodule "submodules/snowball_py"] + path = submodules/snowball_py + url = https://github.com/shibukawa/snowball_py + ignore = dirty +[submodule "submodules/pylama"] + path = submodules/pylama + url = https://github.com/fmv1992/pylama + ignore = dirty diff --git a/pymode/autopep8.py b/pymode/autopep8.py deleted file mode 100644 index 62e5832f..00000000 --- a/pymode/autopep8.py +++ /dev/null @@ -1,3885 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2010-2011 Hideo Hattori -# Copyright (C) 2011-2013 Hideo Hattori, Steven Myint -# Copyright (C) 2013-2016 Hideo Hattori, Steven Myint, Bill Wendling -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Automatically formats Python code to conform to the PEP 8 style guide. - -Fixes that only need be done once can be added by adding a function of the form -"fix_(source)" to this module. They should return the fixed source code. -These fixes are picked up by apply_global_fixes(). - -Fixes that depend on pycodestyle should be added as methods to FixPEP8. See the -class documentation for more information. - -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import codecs -import collections -import copy -import difflib -import fnmatch -import inspect -import io -import keyword -import locale -import os -import re -import signal -import sys -import textwrap -import token -import tokenize - -import pycodestyle - - -try: - unicode -except NameError: - unicode = str - - -__version__ = '1.3.2' - - -CR = '\r' -LF = '\n' -CRLF = '\r\n' - - -PYTHON_SHEBANG_REGEX = re.compile(r'^#!.*\bpython[23]?\b\s*$') -LAMBDA_REGEX = re.compile(r'([\w.]+)\s=\slambda\s*([\(\)\w,\s.]*):') -COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+([^][)(}{]+)\s+(in|is)\s') -BARE_EXCEPT_REGEX = re.compile(r'except\s*:') -STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\s.*\):') - - -# For generating line shortening candidates. -SHORTEN_OPERATOR_GROUPS = frozenset([ - frozenset([',']), - frozenset(['%']), - frozenset([',', '(', '[', '{']), - frozenset(['%', '(', '[', '{']), - frozenset([',', '(', '[', '{', '%', '+', '-', '*', '/', '//']), - frozenset(['%', '+', '-', '*', '/', '//']), -]) - - -DEFAULT_IGNORE = 'E24,W503' -DEFAULT_INDENT_SIZE = 4 - - -# W602 is handled separately due to the need to avoid "with_traceback". -CODE_TO_2TO3 = { - 'E231': ['ws_comma'], - 'E721': ['idioms'], - 'W601': ['has_key'], - 'W603': ['ne'], - 'W604': ['repr'], - 'W690': ['apply', - 'except', - 'exitfunc', - 'numliterals', - 'operator', - 'paren', - 'reduce', - 'renames', - 'standarderror', - 'sys_exc', - 'throw', - 'tuple_params', - 'xreadlines']} - - -if sys.platform == 'win32': # pragma: no cover - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') -else: - DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') -PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') - - -MAX_PYTHON_FILE_DETECTION_BYTES = 1024 - - -def open_with_encoding(filename, - encoding=None, mode='r', limit_byte_check=-1): - """Return opened file with a specific encoding.""" - if not encoding: - encoding = detect_encoding(filename, limit_byte_check=limit_byte_check) - - return io.open(filename, mode=mode, encoding=encoding, - newline='') # Preserve line endings - - -def detect_encoding(filename, limit_byte_check=-1): - """Return file encoding.""" - try: - with open(filename, 'rb') as input_file: - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0] - - with open_with_encoding(filename, encoding) as test_file: - test_file.read(limit_byte_check) - - return encoding - except (LookupError, SyntaxError, UnicodeDecodeError): - return 'latin-1' - - -def readlines_from_file(filename): - """Return contents of file.""" - with open_with_encoding(filename) as input_file: - return input_file.readlines() - - -def extended_blank_lines(logical_line, - blank_lines, - blank_before, - indent_level, - previous_logical): - """Check for missing blank lines after class declaration.""" - if previous_logical.startswith('def '): - if blank_lines and pycodestyle.DOCSTRING_REGEX.match(logical_line): - yield (0, 'E303 too many blank lines ({0})'.format(blank_lines)) - elif pycodestyle.DOCSTRING_REGEX.match(previous_logical): - # Missing blank line between class docstring and method declaration. - if ( - indent_level and - not blank_lines and - not blank_before and - logical_line.startswith(('def ')) and - '(self' in logical_line - ): - yield (0, 'E301 expected 1 blank line, found 0') - - -pycodestyle.register_check(extended_blank_lines) - - -def continued_indentation(logical_line, tokens, indent_level, indent_char, - noqa): - """Override pycodestyle's function to provide indentation information.""" - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - if noqa or nrows == 1: - return - - # indent_next tells us whether the next block is indented. Assuming - # that it is indented by 4 spaces, then we should not allow 4-space - # indents on the final continuation line. In turn, some other - # indents are allowed to have an extra 4 spaces. - indent_next = logical_line.endswith(':') - - row = depth = 0 - valid_hangs = ( - (DEFAULT_INDENT_SIZE,) - if indent_char != '\t' else (DEFAULT_INDENT_SIZE, - 2 * DEFAULT_INDENT_SIZE) - ) - - # Remember how many brackets were opened on each line. - parens = [0] * nrows - - # Relative indents of physical lines. - rel_indent = [0] * nrows - - # For each depth, collect a list of opening rows. - open_rows = [[0]] - # For each depth, memorize the hanging indentation. - hangs = [None] - - # Visual indents. - indent_chances = {} - last_indent = tokens[0][2] - indent = [last_indent[1]] - - last_token_multiline = None - line = None - last_line = '' - last_line_begins_with_multiline = False - for token_type, text, start, end, line in tokens: - - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - last_line_begins_with_multiline = last_token_multiline - - if newline: - # This is the beginning of a continuation line. - last_indent = start - - # Record the initial indent. - rel_indent[row] = pycodestyle.expand_indent(line) - indent_level - - # Identify closing bracket. - close_bracket = (token_type == tokenize.OP and text in ']})') - - # Is the indent relative to an opening bracket line? - for open_row in reversed(open_rows[depth]): - hang = rel_indent[row] - rel_indent[open_row] - hanging_indent = hang in valid_hangs - if hanging_indent: - break - if hangs[depth]: - hanging_indent = (hang == hangs[depth]) - - visual_indent = (not close_bracket and hang > 0 and - indent_chances.get(start[1])) - - if close_bracket and indent[depth]: - # Closing bracket for visual indent. - if start[1] != indent[depth]: - yield (start, 'E124 {0}'.format(indent[depth])) - elif close_bracket and not hang: - pass - elif indent[depth] and start[1] < indent[depth]: - # Visual indent is broken. - yield (start, 'E128 {0}'.format(indent[depth])) - elif (hanging_indent or - (indent_next and - rel_indent[row] == 2 * DEFAULT_INDENT_SIZE)): - # Hanging indent is verified. - if close_bracket: - yield (start, 'E123 {0}'.format(indent_level + - rel_indent[open_row])) - hangs[depth] = hang - elif visual_indent is True: - # Visual indent is verified. - indent[depth] = start[1] - elif visual_indent in (text, unicode): - # Ignore token lined up with matching one from a previous line. - pass - else: - one_indented = (indent_level + rel_indent[open_row] + - DEFAULT_INDENT_SIZE) - # Indent is broken. - if hang <= 0: - error = ('E122', one_indented) - elif indent[depth]: - error = ('E127', indent[depth]) - elif not close_bracket and hangs[depth]: - error = ('E131', one_indented) - elif hang > DEFAULT_INDENT_SIZE: - error = ('E126', one_indented) - else: - hangs[depth] = hang - error = ('E121', one_indented) - - yield (start, '{0} {1}'.format(*error)) - - # Look for visual indenting. - if ( - parens[row] and - token_type not in (tokenize.NL, tokenize.COMMENT) and - not indent[depth] - ): - indent[depth] = start[1] - indent_chances[start[1]] = True - # Deal with implicit string concatenation. - elif (token_type in (tokenize.STRING, tokenize.COMMENT) or - text in ('u', 'ur', 'b', 'br')): - indent_chances[start[1]] = unicode - # Special case for the "if" statement because len("if (") is equal to - # 4. - elif not indent_chances and not row and not depth and text == 'if': - indent_chances[end[1] + 1] = True - elif text == ':' and line[end[1]:].isspace(): - open_rows[depth].append(row) - - # Keep track of bracket depth. - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - hangs.append(None) - if len(open_rows) == depth: - open_rows.append([]) - open_rows[depth].append(row) - parens[row] += 1 - elif text in ')]}' and depth > 0: - # Parent indents should not be more than this one. - prev_indent = indent.pop() or last_indent[1] - hangs.pop() - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - del open_rows[depth + 1:] - depth -= 1 - if depth: - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if ( - start[1] not in indent_chances and - # This is for purposes of speeding up E121 (GitHub #90). - not last_line.rstrip().endswith(',') - ): - # Allow to line up tokens. - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - if last_token_multiline: - rel_indent[end[0] - first_row] = rel_indent[row] - - last_line = line - - if ( - indent_next and - not last_line_begins_with_multiline and - pycodestyle.expand_indent(line) == indent_level + DEFAULT_INDENT_SIZE - ): - pos = (start[0], indent[0] + 4) - desired_indent = indent_level + 2 * DEFAULT_INDENT_SIZE - if visual_indent: - yield (pos, 'E129 {0}'.format(desired_indent)) - else: - yield (pos, 'E125 {0}'.format(desired_indent)) - - -del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation] -pycodestyle.register_check(continued_indentation) - - -class FixPEP8(object): - - """Fix invalid code. - - Fixer methods are prefixed "fix_". The _fix_source() method looks for these - automatically. - - The fixer method can take either one or two arguments (in addition to - self). The first argument is "result", which is the error information from - pycodestyle. The second argument, "logical", is required only for - logical-line fixes. - - The fixer method can return the list of modified lines or None. An empty - list would mean that no changes were made. None would mean that only the - line reported in the pycodestyle error was modified. Note that the modified - line numbers that are returned are indexed at 1. This typically would - correspond with the line number reported in the pycodestyle error - information. - - [fixed method list] - - e111,e114,e115,e116 - - e121,e122,e123,e124,e125,e126,e127,e128,e129 - - e201,e202,e203 - - e211 - - e221,e222,e223,e224,e225 - - e231 - - e251 - - e261,e262 - - e271,e272,e273,e274 - - e301,e302,e303,e304,e306 - - e401 - - e502 - - e701,e702,e703,e704 - - e711,e712,e713,e714 - - e722 - - e731 - - w291 - - w503 - - """ - - def __init__(self, filename, - options, - contents=None, - long_line_ignore_cache=None): - self.filename = filename - if contents is None: - self.source = readlines_from_file(filename) - else: - sio = io.StringIO(contents) - self.source = sio.readlines() - self.options = options - self.indent_word = _get_indentword(''.join(self.source)) - - self.long_line_ignore_cache = ( - set() if long_line_ignore_cache is None - else long_line_ignore_cache) - - # Many fixers are the same even though pycodestyle categorizes them - # differently. - self.fix_e115 = self.fix_e112 - self.fix_e116 = self.fix_e113 - self.fix_e121 = self._fix_reindent - self.fix_e122 = self._fix_reindent - self.fix_e123 = self._fix_reindent - self.fix_e124 = self._fix_reindent - self.fix_e126 = self._fix_reindent - self.fix_e127 = self._fix_reindent - self.fix_e128 = self._fix_reindent - self.fix_e129 = self._fix_reindent - self.fix_e202 = self.fix_e201 - self.fix_e203 = self.fix_e201 - self.fix_e211 = self.fix_e201 - self.fix_e221 = self.fix_e271 - self.fix_e222 = self.fix_e271 - self.fix_e223 = self.fix_e271 - self.fix_e226 = self.fix_e225 - self.fix_e227 = self.fix_e225 - self.fix_e228 = self.fix_e225 - self.fix_e241 = self.fix_e271 - self.fix_e242 = self.fix_e224 - self.fix_e261 = self.fix_e262 - self.fix_e272 = self.fix_e271 - self.fix_e273 = self.fix_e271 - self.fix_e274 = self.fix_e271 - self.fix_e306 = self.fix_e301 - self.fix_e501 = ( - self.fix_long_line_logically if - options and (options.aggressive >= 2 or options.experimental) else - self.fix_long_line_physically) - self.fix_e703 = self.fix_e702 - self.fix_w293 = self.fix_w291 - - def _fix_source(self, results): - try: - (logical_start, logical_end) = _find_logical(self.source) - logical_support = True - except (SyntaxError, tokenize.TokenError): # pragma: no cover - logical_support = False - - completed_lines = set() - for result in sorted(results, key=_priority_key): - if result['line'] in completed_lines: - continue - - fixed_methodname = 'fix_' + result['id'].lower() - if hasattr(self, fixed_methodname): - fix = getattr(self, fixed_methodname) - - line_index = result['line'] - 1 - original_line = self.source[line_index] - - is_logical_fix = len(_get_parameters(fix)) > 2 - if is_logical_fix: - logical = None - if logical_support: - logical = _get_logical(self.source, - result, - logical_start, - logical_end) - if logical and set(range( - logical[0][0] + 1, - logical[1][0] + 1)).intersection( - completed_lines): - continue - - modified_lines = fix(result, logical) - else: - modified_lines = fix(result) - - if modified_lines is None: - # Force logical fixes to report what they modified. - assert not is_logical_fix - - if self.source[line_index] == original_line: - modified_lines = [] - - if modified_lines: - completed_lines.update(modified_lines) - elif modified_lines == []: # Empty list means no fix - if self.options.verbose >= 2: - print( - '---> Not fixing {error} on line {line}'.format( - error=result['id'], line=result['line']), - file=sys.stderr) - else: # We assume one-line fix when None. - completed_lines.add(result['line']) - else: - if self.options.verbose >= 3: - print( - "---> '{0}' is not defined.".format(fixed_methodname), - file=sys.stderr) - - info = result['info'].strip() - print('---> {0}:{1}:{2}:{3}'.format(self.filename, - result['line'], - result['column'], - info), - file=sys.stderr) - - def fix(self): - """Return a version of the source code with PEP 8 violations fixed.""" - pep8_options = { - 'ignore': self.options.ignore, - 'select': self.options.select, - 'max_line_length': self.options.max_line_length, - } - results = _execute_pep8(pep8_options, self.source) - - if self.options.verbose: - progress = {} - for r in results: - if r['id'] not in progress: - progress[r['id']] = set() - progress[r['id']].add(r['line']) - print('---> {n} issue(s) to fix {progress}'.format( - n=len(results), progress=progress), file=sys.stderr) - - if self.options.line_range: - start, end = self.options.line_range - results = [r for r in results - if start <= r['line'] <= end] - - self._fix_source(filter_results(source=''.join(self.source), - results=results, - aggressive=self.options.aggressive)) - - if self.options.line_range: - # If number of lines has changed then change line_range. - count = sum(sline.count('\n') - for sline in self.source[start - 1:end]) - self.options.line_range[1] = start + count - 1 - - return ''.join(self.source) - - def _fix_reindent(self, result): - """Fix a badly indented line. - - This is done by adding or removing from its initial indent only. - - """ - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - self.source[line_index] = ' ' * num_indent_spaces + target.lstrip() - - def fix_e112(self, result): - """Fix under-indented comments.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - if not target.lstrip().startswith('#'): - # Don't screw with invalid syntax. - return [] - - self.source[line_index] = self.indent_word + target - - def fix_e113(self, result): - """Fix over-indented comments.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - indent = _get_indentation(target) - stripped = target.lstrip() - - if not stripped.startswith('#'): - # Don't screw with invalid syntax. - return [] - - self.source[line_index] = indent[1:] + stripped - - def fix_e125(self, result): - """Fix indentation undistinguish from the next logical line.""" - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - spaces_to_add = num_indent_spaces - len(_get_indentation(target)) - indent = len(_get_indentation(target)) - modified_lines = [] - - while len(_get_indentation(self.source[line_index])) >= indent: - self.source[line_index] = (' ' * spaces_to_add + - self.source[line_index]) - modified_lines.append(1 + line_index) # Line indexed at 1. - line_index -= 1 - - return modified_lines - - def fix_e131(self, result): - """Fix indentation undistinguish from the next logical line.""" - num_indent_spaces = int(result['info'].split()[1]) - line_index = result['line'] - 1 - target = self.source[line_index] - - spaces_to_add = num_indent_spaces - len(_get_indentation(target)) - - if spaces_to_add >= 0: - self.source[line_index] = (' ' * spaces_to_add + - self.source[line_index]) - else: - offset = abs(spaces_to_add) - self.source[line_index] = self.source[line_index][offset:] - - def fix_e201(self, result): - """Remove extraneous whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - fixed = fix_whitespace(target, - offset=offset, - replacement='') - - self.source[line_index] = fixed - - def fix_e224(self, result): - """Remove extraneous whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + target[offset:].replace('\t', ' ') - self.source[result['line'] - 1] = fixed - - def fix_e225(self, result): - """Fix missing whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + ' ' + target[offset:] - - # Only proceed if non-whitespace characters match. - # And make sure we don't break the indentation. - if ( - fixed.replace(' ', '') == target.replace(' ', '') and - _get_indentation(fixed) == _get_indentation(target) - ): - self.source[result['line'] - 1] = fixed - error_code = result.get('id', 0) - try: - ts = generate_tokens(fixed) - except tokenize.TokenError: - return - if not check_syntax(fixed.lstrip()): - return - errors = list( - pycodestyle.missing_whitespace_around_operator(fixed, ts)) - for e in reversed(errors): - if error_code != e[1].split()[0]: - continue - offset = e[0][1] - fixed = fixed[:offset] + ' ' + fixed[offset:] - self.source[result['line'] - 1] = fixed - else: - return [] - - def fix_e231(self, result): - """Add missing whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - fixed = target[:offset].rstrip() + ' ' + target[offset:].lstrip() - self.source[line_index] = fixed - - def fix_e251(self, result): - """Remove whitespace around parameter '=' sign.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - # This is necessary since pycodestyle sometimes reports columns that - # goes past the end of the physical line. This happens in cases like, - # foo(bar\n=None) - c = min(result['column'] - 1, - len(target) - 1) - - if target[c].strip(): - fixed = target - else: - fixed = target[:c].rstrip() + target[c:].lstrip() - - # There could be an escaped newline - # - # def foo(a=\ - # 1) - if fixed.endswith(('=\\\n', '=\\\r\n', '=\\\r')): - self.source[line_index] = fixed.rstrip('\n\r \t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] # Line indexed at 1 - - self.source[result['line'] - 1] = fixed - - def fix_e262(self, result): - """Fix spacing after comment hash.""" - target = self.source[result['line'] - 1] - offset = result['column'] - - code = target[:offset].rstrip(' \t#') - comment = target[offset:].lstrip(' \t#') - - fixed = code + (' # ' + comment if comment.strip() else '\n') - - self.source[result['line'] - 1] = fixed - - def fix_e271(self, result): - """Fix extraneous whitespace around keywords.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - fixed = fix_whitespace(target, - offset=offset, - replacement=' ') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e301(self, result): - """Add missing blank line.""" - cr = '\n' - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e302(self, result): - """Add missing 2 blank lines.""" - add_linenum = 2 - int(result['info'].split()[-1]) - cr = '\n' * add_linenum - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e303(self, result): - """Remove extra blank lines.""" - delete_linenum = int(result['info'].split('(')[1].split(')')[0]) - 2 - delete_linenum = max(1, delete_linenum) - - # We need to count because pycodestyle reports an offset line number if - # there are comments. - cnt = 0 - line = result['line'] - 2 - modified_lines = [] - while cnt < delete_linenum and line >= 0: - if not self.source[line].strip(): - self.source[line] = '' - modified_lines.append(1 + line) # Line indexed at 1 - cnt += 1 - line -= 1 - - return modified_lines - - def fix_e304(self, result): - """Remove blank line following function decorator.""" - line = result['line'] - 2 - if not self.source[line].strip(): - self.source[line] = '' - - def fix_e305(self, result): - """Add missing 2 blank lines after end of function or class.""" - cr = '\n' - # check comment line - offset = result['line'] - 2 - while True: - if offset < 0: - break - line = self.source[offset].lstrip() - if not line: - break - if line[0] != '#': - break - offset -= 1 - offset += 1 - self.source[offset] = cr + self.source[offset] - - def fix_e401(self, result): - """Put imports on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - if not target.lstrip().startswith('import'): - return [] - - indentation = re.split(pattern=r'\bimport\b', - string=target, maxsplit=1)[0] - fixed = (target[:offset].rstrip('\t ,') + '\n' + - indentation + 'import ' + target[offset:].lstrip('\t ,')) - self.source[line_index] = fixed - - def fix_long_line_logically(self, result, logical): - """Try to make lines fit within --max-line-length characters.""" - if ( - not logical or - len(logical[2]) == 1 or - self.source[result['line'] - 1].lstrip().startswith('#') - ): - return self.fix_long_line_physically(result) - - start_line_index = logical[0][0] - end_line_index = logical[1][0] - logical_lines = logical[2] - - previous_line = get_item(self.source, start_line_index - 1, default='') - next_line = get_item(self.source, end_line_index + 1, default='') - - single_line = join_logical_line(''.join(logical_lines)) - - try: - fixed = self.fix_long_line( - target=single_line, - previous_line=previous_line, - next_line=next_line, - original=''.join(logical_lines)) - except (SyntaxError, tokenize.TokenError): - return self.fix_long_line_physically(result) - - if fixed: - for line_index in range(start_line_index, end_line_index + 1): - self.source[line_index] = '' - self.source[start_line_index] = fixed - return range(start_line_index + 1, end_line_index + 1) - - return [] - - def fix_long_line_physically(self, result): - """Try to make lines fit within --max-line-length characters.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - previous_line = get_item(self.source, line_index - 1, default='') - next_line = get_item(self.source, line_index + 1, default='') - - try: - fixed = self.fix_long_line( - target=target, - previous_line=previous_line, - next_line=next_line, - original=target) - except (SyntaxError, tokenize.TokenError): - return [] - - if fixed: - self.source[line_index] = fixed - return [line_index + 1] - - return [] - - def fix_long_line(self, target, previous_line, - next_line, original): - cache_entry = (target, previous_line, next_line) - if cache_entry in self.long_line_ignore_cache: - return [] - - if target.lstrip().startswith('#'): - if self.options.aggressive: - # Wrap commented lines. - return shorten_comment( - line=target, - max_line_length=self.options.max_line_length, - last_comment=not next_line.lstrip().startswith('#')) - else: - return [] - - fixed = get_fixed_long_line( - target=target, - previous_line=previous_line, - original=original, - indent_word=self.indent_word, - max_line_length=self.options.max_line_length, - aggressive=self.options.aggressive, - experimental=self.options.experimental, - verbose=self.options.verbose) - - if fixed and not code_almost_equal(original, fixed): - return fixed - - self.long_line_ignore_cache.add(cache_entry) - return None - - def fix_e502(self, result): - """Remove extraneous escape of newline.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - self.source[line_index] = target.rstrip('\n\r \t\\') + '\n' - - def fix_e701(self, result): - """Put colon-separated compound statement on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - c = result['column'] - - fixed_source = (target[:c] + '\n' + - _get_indentation(target) + self.indent_word + - target[c:].lstrip('\n\r \t\\')) - self.source[result['line'] - 1] = fixed_source - return [result['line'], result['line'] + 1] - - def fix_e702(self, result, logical): - """Put semicolon-separated compound statement on separate lines.""" - if not logical: - return [] # pragma: no cover - logical_lines = logical[2] - - # Avoid applying this when indented. - # https://docs.python.org/reference/compound_stmts.html - for line in logical_lines: - if ':' in line: - return [] - - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.rstrip().endswith('\\'): - # Normalize '1; \\\n2' into '1; 2'. - self.source[line_index] = target.rstrip('\n \r\t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] - - if target.rstrip().endswith(';'): - self.source[line_index] = target.rstrip('\n \r\t;') + '\n' - return [line_index + 1] - - offset = result['column'] - 1 - first = target[:offset].rstrip(';').rstrip() - second = (_get_indentation(logical_lines[0]) + - target[offset:].lstrip(';').lstrip()) - - # Find inline comment. - inline_comment = None - if target[offset:].lstrip(';').lstrip()[:2] == '# ': - inline_comment = target[offset:].lstrip(';') - - if inline_comment: - self.source[line_index] = first + inline_comment - else: - self.source[line_index] = first + '\n' + second - return [line_index + 1] - - def fix_e704(self, result): - """Fix multiple statements on one line def""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = STARTSWITH_DEF_REGEX.match(target) - if match: - self.source[line_index] = '{0}\n{1}{2}'.format( - match.group(0), - _get_indentation(target) + self.indent_word, - target[match.end(0):].lstrip()) - - def fix_e711(self, result): - """Fix comparison with None.""" - (line_index, offset, target) = get_index_offset_contents(result, - self.source) - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - if not right.startswith('None'): - return [] - - if center.strip() == '==': - new_center = 'is' - elif center.strip() == '!=': - new_center = 'is not' - else: - return [] - - self.source[line_index] = ' '.join([left, new_center, right]) - - def fix_e712(self, result): - """Fix (trivial case of) comparison with boolean.""" - (line_index, offset, target) = get_index_offset_contents(result, - self.source) - - # Handle very easy "not" special cases. - if re.match(r'^\s*if [\w.]+ == False:$', target): - self.source[line_index] = re.sub(r'if ([\w.]+) == False:', - r'if not \1:', target, count=1) - elif re.match(r'^\s*if [\w.]+ != True:$', target): - self.source[line_index] = re.sub(r'if ([\w.]+) != True:', - r'if not \1:', target, count=1) - else: - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - # Handle simple cases only. - new_right = None - if center.strip() == '==': - if re.match(r'\bTrue\b', right): - new_right = re.sub(r'\bTrue\b *', '', right, count=1) - elif center.strip() == '!=': - if re.match(r'\bFalse\b', right): - new_right = re.sub(r'\bFalse\b *', '', right, count=1) - - if new_right is None: - return [] - - if new_right[0].isalnum(): - new_right = ' ' + new_right - - self.source[line_index] = left + new_right - - def fix_e713(self, result): - """Fix (trivial case of) non-membership check.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - - match = COMPARE_NEGATIVE_REGEX.search(target) - if match: - if match.group(3) == 'in': - pos_start = match.start(1) - self.source[line_index] = '{0}{1} {2} {3} {4}'.format( - target[:pos_start], match.group(2), match.group(1), - match.group(3), target[match.end():]) - - def fix_e714(self, result): - """Fix object identity should be 'is not' case.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - - match = COMPARE_NEGATIVE_REGEX.search(target) - if match: - if match.group(3) == 'is': - pos_start = match.start(1) - self.source[line_index] = '{0}{1} {2} {3} {4}'.format( - target[:pos_start], match.group(2), match.group(3), - match.group(1), target[match.end():]) - - def fix_e722(self, result): - """fix bare except""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = BARE_EXCEPT_REGEX.search(target) - if match: - self.source[line_index] = '{0}{1}{2}'.format( - target[:result['column'] - 1], "except BaseException:", - target[match.end():]) - - def fix_e731(self, result): - """Fix do not assign a lambda expression check.""" - (line_index, _, target) = get_index_offset_contents(result, - self.source) - match = LAMBDA_REGEX.search(target) - if match: - end = match.end() - self.source[line_index] = '{0}def {1}({2}): return {3}'.format( - target[:match.start(0)], match.group(1), match.group(2), - target[end:].lstrip()) - - def fix_w291(self, result): - """Remove trailing whitespace.""" - fixed_line = self.source[result['line'] - 1].rstrip() - self.source[result['line'] - 1] = fixed_line + '\n' - - def fix_w391(self, _): - """Remove trailing blank lines.""" - blank_count = 0 - for line in reversed(self.source): - line = line.rstrip() - if line: - break - else: - blank_count += 1 - - original_length = len(self.source) - self.source = self.source[:original_length - blank_count] - return range(1, 1 + original_length) - - def fix_w503(self, result): - (line_index, _, target) = get_index_offset_contents(result, - self.source) - one_string_token = target.split()[0] - try: - ts = generate_tokens(one_string_token) - except tokenize.TokenError: - return - if not _is_binary_operator(ts[0][0], one_string_token): - return - # find comment - comment_index = None - for i in range(5): - # NOTE: try to parse code in 5 times - if (line_index - i) < 0: - break - from_index = line_index - i - 1 - to_index = line_index + 1 - try: - ts = generate_tokens("".join(self.source[from_index:to_index])) - except Exception: - continue - newline_count = 0 - newline_index = [] - for i, t in enumerate(ts): - if t[0] in (tokenize.NEWLINE, tokenize.NL): - newline_index.append(i) - newline_count += 1 - if newline_count > 2: - tts = ts[newline_index[-3]:] - else: - tts = ts - old = None - for t in tts: - if tokenize.COMMENT == t[0]: - if old is None: - comment_index = 0 - else: - comment_index = old[3][1] - break - old = t - break - i = target.index(one_string_token) - self.source[line_index] = '{0}{1}'.format( - target[:i], target[i + len(one_string_token):]) - nl = find_newline(self.source[line_index - 1:line_index]) - before_line = self.source[line_index - 1] - bl = before_line.index(nl) - if comment_index: - self.source[line_index - 1] = '{0} {1} {2}'.format( - before_line[:comment_index], one_string_token, - before_line[comment_index + 1:]) - else: - self.source[line_index - 1] = '{0} {1}{2}'.format( - before_line[:bl], one_string_token, before_line[bl:]) - - -def get_index_offset_contents(result, source): - """Return (line_index, column_offset, line_contents).""" - line_index = result['line'] - 1 - return (line_index, - result['column'] - 1, - source[line_index]) - - -def get_fixed_long_line(target, previous_line, original, - indent_word=' ', max_line_length=79, - aggressive=False, experimental=False, verbose=False): - """Break up long line and return result. - - Do this by generating multiple reformatted candidates and then - ranking the candidates to heuristically select the best option. - - """ - indent = _get_indentation(target) - source = target[len(indent):] - assert source.lstrip() == source - assert not target.lstrip().startswith('#') - - # Check for partial multiline. - tokens = list(generate_tokens(source)) - - candidates = shorten_line( - tokens, source, indent, - indent_word, - max_line_length, - aggressive=aggressive, - experimental=experimental, - previous_line=previous_line) - - # Also sort alphabetically as a tie breaker (for determinism). - candidates = sorted( - sorted(set(candidates).union([target, original])), - key=lambda x: line_shortening_rank( - x, - indent_word, - max_line_length, - experimental=experimental)) - - if verbose >= 4: - print(('-' * 79 + '\n').join([''] + candidates + ['']), - file=wrap_output(sys.stderr, 'utf-8')) - - if candidates: - best_candidate = candidates[0] - - # Don't allow things to get longer. - if longest_line_length(best_candidate) > longest_line_length(original): - return None - - return best_candidate - - -def longest_line_length(code): - """Return length of longest line.""" - return max(len(line) for line in code.splitlines()) - - -def join_logical_line(logical_line): - """Return single line based on logical line input.""" - indentation = _get_indentation(logical_line) - - return indentation + untokenize_without_newlines( - generate_tokens(logical_line.lstrip())) + '\n' - - -def untokenize_without_newlines(tokens): - """Return source code based on tokens.""" - text = '' - last_row = 0 - last_column = -1 - - for t in tokens: - token_string = t[1] - (start_row, start_column) = t[2] - (end_row, end_column) = t[3] - - if start_row > last_row: - last_column = 0 - if ( - (start_column > last_column or token_string == '\n') and - not text.endswith(' ') - ): - text += ' ' - - if token_string != '\n': - text += token_string - - last_row = end_row - last_column = end_column - - return text.rstrip() - - -def _find_logical(source_lines): - # Make a variable which is the index of all the starts of lines. - logical_start = [] - logical_end = [] - last_newline = True - parens = 0 - for t in generate_tokens(''.join(source_lines)): - if t[0] in [tokenize.COMMENT, tokenize.DEDENT, - tokenize.INDENT, tokenize.NL, - tokenize.ENDMARKER]: - continue - if not parens and t[0] in [tokenize.NEWLINE, tokenize.SEMI]: - last_newline = True - logical_end.append((t[3][0] - 1, t[2][1])) - continue - if last_newline and not parens: - logical_start.append((t[2][0] - 1, t[2][1])) - last_newline = False - if t[0] == tokenize.OP: - if t[1] in '([{': - parens += 1 - elif t[1] in '}])': - parens -= 1 - return (logical_start, logical_end) - - -def _get_logical(source_lines, result, logical_start, logical_end): - """Return the logical line corresponding to the result. - - Assumes input is already E702-clean. - - """ - row = result['line'] - 1 - col = result['column'] - 1 - ls = None - le = None - for i in range(0, len(logical_start), 1): - assert logical_end - x = logical_end[i] - if x[0] > row or (x[0] == row and x[1] > col): - le = x - ls = logical_start[i] - break - if ls is None: - return None - original = source_lines[ls[0]:le[0] + 1] - return ls, le, original - - -def get_item(items, index, default=None): - if 0 <= index < len(items): - return items[index] - - return default - - -def reindent(source, indent_size): - """Reindent all lines.""" - reindenter = Reindenter(source) - return reindenter.run(indent_size) - - -def code_almost_equal(a, b): - """Return True if code is similar. - - Ignore whitespace when comparing specific line. - - """ - split_a = split_and_strip_non_empty_lines(a) - split_b = split_and_strip_non_empty_lines(b) - - if len(split_a) != len(split_b): - return False - - for (index, _) in enumerate(split_a): - if ''.join(split_a[index].split()) != ''.join(split_b[index].split()): - return False - - return True - - -def split_and_strip_non_empty_lines(text): - """Return lines split by newline. - - Ignore empty lines. - - """ - return [line.strip() for line in text.splitlines() if line.strip()] - - -def fix_e265(source, aggressive=False): # pylint: disable=unused-argument - """Format block comments.""" - if '#' not in source: - # Optimization. - return source - - ignored_line_numbers = multiline_string_lines( - source, - include_docstrings=True) | set(commented_out_code_lines(source)) - - fixed_lines = [] - sio = io.StringIO(source) - for (line_number, line) in enumerate(sio.readlines(), start=1): - if ( - line.lstrip().startswith('#') and - line_number not in ignored_line_numbers and - not pycodestyle.noqa(line) - ): - indentation = _get_indentation(line) - line = line.lstrip() - - # Normalize beginning if not a shebang. - if len(line) > 1: - pos = next((index for index, c in enumerate(line) - if c != '#')) - if ( - # Leave multiple spaces like '# ' alone. - (line[:pos].count('#') > 1 or line[1].isalnum()) and - # Leave stylistic outlined blocks alone. - not line.rstrip().endswith('#') - ): - line = '# ' + line.lstrip('# \t') - - fixed_lines.append(indentation + line) - else: - fixed_lines.append(line) - - return ''.join(fixed_lines) - - -def refactor(source, fixer_names, ignore=None, filename=''): - """Return refactored code using lib2to3. - - Skip if ignore string is produced in the refactored code. - - """ - from lib2to3 import pgen2 - try: - new_text = refactor_with_2to3(source, - fixer_names=fixer_names, - filename=filename) - except (pgen2.parse.ParseError, - SyntaxError, - UnicodeDecodeError, - UnicodeEncodeError): - return source - - if ignore: - if ignore in new_text and ignore not in source: - return source - - return new_text - - -def code_to_2to3(select, ignore): - fixes = set() - for code, fix in CODE_TO_2TO3.items(): - if code_match(code, select=select, ignore=ignore): - fixes |= set(fix) - return fixes - - -def fix_2to3(source, - aggressive=True, select=None, ignore=None, filename=''): - """Fix various deprecated code (via lib2to3).""" - if not aggressive: - return source - - select = select or [] - ignore = ignore or [] - - return refactor(source, - code_to_2to3(select=select, - ignore=ignore), - filename=filename) - - -def fix_w602(source, aggressive=True): - """Fix deprecated form of raising exception.""" - if not aggressive: - return source - - return refactor(source, ['raise'], - ignore='with_traceback') - - -def find_newline(source): - """Return type of newline used in source. - - Input is a list of lines. - - """ - assert not isinstance(source, unicode) - - counter = collections.defaultdict(int) - for line in source: - if line.endswith(CRLF): - counter[CRLF] += 1 - elif line.endswith(CR): - counter[CR] += 1 - elif line.endswith(LF): - counter[LF] += 1 - - return (sorted(counter, key=counter.get, reverse=True) or [LF])[0] - - -def _get_indentword(source): - """Return indentation type.""" - indent_word = ' ' # Default in case source has no indentation - try: - for t in generate_tokens(source): - if t[0] == token.INDENT: - indent_word = t[1] - break - except (SyntaxError, tokenize.TokenError): - pass - return indent_word - - -def _get_indentation(line): - """Return leading whitespace.""" - if line.strip(): - non_whitespace_index = len(line) - len(line.lstrip()) - return line[:non_whitespace_index] - - return '' - - -def get_diff_text(old, new, filename): - """Return text of unified diff between old and new.""" - newline = '\n' - diff = difflib.unified_diff( - old, new, - 'original/' + filename, - 'fixed/' + filename, - lineterm=newline) - - text = '' - for line in diff: - text += line - - # Work around missing newline (http://bugs.python.org/issue2142). - if text and not line.endswith(newline): - text += newline + r'\ No newline at end of file' + newline - - return text - - -def _priority_key(pep8_result): - """Key for sorting PEP8 results. - - Global fixes should be done first. This is important for things like - indentation. - - """ - priority = [ - # Fix multiline colon-based before semicolon based. - 'e701', - # Break multiline statements early. - 'e702', - # Things that make lines longer. - 'e225', 'e231', - # Remove extraneous whitespace before breaking lines. - 'e201', - # Shorten whitespace in comment before resorting to wrapping. - 'e262' - ] - middle_index = 10000 - lowest_priority = [ - # We need to shorten lines last since the logical fixer can get in a - # loop, which causes us to exit early. - 'e501', - 'w503' - ] - key = pep8_result['id'].lower() - try: - return priority.index(key) - except ValueError: - try: - return middle_index + lowest_priority.index(key) + 1 - except ValueError: - return middle_index - - -def shorten_line(tokens, source, indentation, indent_word, max_line_length, - aggressive=False, experimental=False, previous_line=''): - """Separate line at OPERATOR. - - Multiple candidates will be yielded. - - """ - for candidate in _shorten_line(tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - aggressive=aggressive, - previous_line=previous_line): - yield candidate - - if aggressive: - for key_token_strings in SHORTEN_OPERATOR_GROUPS: - shortened = _shorten_line_at_tokens( - tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - key_token_strings=key_token_strings, - aggressive=aggressive) - - if shortened is not None and shortened != source: - yield shortened - - if experimental: - for shortened in _shorten_line_at_tokens_new( - tokens=tokens, - source=source, - indentation=indentation, - max_line_length=max_line_length): - - yield shortened - - -def _shorten_line(tokens, source, indentation, indent_word, - aggressive=False, previous_line=''): - """Separate line at OPERATOR. - - The input is expected to be free of newlines except for inside multiline - strings and at the end. - - Multiple candidates will be yielded. - - """ - for (token_type, - token_string, - start_offset, - end_offset) in token_offsets(tokens): - - if ( - token_type == tokenize.COMMENT and - not is_probably_part_of_multiline(previous_line) and - not is_probably_part_of_multiline(source) and - not source[start_offset + 1:].strip().lower().startswith( - ('noqa', 'pragma:', 'pylint:')) - ): - # Move inline comments to previous line. - first = source[:start_offset] - second = source[start_offset:] - yield (indentation + second.strip() + '\n' + - indentation + first.strip() + '\n') - elif token_type == token.OP and token_string != '=': - # Don't break on '=' after keyword as this violates PEP 8. - - assert token_type != token.INDENT - - first = source[:end_offset] - - second_indent = indentation - if first.rstrip().endswith('('): - second_indent += indent_word - elif '(' in first: - second_indent += ' ' * (1 + first.find('(')) - else: - second_indent += indent_word - - second = (second_indent + source[end_offset:].lstrip()) - if ( - not second.strip() or - second.lstrip().startswith('#') - ): - continue - - # Do not begin a line with a comma - if second.lstrip().startswith(','): - continue - # Do end a line with a dot - if first.rstrip().endswith('.'): - continue - if token_string in '+-*/': - fixed = first + ' \\' + '\n' + second - else: - fixed = first + '\n' + second - - # Only fix if syntax is okay. - if check_syntax(normalize_multiline(fixed) - if aggressive else fixed): - yield indentation + fixed - - -def _is_binary_operator(token_type, text): - return ((token_type == tokenize.OP or text in ['and', 'or']) and - text not in '()[]{},:.;@=%~') - - -# A convenient way to handle tokens. -Token = collections.namedtuple('Token', ['token_type', 'token_string', - 'spos', 'epos', 'line']) - - -class ReformattedLines(object): - - """The reflowed lines of atoms. - - Each part of the line is represented as an "atom." They can be moved - around when need be to get the optimal formatting. - - """ - - ########################################################################### - # Private Classes - - class _Indent(object): - - """Represent an indentation in the atom stream.""" - - def __init__(self, indent_amt): - self._indent_amt = indent_amt - - def emit(self): - return ' ' * self._indent_amt - - @property - def size(self): - return self._indent_amt - - class _Space(object): - - """Represent a space in the atom stream.""" - - def emit(self): - return ' ' - - @property - def size(self): - return 1 - - class _LineBreak(object): - - """Represent a line break in the atom stream.""" - - def emit(self): - return '\n' - - @property - def size(self): - return 0 - - def __init__(self, max_line_length): - self._max_line_length = max_line_length - self._lines = [] - self._bracket_depth = 0 - self._prev_item = None - self._prev_prev_item = None - - def __repr__(self): - return self.emit() - - ########################################################################### - # Public Methods - - def add(self, obj, indent_amt, break_after_open_bracket): - if isinstance(obj, Atom): - self._add_item(obj, indent_amt) - return - - self._add_container(obj, indent_amt, break_after_open_bracket) - - def add_comment(self, item): - num_spaces = 2 - if len(self._lines) > 1: - if isinstance(self._lines[-1], self._Space): - num_spaces -= 1 - if len(self._lines) > 2: - if isinstance(self._lines[-2], self._Space): - num_spaces -= 1 - - while num_spaces > 0: - self._lines.append(self._Space()) - num_spaces -= 1 - self._lines.append(item) - - def add_indent(self, indent_amt): - self._lines.append(self._Indent(indent_amt)) - - def add_line_break(self, indent): - self._lines.append(self._LineBreak()) - self.add_indent(len(indent)) - - def add_line_break_at(self, index, indent_amt): - self._lines.insert(index, self._LineBreak()) - self._lines.insert(index + 1, self._Indent(indent_amt)) - - def add_space_if_needed(self, curr_text, equal=False): - if ( - not self._lines or isinstance( - self._lines[-1], (self._LineBreak, self._Indent, self._Space)) - ): - return - - prev_text = unicode(self._prev_item) - prev_prev_text = ( - unicode(self._prev_prev_item) if self._prev_prev_item else '') - - if ( - # The previous item was a keyword or identifier and the current - # item isn't an operator that doesn't require a space. - ((self._prev_item.is_keyword or self._prev_item.is_string or - self._prev_item.is_name or self._prev_item.is_number) and - (curr_text[0] not in '([{.,:}])' or - (curr_text[0] == '=' and equal))) or - - # Don't place spaces around a '.', unless it's in an 'import' - # statement. - ((prev_prev_text != 'from' and prev_text[-1] != '.' and - curr_text != 'import') and - - # Don't place a space before a colon. - curr_text[0] != ':' and - - # Don't split up ending brackets by spaces. - ((prev_text[-1] in '}])' and curr_text[0] not in '.,}])') or - - # Put a space after a colon or comma. - prev_text[-1] in ':,' or - - # Put space around '=' if asked to. - (equal and prev_text == '=') or - - # Put spaces around non-unary arithmetic operators. - ((self._prev_prev_item and - (prev_text not in '+-' and - (self._prev_prev_item.is_name or - self._prev_prev_item.is_number or - self._prev_prev_item.is_string)) and - prev_text in ('+', '-', '%', '*', '/', '//', '**', 'in'))))) - ): - self._lines.append(self._Space()) - - def previous_item(self): - """Return the previous non-whitespace item.""" - return self._prev_item - - def fits_on_current_line(self, item_extent): - return self.current_size() + item_extent <= self._max_line_length - - def current_size(self): - """The size of the current line minus the indentation.""" - size = 0 - for item in reversed(self._lines): - size += item.size - if isinstance(item, self._LineBreak): - break - - return size - - def line_empty(self): - return (self._lines and - isinstance(self._lines[-1], - (self._LineBreak, self._Indent))) - - def emit(self): - string = '' - for item in self._lines: - if isinstance(item, self._LineBreak): - string = string.rstrip() - string += item.emit() - - return string.rstrip() + '\n' - - ########################################################################### - # Private Methods - - def _add_item(self, item, indent_amt): - """Add an item to the line. - - Reflow the line to get the best formatting after the item is - inserted. The bracket depth indicates if the item is being - inserted inside of a container or not. - - """ - if self._prev_item and self._prev_item.is_string and item.is_string: - # Place consecutive string literals on separate lines. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - - item_text = unicode(item) - if self._lines and self._bracket_depth: - # Adding the item into a container. - self._prevent_default_initializer_splitting(item, indent_amt) - - if item_text in '.,)]}': - self._split_after_delimiter(item, indent_amt) - - elif self._lines and not self.line_empty(): - # Adding the item outside of a container. - if self.fits_on_current_line(len(item_text)): - self._enforce_space(item) - - else: - # Line break for the new item. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - - self._lines.append(item) - self._prev_item, self._prev_prev_item = item, self._prev_item - - if item_text in '([{': - self._bracket_depth += 1 - - elif item_text in '}])': - self._bracket_depth -= 1 - assert self._bracket_depth >= 0 - - def _add_container(self, container, indent_amt, break_after_open_bracket): - actual_indent = indent_amt + 1 - - if ( - unicode(self._prev_item) != '=' and - not self.line_empty() and - not self.fits_on_current_line( - container.size + self._bracket_depth + 2) - ): - - if unicode(container)[0] == '(' and self._prev_item.is_name: - # Don't split before the opening bracket of a call. - break_after_open_bracket = True - actual_indent = indent_amt + 4 - elif ( - break_after_open_bracket or - unicode(self._prev_item) not in '([{' - ): - # If the container doesn't fit on the current line and the - # current line isn't empty, place the container on the next - # line. - self._lines.append(self._LineBreak()) - self._lines.append(self._Indent(indent_amt)) - break_after_open_bracket = False - else: - actual_indent = self.current_size() + 1 - break_after_open_bracket = False - - if isinstance(container, (ListComprehension, IfExpression)): - actual_indent = indent_amt - - # Increase the continued indentation only if recursing on a - # container. - container.reflow(self, ' ' * actual_indent, - break_after_open_bracket=break_after_open_bracket) - - def _prevent_default_initializer_splitting(self, item, indent_amt): - """Prevent splitting between a default initializer. - - When there is a default initializer, it's best to keep it all on - the same line. It's nicer and more readable, even if it goes - over the maximum allowable line length. This goes back along the - current line to determine if we have a default initializer, and, - if so, to remove extraneous whitespaces and add a line - break/indent before it if needed. - - """ - if unicode(item) == '=': - # This is the assignment in the initializer. Just remove spaces for - # now. - self._delete_whitespace() - return - - if (not self._prev_item or not self._prev_prev_item or - unicode(self._prev_item) != '='): - return - - self._delete_whitespace() - prev_prev_index = self._lines.index(self._prev_prev_item) - - if ( - isinstance(self._lines[prev_prev_index - 1], self._Indent) or - self.fits_on_current_line(item.size + 1) - ): - # The default initializer is already the only item on this line. - # Don't insert a newline here. - return - - # Replace the space with a newline/indent combo. - if isinstance(self._lines[prev_prev_index - 1], self._Space): - del self._lines[prev_prev_index - 1] - - self.add_line_break_at(self._lines.index(self._prev_prev_item), - indent_amt) - - def _split_after_delimiter(self, item, indent_amt): - """Split the line only after a delimiter.""" - self._delete_whitespace() - - if self.fits_on_current_line(item.size): - return - - last_space = None - for current_item in reversed(self._lines): - if ( - last_space and - (not isinstance(current_item, Atom) or - not current_item.is_colon) - ): - break - else: - last_space = None - if isinstance(current_item, self._Space): - last_space = current_item - if isinstance(current_item, (self._LineBreak, self._Indent)): - return - - if not last_space: - return - - self.add_line_break_at(self._lines.index(last_space), indent_amt) - - def _enforce_space(self, item): - """Enforce a space in certain situations. - - There are cases where we will want a space where normally we - wouldn't put one. This just enforces the addition of a space. - - """ - if isinstance(self._lines[-1], - (self._Space, self._LineBreak, self._Indent)): - return - - if not self._prev_item: - return - - item_text = unicode(item) - prev_text = unicode(self._prev_item) - - # Prefer a space around a '.' in an import statement, and between the - # 'import' and '('. - if ( - (item_text == '.' and prev_text == 'from') or - (item_text == 'import' and prev_text == '.') or - (item_text == '(' and prev_text == 'import') - ): - self._lines.append(self._Space()) - - def _delete_whitespace(self): - """Delete all whitespace from the end of the line.""" - while isinstance(self._lines[-1], (self._Space, self._LineBreak, - self._Indent)): - del self._lines[-1] - - -class Atom(object): - - """The smallest unbreakable unit that can be reflowed.""" - - def __init__(self, atom): - self._atom = atom - - def __repr__(self): - return self._atom.token_string - - def __len__(self): - return self.size - - def reflow( - self, reflowed_lines, continued_indent, extent, - break_after_open_bracket=False, - is_list_comp_or_if_expr=False, - next_is_dot=False - ): - if self._atom.token_type == tokenize.COMMENT: - reflowed_lines.add_comment(self) - return - - total_size = extent if extent else self.size - - if self._atom.token_string not in ',:([{}])': - # Some atoms will need an extra 1-sized space token after them. - total_size += 1 - - prev_item = reflowed_lines.previous_item() - if ( - not is_list_comp_or_if_expr and - not reflowed_lines.fits_on_current_line(total_size) and - not (next_is_dot and - reflowed_lines.fits_on_current_line(self.size + 1)) and - not reflowed_lines.line_empty() and - not self.is_colon and - not (prev_item and prev_item.is_name and - unicode(self) == '(') - ): - # Start a new line if there is already something on the line and - # adding this atom would make it go over the max line length. - reflowed_lines.add_line_break(continued_indent) - else: - reflowed_lines.add_space_if_needed(unicode(self)) - - reflowed_lines.add(self, len(continued_indent), - break_after_open_bracket) - - def emit(self): - return self.__repr__() - - @property - def is_keyword(self): - return keyword.iskeyword(self._atom.token_string) - - @property - def is_string(self): - return self._atom.token_type == tokenize.STRING - - @property - def is_name(self): - return self._atom.token_type == tokenize.NAME - - @property - def is_number(self): - return self._atom.token_type == tokenize.NUMBER - - @property - def is_comma(self): - return self._atom.token_string == ',' - - @property - def is_colon(self): - return self._atom.token_string == ':' - - @property - def size(self): - return len(self._atom.token_string) - - -class Container(object): - - """Base class for all container types.""" - - def __init__(self, items): - self._items = items - - def __repr__(self): - string = '' - last_was_keyword = False - - for item in self._items: - if item.is_comma: - string += ', ' - elif item.is_colon: - string += ': ' - else: - item_string = unicode(item) - if ( - string and - (last_was_keyword or - (not string.endswith(tuple('([{,.:}]) ')) and - not item_string.startswith(tuple('([{,.:}])')))) - ): - string += ' ' - string += item_string - - last_was_keyword = item.is_keyword - return string - - def __iter__(self): - for element in self._items: - yield element - - def __getitem__(self, idx): - return self._items[idx] - - def reflow(self, reflowed_lines, continued_indent, - break_after_open_bracket=False): - last_was_container = False - for (index, item) in enumerate(self._items): - next_item = get_item(self._items, index + 1) - - if isinstance(item, Atom): - is_list_comp_or_if_expr = ( - isinstance(self, (ListComprehension, IfExpression))) - item.reflow(reflowed_lines, continued_indent, - self._get_extent(index), - is_list_comp_or_if_expr=is_list_comp_or_if_expr, - next_is_dot=(next_item and - unicode(next_item) == '.')) - if last_was_container and item.is_comma: - reflowed_lines.add_line_break(continued_indent) - last_was_container = False - else: # isinstance(item, Container) - reflowed_lines.add(item, len(continued_indent), - break_after_open_bracket) - last_was_container = not isinstance(item, (ListComprehension, - IfExpression)) - - if ( - break_after_open_bracket and index == 0 and - # Prefer to keep empty containers together instead of - # separating them. - unicode(item) == self.open_bracket and - (not next_item or unicode(next_item) != self.close_bracket) and - (len(self._items) != 3 or not isinstance(next_item, Atom)) - ): - reflowed_lines.add_line_break(continued_indent) - break_after_open_bracket = False - else: - next_next_item = get_item(self._items, index + 2) - if ( - unicode(item) not in ['.', '%', 'in'] and - next_item and not isinstance(next_item, Container) and - unicode(next_item) != ':' and - next_next_item and (not isinstance(next_next_item, Atom) or - unicode(next_item) == 'not') and - not reflowed_lines.line_empty() and - not reflowed_lines.fits_on_current_line( - self._get_extent(index + 1) + 2) - ): - reflowed_lines.add_line_break(continued_indent) - - def _get_extent(self, index): - """The extent of the full element. - - E.g., the length of a function call or keyword. - - """ - extent = 0 - prev_item = get_item(self._items, index - 1) - seen_dot = prev_item and unicode(prev_item) == '.' - while index < len(self._items): - item = get_item(self._items, index) - index += 1 - - if isinstance(item, (ListComprehension, IfExpression)): - break - - if isinstance(item, Container): - if prev_item and prev_item.is_name: - if seen_dot: - extent += 1 - else: - extent += item.size - - prev_item = item - continue - elif (unicode(item) not in ['.', '=', ':', 'not'] and - not item.is_name and not item.is_string): - break - - if unicode(item) == '.': - seen_dot = True - - extent += item.size - prev_item = item - - return extent - - @property - def is_string(self): - return False - - @property - def size(self): - return len(self.__repr__()) - - @property - def is_keyword(self): - return False - - @property - def is_name(self): - return False - - @property - def is_comma(self): - return False - - @property - def is_colon(self): - return False - - @property - def open_bracket(self): - return None - - @property - def close_bracket(self): - return None - - -class Tuple(Container): - - """A high-level representation of a tuple.""" - - @property - def open_bracket(self): - return '(' - - @property - def close_bracket(self): - return ')' - - -class List(Container): - - """A high-level representation of a list.""" - - @property - def open_bracket(self): - return '[' - - @property - def close_bracket(self): - return ']' - - -class DictOrSet(Container): - - """A high-level representation of a dictionary or set.""" - - @property - def open_bracket(self): - return '{' - - @property - def close_bracket(self): - return '}' - - -class ListComprehension(Container): - - """A high-level representation of a list comprehension.""" - - @property - def size(self): - length = 0 - for item in self._items: - if isinstance(item, IfExpression): - break - length += item.size - return length - - -class IfExpression(Container): - - """A high-level representation of an if-expression.""" - - -def _parse_container(tokens, index, for_or_if=None): - """Parse a high-level container, such as a list, tuple, etc.""" - - # Store the opening bracket. - items = [Atom(Token(*tokens[index]))] - index += 1 - - num_tokens = len(tokens) - while index < num_tokens: - tok = Token(*tokens[index]) - - if tok.token_string in ',)]}': - # First check if we're at the end of a list comprehension or - # if-expression. Don't add the ending token as part of the list - # comprehension or if-expression, because they aren't part of those - # constructs. - if for_or_if == 'for': - return (ListComprehension(items), index - 1) - - elif for_or_if == 'if': - return (IfExpression(items), index - 1) - - # We've reached the end of a container. - items.append(Atom(tok)) - - # If not, then we are at the end of a container. - if tok.token_string == ')': - # The end of a tuple. - return (Tuple(items), index) - - elif tok.token_string == ']': - # The end of a list. - return (List(items), index) - - elif tok.token_string == '}': - # The end of a dictionary or set. - return (DictOrSet(items), index) - - elif tok.token_string in '([{': - # A sub-container is being defined. - (container, index) = _parse_container(tokens, index) - items.append(container) - - elif tok.token_string == 'for': - (container, index) = _parse_container(tokens, index, 'for') - items.append(container) - - elif tok.token_string == 'if': - (container, index) = _parse_container(tokens, index, 'if') - items.append(container) - - else: - items.append(Atom(tok)) - - index += 1 - - return (None, None) - - -def _parse_tokens(tokens): - """Parse the tokens. - - This converts the tokens into a form where we can manipulate them - more easily. - - """ - - index = 0 - parsed_tokens = [] - - num_tokens = len(tokens) - while index < num_tokens: - tok = Token(*tokens[index]) - - assert tok.token_type != token.INDENT - if tok.token_type == tokenize.NEWLINE: - # There's only one newline and it's at the end. - break - - if tok.token_string in '([{': - (container, index) = _parse_container(tokens, index) - if not container: - return None - parsed_tokens.append(container) - else: - parsed_tokens.append(Atom(tok)) - - index += 1 - - return parsed_tokens - - -def _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line): - """Reflow the lines so that it looks nice.""" - - if unicode(parsed_tokens[0]) == 'def': - # A function definition gets indented a bit more. - continued_indent = indentation + ' ' * 2 * DEFAULT_INDENT_SIZE - else: - continued_indent = indentation + ' ' * DEFAULT_INDENT_SIZE - - break_after_open_bracket = not start_on_prefix_line - - lines = ReformattedLines(max_line_length) - lines.add_indent(len(indentation.lstrip('\r\n'))) - - if not start_on_prefix_line: - # If splitting after the opening bracket will cause the first element - # to be aligned weirdly, don't try it. - first_token = get_item(parsed_tokens, 0) - second_token = get_item(parsed_tokens, 1) - - if ( - first_token and second_token and - unicode(second_token)[0] == '(' and - len(indentation) + len(first_token) + 1 == len(continued_indent) - ): - return None - - for item in parsed_tokens: - lines.add_space_if_needed(unicode(item), equal=True) - - save_continued_indent = continued_indent - if start_on_prefix_line and isinstance(item, Container): - start_on_prefix_line = False - continued_indent = ' ' * (lines.current_size() + 1) - - item.reflow(lines, continued_indent, break_after_open_bracket) - continued_indent = save_continued_indent - - return lines.emit() - - -def _shorten_line_at_tokens_new(tokens, source, indentation, - max_line_length): - """Shorten the line taking its length into account. - - The input is expected to be free of newlines except for inside - multiline strings and at the end. - - """ - # Yield the original source so to see if it's a better choice than the - # shortened candidate lines we generate here. - yield indentation + source - - parsed_tokens = _parse_tokens(tokens) - - if parsed_tokens: - # Perform two reflows. The first one starts on the same line as the - # prefix. The second starts on the line after the prefix. - fixed = _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line=True) - if fixed and check_syntax(normalize_multiline(fixed.lstrip())): - yield fixed - - fixed = _reflow_lines(parsed_tokens, indentation, max_line_length, - start_on_prefix_line=False) - if fixed and check_syntax(normalize_multiline(fixed.lstrip())): - yield fixed - - -def _shorten_line_at_tokens(tokens, source, indentation, indent_word, - key_token_strings, aggressive): - """Separate line by breaking at tokens in key_token_strings. - - The input is expected to be free of newlines except for inside - multiline strings and at the end. - - """ - offsets = [] - for (index, _t) in enumerate(token_offsets(tokens)): - (token_type, - token_string, - start_offset, - end_offset) = _t - - assert token_type != token.INDENT - - if token_string in key_token_strings: - # Do not break in containers with zero or one items. - unwanted_next_token = { - '(': ')', - '[': ']', - '{': '}'}.get(token_string) - if unwanted_next_token: - if ( - get_item(tokens, - index + 1, - default=[None, None])[1] == unwanted_next_token or - get_item(tokens, - index + 2, - default=[None, None])[1] == unwanted_next_token - ): - continue - - if ( - index > 2 and token_string == '(' and - tokens[index - 1][1] in ',(%[' - ): - # Don't split after a tuple start, or before a tuple start if - # the tuple is in a list. - continue - - if end_offset < len(source) - 1: - # Don't split right before newline. - offsets.append(end_offset) - else: - # Break at adjacent strings. These were probably meant to be on - # separate lines in the first place. - previous_token = get_item(tokens, index - 1) - if ( - token_type == tokenize.STRING and - previous_token and previous_token[0] == tokenize.STRING - ): - offsets.append(start_offset) - - current_indent = None - fixed = None - for line in split_at_offsets(source, offsets): - if fixed: - fixed += '\n' + current_indent + line - - for symbol in '([{': - if line.endswith(symbol): - current_indent += indent_word - else: - # First line. - fixed = line - assert not current_indent - current_indent = indent_word - - assert fixed is not None - - if check_syntax(normalize_multiline(fixed) - if aggressive > 1 else fixed): - return indentation + fixed - - return None - - -def token_offsets(tokens): - """Yield tokens and offsets.""" - end_offset = 0 - previous_end_row = 0 - previous_end_column = 0 - for t in tokens: - token_type = t[0] - token_string = t[1] - (start_row, start_column) = t[2] - (end_row, end_column) = t[3] - - # Account for the whitespace between tokens. - end_offset += start_column - if previous_end_row == start_row: - end_offset -= previous_end_column - - # Record the start offset of the token. - start_offset = end_offset - - # Account for the length of the token itself. - end_offset += len(token_string) - - yield (token_type, - token_string, - start_offset, - end_offset) - - previous_end_row = end_row - previous_end_column = end_column - - -def normalize_multiline(line): - """Normalize multiline-related code that will cause syntax error. - - This is for purposes of checking syntax. - - """ - if line.startswith('def ') and line.rstrip().endswith(':'): - return line + ' pass' - elif line.startswith('return '): - return 'def _(): ' + line - elif line.startswith('@'): - return line + 'def _(): pass' - elif line.startswith('class '): - return line + ' pass' - elif line.startswith(('if ', 'elif ', 'for ', 'while ')): - return line + ' pass' - - return line - - -def fix_whitespace(line, offset, replacement): - """Replace whitespace at offset and return fixed line.""" - # Replace escaped newlines too - left = line[:offset].rstrip('\n\r \t\\') - right = line[offset:].lstrip('\n\r \t\\') - if right.startswith('#'): - return line - - return left + replacement + right - - -def _execute_pep8(pep8_options, source): - """Execute pycodestyle via python method calls.""" - class QuietReport(pycodestyle.BaseReport): - - """Version of checker that does not print.""" - - def __init__(self, options): - super(QuietReport, self).__init__(options) - self.__full_error_results = [] - - def error(self, line_number, offset, text, check): - """Collect errors.""" - code = super(QuietReport, self).error(line_number, - offset, - text, - check) - if code: - self.__full_error_results.append( - {'id': code, - 'line': line_number, - 'column': offset + 1, - 'info': text}) - - def full_error_results(self): - """Return error results in detail. - - Results are in the form of a list of dictionaries. Each - dictionary contains 'id', 'line', 'column', and 'info'. - - """ - return self.__full_error_results - - checker = pycodestyle.Checker('', lines=source, reporter=QuietReport, - **pep8_options) - checker.check_all() - return checker.report.full_error_results() - - -def _remove_leading_and_normalize(line): - return line.lstrip().rstrip(CR + LF) + '\n' - - -class Reindenter(object): - - """Reindents badly-indented code to uniformly use four-space indentation. - - Released to the public domain, by Tim Peters, 03 October 2000. - - """ - - def __init__(self, input_text): - sio = io.StringIO(input_text) - source_lines = sio.readlines() - - self.string_content_line_numbers = multiline_string_lines(input_text) - - # File lines, rstripped & tab-expanded. Dummy at start is so - # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it is a newline. - self.lines = [] - for line_number, line in enumerate(source_lines, start=1): - # Do not modify if inside a multiline string. - if line_number in self.string_content_line_numbers: - self.lines.append(line) - else: - # Only expand leading tabs. - self.lines.append(_get_indentation(line).expandtabs() + - _remove_leading_and_normalize(line)) - - self.lines.insert(0, None) - self.index = 1 # index into self.lines of next line - self.input_text = input_text - - def run(self, indent_size=DEFAULT_INDENT_SIZE): - """Fix indentation and return modified line numbers. - - Line numbers are indexed at 1. - - """ - if indent_size < 1: - return self.input_text - - try: - stats = _reindent_stats(tokenize.generate_tokens(self.getline)) - except (SyntaxError, tokenize.TokenError): - return self.input_text - # Remove trailing empty lines. - lines = self.lines - # Sentinel. - stats.append((len(lines), 0)) - # Map count of leading spaces to # we want. - have2want = {} - # Program after transformation. - after = [] - # Copy over initial empty lines -- there's nothing to do until - # we see a line with *something* on it. - i = stats[0][0] - after.extend(lines[1:i]) - for i in range(len(stats) - 1): - thisstmt, thislevel = stats[i] - nextstmt = stats[i + 1][0] - have = _leading_space_count(lines[thisstmt]) - want = thislevel * indent_size - if want < 0: - # A comment line. - if have: - # An indented comment line. If we saw the same - # indentation before, reuse what it most recently - # mapped to. - want = have2want.get(have, -1) - if want < 0: - # Then it probably belongs to the next real stmt. - for j in range(i + 1, len(stats) - 1): - jline, jlevel = stats[j] - if jlevel >= 0: - if have == _leading_space_count(lines[jline]): - want = jlevel * indent_size - break - if want < 0: # Maybe it's a hanging - # comment like this one, - # in which case we should shift it like its base - # line got shifted. - for j in range(i - 1, -1, -1): - jline, jlevel = stats[j] - if jlevel >= 0: - want = (have + _leading_space_count( - after[jline - 1]) - - _leading_space_count(lines[jline])) - break - if want < 0: - # Still no luck -- leave it alone. - want = have - else: - want = 0 - assert want >= 0 - have2want[have] = want - diff = want - have - if diff == 0 or have == 0: - after.extend(lines[thisstmt:nextstmt]) - else: - for line_number, line in enumerate(lines[thisstmt:nextstmt], - start=thisstmt): - if line_number in self.string_content_line_numbers: - after.append(line) - elif diff > 0: - if line == '\n': - after.append(line) - else: - after.append(' ' * diff + line) - else: - remove = min(_leading_space_count(line), -diff) - after.append(line[remove:]) - - return ''.join(after) - - def getline(self): - """Line-getter for tokenize.""" - if self.index >= len(self.lines): - line = '' - else: - line = self.lines[self.index] - self.index += 1 - return line - - -def _reindent_stats(tokens): - """Return list of (lineno, indentlevel) pairs. - - One for each stmt and comment line. indentlevel is -1 for comment - lines, as a signal that tokenize doesn't know what to do about them; - indeed, they're our headache! - - """ - find_stmt = 1 # Next token begins a fresh stmt? - level = 0 # Current indent level. - stats = [] - - for t in tokens: - token_type = t[0] - sline = t[2][0] - line = t[4] - - if token_type == tokenize.NEWLINE: - # A program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - find_stmt = 1 - - elif token_type == tokenize.INDENT: - find_stmt = 1 - level += 1 - - elif token_type == tokenize.DEDENT: - find_stmt = 1 - level -= 1 - - elif token_type == tokenize.COMMENT: - if find_stmt: - stats.append((sline, -1)) - # But we're still looking for a new stmt, so leave - # find_stmt alone. - - elif token_type == tokenize.NL: - pass - - elif find_stmt: - # This is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER. - find_stmt = 0 - if line: # Not endmarker. - stats.append((sline, level)) - - return stats - - -def _leading_space_count(line): - """Return number of leading spaces in line.""" - i = 0 - while i < len(line) and line[i] == ' ': - i += 1 - return i - - -def refactor_with_2to3(source_text, fixer_names, filename=''): - """Use lib2to3 to refactor the source. - - Return the refactored source code. - - """ - from lib2to3.refactor import RefactoringTool - fixers = ['lib2to3.fixes.fix_' + name for name in fixer_names] - tool = RefactoringTool(fixer_names=fixers, explicit=fixers) - - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - try: - # The name parameter is necessary particularly for the "import" fixer. - return unicode(tool.refactor_string(source_text, name=filename)) - except lib2to3_tokenize.TokenError: - return source_text - - -def check_syntax(code): - """Return True if syntax is okay.""" - try: - return compile(code, '', 'exec') - except (SyntaxError, TypeError, UnicodeDecodeError): - return False - - -def filter_results(source, results, aggressive): - """Filter out spurious reports from pycodestyle. - - If aggressive is True, we allow possibly unsafe fixes (E711, E712). - - """ - non_docstring_string_line_numbers = multiline_string_lines( - source, include_docstrings=False) - all_string_line_numbers = multiline_string_lines( - source, include_docstrings=True) - - commented_out_code_line_numbers = commented_out_code_lines(source) - - has_e901 = any(result['id'].lower() == 'e901' for result in results) - - for r in results: - issue_id = r['id'].lower() - - if r['line'] in non_docstring_string_line_numbers: - if issue_id.startswith(('e1', 'e501', 'w191')): - continue - - if r['line'] in all_string_line_numbers: - if issue_id in ['e501']: - continue - - # We must offset by 1 for lines that contain the trailing contents of - # multiline strings. - if not aggressive and (r['line'] + 1) in all_string_line_numbers: - # Do not modify multiline strings in non-aggressive mode. Remove - # trailing whitespace could break doctests. - if issue_id.startswith(('w29', 'w39')): - continue - - if aggressive <= 0: - if issue_id.startswith(('e711', 'e72', 'w6')): - continue - - if aggressive <= 1: - if issue_id.startswith(('e712', 'e713', 'e714', 'w5')): - continue - - if aggressive <= 2: - if issue_id.startswith(('e704', 'w5')): - continue - - if r['line'] in commented_out_code_line_numbers: - if issue_id.startswith(('e26', 'e501')): - continue - - # Do not touch indentation if there is a token error caused by - # incomplete multi-line statement. Otherwise, we risk screwing up the - # indentation. - if has_e901: - if issue_id.startswith(('e1', 'e7')): - continue - - yield r - - -def multiline_string_lines(source, include_docstrings=False): - """Return line numbers that are within multiline strings. - - The line numbers are indexed at 1. - - Docstrings are ignored. - - """ - line_numbers = set() - previous_token_type = '' - try: - for t in generate_tokens(source): - token_type = t[0] - start_row = t[2][0] - end_row = t[3][0] - - if token_type == tokenize.STRING and start_row != end_row: - if ( - include_docstrings or - previous_token_type != tokenize.INDENT - ): - # We increment by one since we want the contents of the - # string. - line_numbers |= set(range(1 + start_row, 1 + end_row)) - - previous_token_type = token_type - except (SyntaxError, tokenize.TokenError): - pass - - return line_numbers - - -def commented_out_code_lines(source): - """Return line numbers of comments that are likely code. - - Commented-out code is bad practice, but modifying it just adds even - more clutter. - - """ - line_numbers = [] - try: - for t in generate_tokens(source): - token_type = t[0] - token_string = t[1] - start_row = t[2][0] - line = t[4] - - # Ignore inline comments. - if not line.lstrip().startswith('#'): - continue - - if token_type == tokenize.COMMENT: - stripped_line = token_string.lstrip('#').strip() - if ( - ' ' in stripped_line and - '#' not in stripped_line and - check_syntax(stripped_line) - ): - line_numbers.append(start_row) - except (SyntaxError, tokenize.TokenError): - pass - - return line_numbers - - -def shorten_comment(line, max_line_length, last_comment=False): - """Return trimmed or split long comment line. - - If there are no comments immediately following it, do a text wrap. - Doing this wrapping on all comments in general would lead to jagged - comment text. - - """ - assert len(line) > max_line_length - line = line.rstrip() - - # PEP 8 recommends 72 characters for comment text. - indentation = _get_indentation(line) + '# ' - max_line_length = min(max_line_length, - len(indentation) + 72) - - MIN_CHARACTER_REPEAT = 5 - if ( - len(line) - len(line.rstrip(line[-1])) >= MIN_CHARACTER_REPEAT and - not line[-1].isalnum() - ): - # Trim comments that end with things like --------- - return line[:max_line_length] + '\n' - elif last_comment and re.match(r'\s*#+\s*\w+', line): - split_lines = textwrap.wrap(line.lstrip(' \t#'), - initial_indent=indentation, - subsequent_indent=indentation, - width=max_line_length, - break_long_words=False, - break_on_hyphens=False) - return '\n'.join(split_lines) + '\n' - - return line + '\n' - - -def normalize_line_endings(lines, newline): - """Return fixed line endings. - - All lines will be modified to use the most common line ending. - - """ - return [line.rstrip('\n\r') + newline for line in lines] - - -def mutual_startswith(a, b): - return b.startswith(a) or a.startswith(b) - - -def code_match(code, select, ignore): - if ignore: - assert not isinstance(ignore, unicode) - for ignored_code in [c.strip() for c in ignore]: - if mutual_startswith(code.lower(), ignored_code.lower()): - return False - - if select: - assert not isinstance(select, unicode) - for selected_code in [c.strip() for c in select]: - if mutual_startswith(code.lower(), selected_code.lower()): - return True - return False - - return True - - -def fix_code(source, options=None, encoding=None, apply_config=False): - """Return fixed source code. - - "encoding" will be used to decode "source" if it is a byte string. - - """ - options = _get_options(options, apply_config) - - if not isinstance(source, unicode): - source = source.decode(encoding or get_encoding()) - - sio = io.StringIO(source) - return fix_lines(sio.readlines(), options=options) - - -def _get_options(raw_options, apply_config): - """Return parsed options.""" - if not raw_options: - return parse_args([''], apply_config=apply_config) - - if isinstance(raw_options, dict): - options = parse_args([''], apply_config=apply_config) - for name, value in raw_options.items(): - if not hasattr(options, name): - raise ValueError("No such option '{}'".format(name)) - - # Check for very basic type errors. - expected_type = type(getattr(options, name)) - if not isinstance(expected_type, (str, unicode)): - if isinstance(value, (str, unicode)): - raise ValueError( - "Option '{}' should not be a string".format(name)) - setattr(options, name, value) - else: - options = raw_options - - return options - - -def fix_lines(source_lines, options, filename=''): - """Return fixed source code.""" - # Transform everything to line feed. Then change them back to original - # before returning fixed source code. - original_newline = find_newline(source_lines) - tmp_source = ''.join(normalize_line_endings(source_lines, '\n')) - - # Keep a history to break out of cycles. - previous_hashes = set() - - if options.line_range: - # Disable "apply_local_fixes()" for now due to issue #175. - fixed_source = tmp_source - else: - # Apply global fixes only once (for efficiency). - fixed_source = apply_global_fixes(tmp_source, - options, - filename=filename) - - passes = 0 - long_line_ignore_cache = set() - while hash(fixed_source) not in previous_hashes: - if options.pep8_passes >= 0 and passes > options.pep8_passes: - break - passes += 1 - - previous_hashes.add(hash(fixed_source)) - - tmp_source = copy.copy(fixed_source) - - fix = FixPEP8( - filename, - options, - contents=tmp_source, - long_line_ignore_cache=long_line_ignore_cache) - - fixed_source = fix.fix() - - sio = io.StringIO(fixed_source) - return ''.join(normalize_line_endings(sio.readlines(), original_newline)) - - -def fix_file(filename, options=None, output=None, apply_config=False): - if not options: - options = parse_args([filename], apply_config=apply_config) - - original_source = readlines_from_file(filename) - - fixed_source = original_source - - if options.in_place or output: - encoding = detect_encoding(filename) - - if output: - output = LineEndingWrapper(wrap_output(output, encoding=encoding)) - - fixed_source = fix_lines(fixed_source, options, filename=filename) - - if options.diff: - new = io.StringIO(fixed_source) - new = new.readlines() - diff = get_diff_text(original_source, new, filename) - if output: - output.write(diff) - output.flush() - else: - return diff - elif options.in_place: - fp = open_with_encoding(filename, encoding=encoding, mode='w') - fp.write(fixed_source) - fp.close() - else: - if output: - output.write(fixed_source) - output.flush() - else: - return fixed_source - - -def global_fixes(): - """Yield multiple (code, function) tuples.""" - for function in list(globals().values()): - if inspect.isfunction(function): - arguments = _get_parameters(function) - if arguments[:1] != ['source']: - continue - - code = extract_code_from_function(function) - if code: - yield (code, function) - - -def _get_parameters(function): - # pylint: disable=deprecated-method - if sys.version_info >= (3, 3): - # We need to match "getargspec()", which includes "self" as the first - # value for methods. - # https://bugs.python.org/issue17481#msg209469 - if inspect.ismethod(function): - function = function.__func__ - - return list(inspect.signature(function).parameters) - else: - return inspect.getargspec(function)[0] - - -def apply_global_fixes(source, options, where='global', filename=''): - """Run global fixes on source code. - - These are fixes that only need be done once (unlike those in - FixPEP8, which are dependent on pycodestyle). - - """ - if any(code_match(code, select=options.select, ignore=options.ignore) - for code in ['E101', 'E111']): - source = reindent(source, - indent_size=options.indent_size) - - for (code, function) in global_fixes(): - if code_match(code, select=options.select, ignore=options.ignore): - if options.verbose: - print('---> Applying {0} fix for {1}'.format(where, - code.upper()), - file=sys.stderr) - source = function(source, - aggressive=options.aggressive) - - source = fix_2to3(source, - aggressive=options.aggressive, - select=options.select, - ignore=options.ignore, - filename=filename) - - return source - - -def extract_code_from_function(function): - """Return code handled by function.""" - if not function.__name__.startswith('fix_'): - return None - - code = re.sub('^fix_', '', function.__name__) - if not code: - return None - - try: - int(code[1:]) - except ValueError: - return None - - return code - - -def _get_package_version(): - packages = ["pycodestyle: {0}".format(pycodestyle.__version__)] - return ", ".join(packages) - - -def create_parser(): - """Return command-line parser.""" - # Do import locally to be friendly to those who use autopep8 as a library - # and are supporting Python 2.6. - import argparse - - parser = argparse.ArgumentParser(description=docstring_summary(__doc__), - prog='autopep8') - parser.add_argument('--version', action='version', - version='%(prog)s {0} ({1})'.format( - __version__, _get_package_version())) - parser.add_argument('-v', '--verbose', action='count', - default=0, - help='print verbose messages; ' - 'multiple -v result in more verbose messages') - parser.add_argument('-d', '--diff', action='store_true', - help='print the diff for the fixed source') - parser.add_argument('-i', '--in-place', action='store_true', - help='make changes to files in place') - parser.add_argument('--global-config', metavar='filename', - default=DEFAULT_CONFIG, - help='path to a global pep8 config file; if this file ' - 'does not exist then this is ignored ' - '(default: {0})'.format(DEFAULT_CONFIG)) - parser.add_argument('--ignore-local-config', action='store_true', - help="don't look for and apply local config files; " - 'if not passed, defaults are updated with any ' - "config files in the project's root directory") - parser.add_argument('-r', '--recursive', action='store_true', - help='run recursively over directories; ' - 'must be used with --in-place or --diff') - parser.add_argument('-j', '--jobs', type=int, metavar='n', default=1, - help='number of parallel jobs; ' - 'match CPU count if value is less than 1') - parser.add_argument('-p', '--pep8-passes', metavar='n', - default=-1, type=int, - help='maximum number of additional pep8 passes ' - '(default: infinite)') - parser.add_argument('-a', '--aggressive', action='count', default=0, - help='enable non-whitespace changes; ' - 'multiple -a result in more aggressive changes') - parser.add_argument('--experimental', action='store_true', - help='enable experimental fixes') - parser.add_argument('--exclude', metavar='globs', - help='exclude file/directory names that match these ' - 'comma-separated globs') - parser.add_argument('--list-fixes', action='store_true', - help='list codes for fixes; ' - 'used by --ignore and --select') - parser.add_argument('--ignore', metavar='errors', default='', - help='do not fix these errors/warnings ' - '(default: {0})'.format(DEFAULT_IGNORE)) - parser.add_argument('--select', metavar='errors', default='', - help='fix only these errors/warnings (e.g. E4,W)') - parser.add_argument('--max-line-length', metavar='n', default=79, type=int, - help='set maximum allowed line length ' - '(default: %(default)s)') - parser.add_argument('--line-range', '--range', metavar='line', - default=None, type=int, nargs=2, - help='only fix errors found within this inclusive ' - 'range of line numbers (e.g. 1 99); ' - 'line numbers are indexed at 1') - parser.add_argument('--indent-size', default=DEFAULT_INDENT_SIZE, - type=int, help=argparse.SUPPRESS) - parser.add_argument('files', nargs='*', - help="files to format or '-' for standard in") - - return parser - - -def parse_args(arguments, apply_config=False): - """Parse command-line options.""" - parser = create_parser() - args = parser.parse_args(arguments) - - if not args.files and not args.list_fixes: - parser.error('incorrect number of arguments') - - args.files = [decode_filename(name) for name in args.files] - - if apply_config: - parser = read_config(args, parser) - args = parser.parse_args(arguments) - args.files = [decode_filename(name) for name in args.files] - - if '-' in args.files: - if len(args.files) > 1: - parser.error('cannot mix stdin and regular files') - - if args.diff: - parser.error('--diff cannot be used with standard input') - - if args.in_place: - parser.error('--in-place cannot be used with standard input') - - if args.recursive: - parser.error('--recursive cannot be used with standard input') - - if len(args.files) > 1 and not (args.in_place or args.diff): - parser.error('autopep8 only takes one filename as argument ' - 'unless the "--in-place" or "--diff" args are ' - 'used') - - if args.recursive and not (args.in_place or args.diff): - parser.error('--recursive must be used with --in-place or --diff') - - if args.in_place and args.diff: - parser.error('--in-place and --diff are mutually exclusive') - - if args.max_line_length <= 0: - parser.error('--max-line-length must be greater than 0') - - if args.select: - args.select = _split_comma_separated(args.select) - - if args.ignore: - args.ignore = _split_comma_separated(args.ignore) - elif not args.select: - if args.aggressive: - # Enable everything by default if aggressive. - args.select = set(['E', 'W']) - else: - args.ignore = _split_comma_separated(DEFAULT_IGNORE) - - if args.exclude: - args.exclude = _split_comma_separated(args.exclude) - else: - args.exclude = set([]) - - if args.jobs < 1: - # Do not import multiprocessing globally in case it is not supported - # on the platform. - import multiprocessing - args.jobs = multiprocessing.cpu_count() - - if args.jobs > 1 and not args.in_place: - parser.error('parallel jobs requires --in-place') - - if args.line_range: - if args.line_range[0] <= 0: - parser.error('--range must be positive numbers') - if args.line_range[0] > args.line_range[1]: - parser.error('First value of --range should be less than or equal ' - 'to the second') - - return args - - -def read_config(args, parser): - """Read both user configuration and local configuration.""" - try: - from configparser import ConfigParser as SafeConfigParser - from configparser import Error - except ImportError: - from ConfigParser import SafeConfigParser - from ConfigParser import Error - - config = SafeConfigParser() - - try: - config.read(args.global_config) - - if not args.ignore_local_config: - parent = tail = args.files and os.path.abspath( - os.path.commonprefix(args.files)) - while tail: - if config.read([os.path.join(parent, fn) - for fn in PROJECT_CONFIG]): - break - (parent, tail) = os.path.split(parent) - - defaults = dict() - option_list = dict([(o.dest, o.type or type(o.default)) - for o in parser._actions]) - - for section in ['pep8', 'pycodestyle']: - if not config.has_section(section): - continue - for (k, _) in config.items(section): - norm_opt = k.lstrip('-').replace('-', '_') - opt_type = option_list[norm_opt] - if opt_type is int: - value = config.getint(section, k) - elif opt_type is bool: - value = config.getboolean(section, k) - else: - value = config.get(section, k) - defaults[norm_opt] = value - - parser.set_defaults(**defaults) - except Error: - # Ignore for now. - pass - - return parser - - -def _split_comma_separated(string): - """Return a set of strings.""" - return set(text.strip() for text in string.split(',') if text.strip()) - - -def decode_filename(filename): - """Return Unicode filename.""" - if isinstance(filename, unicode): - return filename - - return filename.decode(sys.getfilesystemencoding()) - - -def supported_fixes(): - """Yield pep8 error codes that autopep8 fixes. - - Each item we yield is a tuple of the code followed by its - description. - - """ - yield ('E101', docstring_summary(reindent.__doc__)) - - instance = FixPEP8(filename=None, options=None, contents='') - for attribute in dir(instance): - code = re.match('fix_([ew][0-9][0-9][0-9])', attribute) - if code: - yield ( - code.group(1).upper(), - re.sub(r'\s+', ' ', - docstring_summary(getattr(instance, attribute).__doc__)) - ) - - for (code, function) in sorted(global_fixes()): - yield (code.upper() + (4 - len(code)) * ' ', - re.sub(r'\s+', ' ', docstring_summary(function.__doc__))) - - for code in sorted(CODE_TO_2TO3): - yield (code.upper() + (4 - len(code)) * ' ', - re.sub(r'\s+', ' ', docstring_summary(fix_2to3.__doc__))) - - -def docstring_summary(docstring): - """Return summary of docstring.""" - return docstring.split('\n')[0] if docstring else '' - - -def line_shortening_rank(candidate, indent_word, max_line_length, - experimental=False): - """Return rank of candidate. - - This is for sorting candidates. - - """ - if not candidate.strip(): - return 0 - - rank = 0 - lines = candidate.rstrip().split('\n') - - offset = 0 - if ( - not lines[0].lstrip().startswith('#') and - lines[0].rstrip()[-1] not in '([{' - ): - for (opening, closing) in ('()', '[]', '{}'): - # Don't penalize empty containers that aren't split up. Things like - # this "foo(\n )" aren't particularly good. - opening_loc = lines[0].find(opening) - closing_loc = lines[0].find(closing) - if opening_loc >= 0: - if closing_loc < 0 or closing_loc != opening_loc + 1: - offset = max(offset, 1 + opening_loc) - - current_longest = max(offset + len(x.strip()) for x in lines) - - rank += 4 * max(0, current_longest - max_line_length) - - rank += len(lines) - - # Too much variation in line length is ugly. - rank += 2 * standard_deviation(len(line) for line in lines) - - bad_staring_symbol = { - '(': ')', - '[': ']', - '{': '}'}.get(lines[0][-1]) - - if len(lines) > 1: - if ( - bad_staring_symbol and - lines[1].lstrip().startswith(bad_staring_symbol) - ): - rank += 20 - - for lineno, current_line in enumerate(lines): - current_line = current_line.strip() - - if current_line.startswith('#'): - continue - - for bad_start in ['.', '%', '+', '-', '/']: - if current_line.startswith(bad_start): - rank += 100 - - # Do not tolerate operators on their own line. - if current_line == bad_start: - rank += 1000 - - if ( - current_line.endswith(('.', '%', '+', '-', '/')) and - "': " in current_line - ): - rank += 1000 - - if current_line.endswith(('(', '[', '{', '.')): - # Avoid lonely opening. They result in longer lines. - if len(current_line) <= len(indent_word): - rank += 100 - - # Avoid the ugliness of ", (\n". - if ( - current_line.endswith('(') and - current_line[:-1].rstrip().endswith(',') - ): - rank += 100 - - # Avoid the ugliness of "something[\n" and something[index][\n. - if ( - current_line.endswith('[') and - len(current_line) > 1 and - (current_line[-2].isalnum() or current_line[-2] in ']') - ): - rank += 300 - - # Also avoid the ugliness of "foo.\nbar" - if current_line.endswith('.'): - rank += 100 - - if has_arithmetic_operator(current_line): - rank += 100 - - # Avoid breaking at unary operators. - if re.match(r'.*[(\[{]\s*[\-\+~]$', current_line.rstrip('\\ ')): - rank += 1000 - - if re.match(r'.*lambda\s*\*$', current_line.rstrip('\\ ')): - rank += 1000 - - if current_line.endswith(('%', '(', '[', '{')): - rank -= 20 - - # Try to break list comprehensions at the "for". - if current_line.startswith('for '): - rank -= 50 - - if current_line.endswith('\\'): - # If a line ends in \-newline, it may be part of a - # multiline string. In that case, we would like to know - # how long that line is without the \-newline. If it's - # longer than the maximum, or has comments, then we assume - # that the \-newline is an okay candidate and only - # penalize it a bit. - total_len = len(current_line) - lineno += 1 - while lineno < len(lines): - total_len += len(lines[lineno]) - - if lines[lineno].lstrip().startswith('#'): - total_len = max_line_length - break - - if not lines[lineno].endswith('\\'): - break - - lineno += 1 - - if total_len < max_line_length: - rank += 10 - else: - rank += 100 if experimental else 1 - - # Prefer breaking at commas rather than colon. - if ',' in current_line and current_line.endswith(':'): - rank += 10 - - # Avoid splitting dictionaries between key and value. - if current_line.endswith(':'): - rank += 100 - - rank += 10 * count_unbalanced_brackets(current_line) - - return max(0, rank) - - -def standard_deviation(numbers): - """Return standard devation.""" - numbers = list(numbers) - if not numbers: - return 0 - mean = sum(numbers) / len(numbers) - return (sum((n - mean) ** 2 for n in numbers) / - len(numbers)) ** .5 - - -def has_arithmetic_operator(line): - """Return True if line contains any arithmetic operators.""" - for operator in pycodestyle.ARITHMETIC_OP: - if operator in line: - return True - - return False - - -def count_unbalanced_brackets(line): - """Return number of unmatched open/close brackets.""" - count = 0 - for opening, closing in ['()', '[]', '{}']: - count += abs(line.count(opening) - line.count(closing)) - - return count - - -def split_at_offsets(line, offsets): - """Split line at offsets. - - Return list of strings. - - """ - result = [] - - previous_offset = 0 - current_offset = 0 - for current_offset in sorted(offsets): - if current_offset < len(line) and previous_offset != current_offset: - result.append(line[previous_offset:current_offset].strip()) - previous_offset = current_offset - - result.append(line[current_offset:]) - - return result - - -class LineEndingWrapper(object): - - r"""Replace line endings to work with sys.stdout. - - It seems that sys.stdout expects only '\n' as the line ending, no matter - the platform. Otherwise, we get repeated line endings. - - """ - - def __init__(self, output): - self.__output = output - - def write(self, s): - self.__output.write(s.replace('\r\n', '\n').replace('\r', '\n')) - - def flush(self): - self.__output.flush() - - -def match_file(filename, exclude): - """Return True if file is okay for modifying/recursing.""" - base_name = os.path.basename(filename) - - if base_name.startswith('.'): - return False - - for pattern in exclude: - if fnmatch.fnmatch(base_name, pattern): - return False - if fnmatch.fnmatch(filename, pattern): - return False - - if not os.path.isdir(filename) and not is_python_file(filename): - return False - - return True - - -def find_files(filenames, recursive, exclude): - """Yield filenames.""" - while filenames: - name = filenames.pop(0) - if recursive and os.path.isdir(name): - for root, directories, children in os.walk(name): - filenames += [os.path.join(root, f) for f in children - if match_file(os.path.join(root, f), - exclude)] - directories[:] = [d for d in directories - if match_file(os.path.join(root, d), - exclude)] - else: - yield name - - -def _fix_file(parameters): - """Helper function for optionally running fix_file() in parallel.""" - if parameters[1].verbose: - print('[file:{0}]'.format(parameters[0]), file=sys.stderr) - try: - fix_file(*parameters) - except IOError as error: - print(unicode(error), file=sys.stderr) - - -def fix_multiple_files(filenames, options, output=None): - """Fix list of files. - - Optionally fix files recursively. - - """ - filenames = find_files(filenames, options.recursive, options.exclude) - if options.jobs > 1: - import multiprocessing - pool = multiprocessing.Pool(options.jobs) - pool.map(_fix_file, - [(name, options) for name in filenames]) - else: - for name in filenames: - _fix_file((name, options, output)) - - -def is_python_file(filename): - """Return True if filename is Python file.""" - if filename.endswith('.py'): - return True - - try: - with open_with_encoding( - filename, - limit_byte_check=MAX_PYTHON_FILE_DETECTION_BYTES) as f: - text = f.read(MAX_PYTHON_FILE_DETECTION_BYTES) - if not text: - return False - first_line = text.splitlines()[0] - except (IOError, IndexError): - return False - - if not PYTHON_SHEBANG_REGEX.match(first_line): - return False - - return True - - -def is_probably_part_of_multiline(line): - """Return True if line is likely part of a multiline string. - - When multiline strings are involved, pep8 reports the error as being - at the start of the multiline string, which doesn't work for us. - - """ - return ( - '"""' in line or - "'''" in line or - line.rstrip().endswith('\\') - ) - - -def wrap_output(output, encoding): - """Return output with specified encoding.""" - return codecs.getwriter(encoding)(output.buffer - if hasattr(output, 'buffer') - else output) - - -def get_encoding(): - """Return preferred encoding.""" - return locale.getpreferredencoding() or sys.getdefaultencoding() - - -def main(argv=None, apply_config=True): - """Command-line entry.""" - if argv is None: - argv = sys.argv - - try: - # Exit on broken pipe. - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - except AttributeError: # pragma: no cover - # SIGPIPE is not available on Windows. - pass - - try: - args = parse_args(argv[1:], apply_config=apply_config) - - if args.list_fixes: - for code, description in sorted(supported_fixes()): - print('{code} - {description}'.format( - code=code, description=description)) - return 0 - - if args.files == ['-']: - assert not args.in_place - - encoding = sys.stdin.encoding or get_encoding() - - # LineEndingWrapper is unnecessary here due to the symmetry between - # standard in and standard out. - wrap_output(sys.stdout, encoding=encoding).write( - fix_code(sys.stdin.read(), args, encoding=encoding)) - else: - if args.in_place or args.diff: - args.files = list(set(args.files)) - else: - assert len(args.files) == 1 - assert not args.recursive - - fix_multiple_files(args.files, args, sys.stdout) - except KeyboardInterrupt: - return 1 # pragma: no cover - - -class CachedTokenizer(object): - - """A one-element cache around tokenize.generate_tokens(). - - Original code written by Ned Batchelder, in coverage.py. - - """ - - def __init__(self): - self.last_text = None - self.last_tokens = None - - def generate_tokens(self, text): - """A stand-in for tokenize.generate_tokens().""" - if text != self.last_text: - string_io = io.StringIO(text) - self.last_tokens = list( - tokenize.generate_tokens(string_io.readline) - ) - self.last_text = text - return self.last_tokens - - -_cached_tokenizer = CachedTokenizer() -generate_tokens = _cached_tokenizer.generate_tokens - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/pymode/autopep8.py b/pymode/autopep8.py new file mode 120000 index 00000000..0a26e017 --- /dev/null +++ b/pymode/autopep8.py @@ -0,0 +1 @@ +../submodules/autopep8/autopep8.py \ No newline at end of file diff --git a/pymode/libs/_markerlib/__init__.py b/pymode/libs/_markerlib/__init__.py new file mode 100644 index 00000000..e2b237b1 --- /dev/null +++ b/pymode/libs/_markerlib/__init__.py @@ -0,0 +1,16 @@ +try: + import ast + from _markerlib.markers import default_environment, compile, interpret +except ImportError: + if 'ast' in globals(): + raise + def default_environment(): + return {} + def compile(marker): + def marker_fn(environment=None, override=None): + # 'empty markers are True' heuristic won't install extra deps. + return not marker.strip() + marker_fn.__doc__ = marker + return marker_fn + def interpret(marker, environment=None, override=None): + return compile(marker)() diff --git a/pymode/libs/_markerlib/markers.py b/pymode/libs/_markerlib/markers.py new file mode 100644 index 00000000..fa837061 --- /dev/null +++ b/pymode/libs/_markerlib/markers.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +"""Interpret PEP 345 environment markers. + +EXPR [in|==|!=|not in] EXPR [or|and] ... + +where EXPR belongs to any of those: + + python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1]) + python_full_version = sys.version.split()[0] + os.name = os.name + sys.platform = sys.platform + platform.version = platform.version() + platform.machine = platform.machine() + platform.python_implementation = platform.python_implementation() + a free string, like '2.6', or 'win32' +""" + +__all__ = ['default_environment', 'compile', 'interpret'] + +import ast +import os +import platform +import sys +import weakref + +_builtin_compile = compile + +try: + from platform import python_implementation +except ImportError: + if os.name == "java": + # Jython 2.5 has ast module, but not platform.python_implementation() function. + def python_implementation(): + return "Jython" + else: + raise + + +# restricted set of variables +_VARS = {'sys.platform': sys.platform, + 'python_version': '%s.%s' % sys.version_info[:2], + # FIXME parsing sys.platform is not reliable, but there is no other + # way to get e.g. 2.7.2+, and the PEP is defined with sys.version + 'python_full_version': sys.version.split(' ', 1)[0], + 'os.name': os.name, + 'platform.version': platform.version(), + 'platform.machine': platform.machine(), + 'platform.python_implementation': python_implementation(), + 'extra': None # wheel extension + } + +for var in list(_VARS.keys()): + if '.' in var: + _VARS[var.replace('.', '_')] = _VARS[var] + +def default_environment(): + """Return copy of default PEP 385 globals dictionary.""" + return dict(_VARS) + +class ASTWhitelist(ast.NodeTransformer): + def __init__(self, statement): + self.statement = statement # for error messages + + ALLOWED = (ast.Compare, ast.BoolOp, ast.Attribute, ast.Name, ast.Load, ast.Str) + # Bool operations + ALLOWED += (ast.And, ast.Or) + # Comparison operations + ALLOWED += (ast.Eq, ast.Gt, ast.GtE, ast.In, ast.Is, ast.IsNot, ast.Lt, ast.LtE, ast.NotEq, ast.NotIn) + + def visit(self, node): + """Ensure statement only contains allowed nodes.""" + if not isinstance(node, self.ALLOWED): + raise SyntaxError('Not allowed in environment markers.\n%s\n%s' % + (self.statement, + (' ' * node.col_offset) + '^')) + return ast.NodeTransformer.visit(self, node) + + def visit_Attribute(self, node): + """Flatten one level of attribute access.""" + new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx) + return ast.copy_location(new_node, node) + +def parse_marker(marker): + tree = ast.parse(marker, mode='eval') + new_tree = ASTWhitelist(marker).generic_visit(tree) + return new_tree + +def compile_marker(parsed_marker): + return _builtin_compile(parsed_marker, '', 'eval', + dont_inherit=True) + +_cache = weakref.WeakValueDictionary() + +def compile(marker): + """Return compiled marker as a function accepting an environment dict.""" + try: + return _cache[marker] + except KeyError: + pass + if not marker.strip(): + def marker_fn(environment=None, override=None): + """""" + return True + else: + compiled_marker = compile_marker(parse_marker(marker)) + def marker_fn(environment=None, override=None): + """override updates environment""" + if override is None: + override = {} + if environment is None: + environment = default_environment() + environment.update(override) + return eval(compiled_marker, environment) + marker_fn.__doc__ = marker + _cache[marker] = marker_fn + return _cache[marker] + +def interpret(marker, environment=None): + return compile(marker)(environment) diff --git a/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth b/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth deleted file mode 100644 index 0b1f79dd..00000000 --- a/pymode/libs/backports.functools_lru_cache-1.3-py3.5-nspkg.pth +++ /dev/null @@ -1 +0,0 @@ -import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('backports', types.ModuleType('backports'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/pymode/libs/backports/configparser/__init__.py b/pymode/libs/backports/configparser/__init__.py deleted file mode 100644 index 06d7a085..00000000 --- a/pymode/libs/backports/configparser/__init__.py +++ /dev/null @@ -1,1390 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""Configuration file parser. - -A configuration file consists of sections, lead by a "[section]" header, -and followed by "name: value" entries, with continuations and such in -the style of RFC 822. - -Intrinsic defaults can be specified by passing them into the -ConfigParser constructor as a dictionary. - -class: - -ConfigParser -- responsible for parsing a list of - configuration files, and managing the parsed database. - - methods: - - __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, - delimiters=('=', ':'), comment_prefixes=('#', ';'), - inline_comment_prefixes=None, strict=True, - empty_lines_in_values=True, default_section='DEFAULT', - interpolation=, converters=): - Create the parser. When `defaults' is given, it is initialized into the - dictionary or intrinsic defaults. The keys must be strings, the values - must be appropriate for %()s string interpolation. - - When `dict_type' is given, it will be used to create the dictionary - objects for the list of sections, for the options within a section, and - for the default values. - - When `delimiters' is given, it will be used as the set of substrings - that divide keys from values. - - When `comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in empty lines. Comments can be - indented. - - When `inline_comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in non-empty lines. - - When `strict` is True, the parser won't allow for any section or option - duplicates while reading from a single source (file, string or - dictionary). Default is True. - - When `empty_lines_in_values' is False (default: True), each empty line - marks the end of an option. Otherwise, internal empty lines of - a multiline option are kept as part of the value. - - When `allow_no_value' is True (default: False), options without - values are accepted; the value presented for these is None. - - sections() - Return all the configuration section names, sans DEFAULT. - - has_section(section) - Return whether the given section exists. - - has_option(section, option) - Return whether the given option exists in the given section. - - options(section) - Return list of configuration options for the named section. - - read(filenames, encoding=None) - Read and parse the list of named configuration files, given by - name. A single filename is also allowed. Non-existing files - are ignored. Return list of successfully read files. - - read_file(f, filename=None) - Read and parse one configuration file, given as a file object. - The filename defaults to f.name; it is only used in error - messages (if f has no `name' attribute, the string `' is used). - - read_string(string) - Read configuration from a given string. - - read_dict(dictionary) - Read configuration from a dictionary. Keys are section names, - values are dictionaries with keys and values that should be present - in the section. If the used dictionary type preserves order, sections - and their keys will be added in order. Values are automatically - converted to strings. - - get(section, option, raw=False, vars=None, fallback=_UNSET) - Return a string value for the named option. All % interpolations are - expanded in the return values, based on the defaults passed into the - constructor and the DEFAULT section. Additional substitutions may be - provided using the `vars' argument, which must be a dictionary whose - contents override any pre-existing defaults. If `option' is a key in - `vars', the value from `vars' is used. - - getint(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to an integer. - - getfloat(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a float. - - getboolean(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a boolean (currently case - insensitively defined as 0, false, no, off for False, and 1, true, - yes, on for True). Returns False or True. - - items(section=_UNSET, raw=False, vars=None) - If section is given, return a list of tuples with (name, value) for - each option in the section. Otherwise, return a list of tuples with - (section_name, section_proxy) for each section, including DEFAULTSECT. - - remove_section(section) - Remove the given file section and all its options. - - remove_option(section, option) - Remove the given option from the given section. - - set(section, option, value) - Set the given option. - - write(fp, space_around_delimiters=True) - Write the configuration state in .ini format. If - `space_around_delimiters' is True (the default), delimiters - between keys and values are surrounded by spaces. -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -from collections import MutableMapping -import functools -import io -import itertools -import re -import sys -import warnings - -from backports.configparser.helpers import OrderedDict as _default_dict -from backports.configparser.helpers import ChainMap as _ChainMap -from backports.configparser.helpers import from_none, open, str, PY2 - -__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError", - "NoOptionError", "InterpolationError", "InterpolationDepthError", - "InterpolationMissingOptionError", "InterpolationSyntaxError", - "ParsingError", "MissingSectionHeaderError", - "ConfigParser", "SafeConfigParser", "RawConfigParser", - "Interpolation", "BasicInterpolation", "ExtendedInterpolation", - "LegacyInterpolation", "SectionProxy", "ConverterMapping", - "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] - -DEFAULTSECT = "DEFAULT" - -MAX_INTERPOLATION_DEPTH = 10 - - -# exception classes -class Error(Exception): - """Base class for ConfigParser exceptions.""" - - def __init__(self, msg=''): - self.message = msg - Exception.__init__(self, msg) - - def __repr__(self): - return self.message - - __str__ = __repr__ - - -class NoSectionError(Error): - """Raised when no section matches a requested option.""" - - def __init__(self, section): - Error.__init__(self, 'No section: %r' % (section,)) - self.section = section - self.args = (section, ) - - -class DuplicateSectionError(Error): - """Raised when a section is repeated in an input source. - - Possible repetitions that raise this exception are: multiple creation - using the API or in strict parsers when a section is found more than once - in a single input file, string or dictionary. - """ - - def __init__(self, section, source=None, lineno=None): - msg = [repr(section), " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": section ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Section ") - Error.__init__(self, "".join(msg)) - self.section = section - self.source = source - self.lineno = lineno - self.args = (section, source, lineno) - - -class DuplicateOptionError(Error): - """Raised by strict parsers when an option is repeated in an input source. - - Current implementation raises this exception only when an option is found - more than once in a single file, string or dictionary. - """ - - def __init__(self, section, option, source=None, lineno=None): - msg = [repr(option), " in section ", repr(section), - " already exists"] - if source is not None: - message = ["While reading from ", repr(source)] - if lineno is not None: - message.append(" [line {0:2d}]".format(lineno)) - message.append(": option ") - message.extend(msg) - msg = message - else: - msg.insert(0, "Option ") - Error.__init__(self, "".join(msg)) - self.section = section - self.option = option - self.source = source - self.lineno = lineno - self.args = (section, option, source, lineno) - - -class NoOptionError(Error): - """A requested option was not found.""" - - def __init__(self, option, section): - Error.__init__(self, "No option %r in section: %r" % - (option, section)) - self.option = option - self.section = section - self.args = (option, section) - - -class InterpolationError(Error): - """Base class for interpolation-related exceptions.""" - - def __init__(self, option, section, msg): - Error.__init__(self, msg) - self.option = option - self.section = section - self.args = (option, section, msg) - - -class InterpolationMissingOptionError(InterpolationError): - """A string substitution required a setting which was not available.""" - - def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution: option {0!r} in section {1!r} contains " - "an interpolation key {2!r} which is not a valid option name. " - "Raw value: {3!r}".format(option, section, reference, rawval)) - InterpolationError.__init__(self, option, section, msg) - self.reference = reference - self.args = (option, section, rawval, reference) - - -class InterpolationSyntaxError(InterpolationError): - """Raised when the source text contains invalid syntax. - - Current implementation raises this exception when the source text into - which substitutions are made does not conform to the required syntax. - """ - - -class InterpolationDepthError(InterpolationError): - """Raised when substitutions are nested too deeply.""" - - def __init__(self, option, section, rawval): - msg = ("Recursion limit exceeded in value substitution: option {0!r} " - "in section {1!r} contains an interpolation key which " - "cannot be substituted in {2} steps. Raw value: {3!r}" - "".format(option, section, MAX_INTERPOLATION_DEPTH, - rawval)) - InterpolationError.__init__(self, option, section, msg) - self.args = (option, section, rawval) - - -class ParsingError(Error): - """Raised when a configuration file does not follow legal syntax.""" - - def __init__(self, source=None, filename=None): - # Exactly one of `source'/`filename' arguments has to be given. - # `filename' kept for compatibility. - if filename and source: - raise ValueError("Cannot specify both `filename' and `source'. " - "Use `source'.") - elif not filename and not source: - raise ValueError("Required argument `source' not given.") - elif filename: - source = filename - Error.__init__(self, 'Source contains parsing errors: %r' % source) - self.source = source - self.errors = [] - self.args = (source, ) - - @property - def filename(self): - """Deprecated, use `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - return self.source - - @filename.setter - def filename(self, value): - """Deprecated, user `source'.""" - warnings.warn( - "The 'filename' attribute will be removed in future versions. " - "Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - self.source = value - - def append(self, lineno, line): - self.errors.append((lineno, line)) - self.message += '\n\t[line %2d]: %s' % (lineno, line) - - -class MissingSectionHeaderError(ParsingError): - """Raised when a key-value pair is found before any section header.""" - - def __init__(self, filename, lineno, line): - Error.__init__( - self, - 'File contains no section headers.\nfile: %r, line: %d\n%r' % - (filename, lineno, line)) - self.source = filename - self.lineno = lineno - self.line = line - self.args = (filename, lineno, line) - - -# Used in parser getters to indicate the default behaviour when a specific -# option is not found it to raise an exception. Created to enable `None' as -# a valid fallback value. -_UNSET = object() - - -class Interpolation(object): - """Dummy interpolation that passes the value through with no changes.""" - - def before_get(self, parser, section, option, value, defaults): - return value - - def before_set(self, parser, section, option, value): - return value - - def before_read(self, parser, section, option, value): - return value - - def before_write(self, parser, section, option, value): - return value - - -class BasicInterpolation(Interpolation): - """Interpolation as implemented in the classic ConfigParser. - - The option values can contain format strings which refer to other values in - the same section, or values in the special default section. - - For example: - - something: %(dir)s/whatever - - would resolve the "%(dir)s" to the value of dir. All reference - expansions are done late, on demand. If a user needs to use a bare % in - a configuration file, she can escape it by writing %%. Other % usage - is considered a user error and raises `InterpolationSyntaxError'.""" - - _KEYCRE = re.compile(r"%\(([^)]+)\)s") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('%%', '') # escaped percent signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '%' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('%'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("%") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "%": - accum.append("%") - rest = rest[2:] - elif c == "(": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - var = parser.optionxform(m.group(1)) - rest = rest[m.end():] - try: - v = map[var] - except KeyError: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, var)) - if "%" in v: - self._interpolate_some(parser, option, accum, v, - section, map, depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'%%' must be followed by '%%' or '(', " - "found: %r" % (rest,)) - - -class ExtendedInterpolation(Interpolation): - """Advanced variant of interpolation, supports the syntax used by - `zc.buildout'. Enables interpolation between sections.""" - - _KEYCRE = re.compile(r"\$\{([^}]+)\}") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return ''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace('$$', '') # escaped dollar signs - tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax - if '$' in tmp_value: - raise ValueError("invalid interpolation syntax in %r at " - "position %d" % (value, tmp_value.find('$'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - rawval = parser.get(section, option, raw=True, fallback=rest) - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rawval) - while rest: - p = rest.find("$") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == "$": - accum.append("$") - rest = rest[2:] - elif c == "{": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - "bad interpolation variable reference %r" % rest) - path = m.group(1).split(':') - rest = rest[m.end():] - sect = section - opt = option - try: - if len(path) == 1: - opt = parser.optionxform(path[0]) - v = map[opt] - elif len(path) == 2: - sect = path[0] - opt = parser.optionxform(path[1]) - v = parser.get(sect, opt, raw=True) - else: - raise InterpolationSyntaxError( - option, section, - "More than one ':' found: %r" % (rest,)) - except (KeyError, NoSectionError, NoOptionError): - raise from_none(InterpolationMissingOptionError( - option, section, rawval, ":".join(path))) - if "$" in v: - self._interpolate_some(parser, opt, accum, v, sect, - dict(parser.items(sect, raw=True)), - depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - "'$' must be followed by '$' or '{', " - "found: %r" % (rest,)) - - -class LegacyInterpolation(Interpolation): - """Deprecated interpolation used in old versions of ConfigParser. - Use BasicInterpolation or ExtendedInterpolation instead.""" - - _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") - - def before_get(self, parser, section, option, value, vars): - rawval = value - depth = MAX_INTERPOLATION_DEPTH - while depth: # Loop through this until it's done - depth -= 1 - if value and "%(" in value: - replace = functools.partial(self._interpolation_replace, - parser=parser) - value = self._KEYCRE.sub(replace, value) - try: - value = value % vars - except KeyError as e: - raise from_none(InterpolationMissingOptionError( - option, section, rawval, e.args[0])) - else: - break - if value and "%(" in value: - raise InterpolationDepthError(option, section, rawval) - return value - - def before_set(self, parser, section, option, value): - return value - - @staticmethod - def _interpolation_replace(match, parser): - s = match.group(1) - if s is None: - return match.group() - else: - return "%%(%s)s" % parser.optionxform(s) - - -class RawConfigParser(MutableMapping): - """ConfigParser that does not do interpolation.""" - - # Regular expressions for parsing section headers and options - _SECT_TMPL = r""" - \[ # [ - (?P
[^]]+) # very permissive! - \] # ] - """ - _OPT_TMPL = r""" - (?P