_g='Blank line at end of file'
_f='Trailing whitespace'
_e='decorator'
_d='string'
_c='comparison'
_b='lambdef'
_a='dictorsetmaker'
_Z='try_stmt'
_Y='classdef'
_X='import_from'
_W='import_name'
_V='error_node'
_U='backslash'
_T='decorated'
_S='def'
_R='class'
_Q='endmarker'
_P='suite'
_O='expr_stmt'
_N='argument'
_M='funcdef'
_L='comment'
_K='keyword'
_J='name'
_I='\t'
_H='error_leaf'
_G='\r'
_F='\n'
_E=':'
_D='newline'
_C=True
_B=False
_A=None
import re
from contextlib import contextmanager
from typing import Tuple
from parso.python.errors import ErrorFinder,ErrorFinderConfig
from parso.normalizer import Rule
from parso.python.tree import Flow,Scope
_IMPORT_TYPES=_W,_X
_SUITE_INTRODUCERS=_Y,_M,'if_stmt','while_stmt','for_stmt',_Z,'with_stmt'
_NON_STAR_TYPES='term',_X,'power'
_OPENING_BRACKETS='(','[','{'
_CLOSING_BRACKETS=')',']','}'
_FACTOR='+','-','~'
_ALLOW_SPACE='*','+','-','**','/','//','@'
_BITWISE_OPERATOR='<<','>>','|','&','^'
_NEEDS_SPACE='=','%','->','<','>','==','>=','<=','<>','!=','+=','-=','*=','@=','/=','%=','&=','|=','^=','<<=','>>=','**=','//='
_NEEDS_SPACE+=_BITWISE_OPERATOR
_IMPLICIT_INDENTATION_TYPES=_a,_N
_POSSIBLE_SLICE_PARENTS='subscript','subscriptlist','sliceop'
class IndentationTypes:VERTICAL_BRACKET=object();HANGING_BRACKET=object();BACKSLASH=object();SUITE=object();IMPLICIT=object()
class IndentationNode:
	type=IndentationTypes.SUITE
	def __init__(A,config,indentation,parent=_A):A.bracket_indentation=A.indentation=indentation;A.parent=parent
	def __repr__(A):return'<%s>'%A.__class__.__name__
	def get_latest_suite_node(B):
		A=B
		while A is not _A:
			if A.type==IndentationTypes.SUITE:return A
			A=A.parent
class BracketNode(IndentationNode):
	def __init__(A,config,leaf,parent,in_suite_introducer=_B):
		F=parent;D=leaf;C=config;A.leaf=D;E=D;B=F
		if B.type==IndentationTypes.IMPLICIT:B=B.parent
		while _C:
			if hasattr(B,'leaf')and E.line!=B.leaf.line:break
			E=E.get_previous_leaf()
			if not isinstance(B,BracketNode)or E!=B.leaf:break
			B=B.parent
		G=B.indentation;H=D.get_next_leaf()
		if _F in H.prefix or _G in H.prefix:A.bracket_indentation=G+C.closing_bracket_hanging_indentation;A.indentation=G+C.indentation;A.type=IndentationTypes.HANGING_BRACKET
		else:
			I=D.end_pos[1]
			if _I in C.indentation:A.indentation=_A
			else:A.indentation=' '*I
			A.bracket_indentation=A.indentation;A.type=IndentationTypes.VERTICAL_BRACKET
		if in_suite_introducer and F.type==IndentationTypes.SUITE and A.indentation==G+C.indentation:A.indentation+=C.indentation;A.bracket_indentation=A.indentation
		A.parent=F
class ImplicitNode(BracketNode):
	'\n    Implicit indentation after keyword arguments, default arguments,\n    annotations and dict values.\n    '
	def __init__(B,config,leaf,parent):
		A=leaf;super().__init__(config,A,parent);B.type=IndentationTypes.IMPLICIT;C=A.get_next_leaf()
		if A==_E and _F not in C.prefix and _G not in C.prefix:B.indentation+=' '
class BackslashNode(IndentationNode):
	type=IndentationTypes.BACKSLASH
	def __init__(A,config,parent_indentation,containing_leaf,spacing,parent=_A):
		C=parent_indentation;B=config;D=containing_leaf.search_ancestor(_O)
		if D is not _A:
			E=D.children[-2]
			if _I in B.indentation:A.indentation=_A
			elif E.end_pos==spacing.start_pos:A.indentation=C+B.indentation
			else:A.indentation=' '*(E.end_pos[1]+1)
		else:A.indentation=C+B.indentation
		A.bracket_indentation=A.indentation;A.parent=parent
def _is_magic_name(name):return name.value.startswith('__')and name.value.endswith('__')
class PEP8Normalizer(ErrorFinder):
	def __init__(A,*B,**C):
		super().__init__(*B,**C);A._previous_part=_A;A._previous_leaf=_A;A._on_newline=_C;A._newline_count=0;A._wanted_newline_count=_A;A._max_new_lines_in_prefix=0;A._new_statement=_C;A._implicit_indentation_possible=_B;A._indentation_tos=A._last_indentation_tos=IndentationNode(A._config,indentation='');A._in_suite_introducer=_B
		if' 'in A._config.indentation:A._indentation_type='spaces';A._wrong_indentation_char=_I
		else:A._indentation_type='tabs';A._wrong_indentation_char=' '
	@contextmanager
	def visit_node(self,node):
		with super().visit_node(node):
			with self._visit_node(node):yield
	@contextmanager
	def _visit_node(self,node):
		I='file_input';D=node;A=self;C=D.type
		if C in _W:
			J=D.get_defined_names()
			if len(J)>1:
				for S in J[:1]:A.add_issue(S,401,'Multiple imports on one line')
		elif C==_b:
			K=D.parent
			if K.type==_O and any(A.type==_J for A in K.children[:-2:2]):A.add_issue(D,731,'Do not assign a lambda expression, use a def')
		elif C==_Z:
			for B in D.children:
				if B.type==_K and B.value=='except':A.add_issue(B,722,'Do not use bare except, specify exception instead')
		elif C==_c:
			for B in D.children:
				if B.type not in('atom_expr','power'):continue
				if len(B.children)>2:continue
				T=B.children[1];L=B.children[0]
				if T.type=='trailer'and L.type==_J and L.value=='type':A.add_issue(D,721,"Do not compare types, use 'isinstance()");break
		elif C==I:
			F=D.children[-1];M=F.get_previous_leaf();G=F.prefix
			if not G.endswith(_F)and not G.endswith(_G)and(G or M is _A or M.value not in{_F,'\r\n',_G}):A.add_issue(F,292,'No newline at end of file')
		if C in _IMPORT_TYPES:
			N=D.parent;H=N.parent
			if H.type==I:
				U=H.children.index(N)
				for B in H.children[:U]:
					O=[B]
					if B.type=='simple_stmt':O=B.children[:-1]
					P=_B
					for E in O:
						if E.type==_d and not P:continue
						P=_C
						if E.type==_O and all(_is_magic_name(A)for A in E.get_defined_names()):continue
						if E.type in _IMPORT_TYPES or isinstance(E,Flow):continue
						A.add_issue(D,402,'Module level import not at top of file');break
					else:continue
					break
		Q=C in _IMPLICIT_INDENTATION_TYPES;R=C in _SUITE_INTRODUCERS
		if R:A._in_suite_introducer=_C
		elif C==_P:
			if A._indentation_tos.type==IndentationTypes.BACKSLASH:A._indentation_tos=A._indentation_tos.parent
			A._indentation_tos=IndentationNode(A._config,A._indentation_tos.indentation+A._config.indentation,parent=A._indentation_tos)
		elif Q:A._implicit_indentation_possible=_C
		yield
		if C==_P:assert A._indentation_tos.type==IndentationTypes.SUITE;A._indentation_tos=A._indentation_tos.parent;A._wanted_newline_count=_A
		elif Q:
			A._implicit_indentation_possible=_B
			if A._indentation_tos.type==IndentationTypes.IMPLICIT:A._indentation_tos=A._indentation_tos.parent
		elif R:
			A._in_suite_introducer=_B
			if C in(_Y,_M):A._wanted_newline_count=A._get_wanted_blank_lines_count()
	def _check_tabs_spaces(A,spacing):
		B=spacing
		if A._wrong_indentation_char in B.value:A.add_issue(B,101,'Indentation contains '+A._indentation_type);return _C
		return _B
	def _get_wanted_blank_lines_count(A):B=A._indentation_tos.get_latest_suite_node();return int(B.parent is _A)+1
	def _reset_newlines(A,spacing,leaf,is_comment=_B):
		H='async';I='expected %s blank line, found %s';J=is_comment;K=spacing;C=leaf;A._max_new_lines_in_prefix=max(A._max_new_lines_in_prefix,A._newline_count);B=A._wanted_newline_count
		if B is not _A:
			L=A._newline_count-1
			if B>L and C.type!=_Q:
				if not J:F=302 if B==2 else 301;G=I%(B,L);A.add_issue(K,F,G);A._wanted_newline_count=_A
			else:A._wanted_newline_count=_A
		if not J:
			B=A._get_wanted_blank_lines_count();M=A._max_new_lines_in_prefix-1;E=C.value;O=E=='@'and C.parent.type==_e or(E==_R or E==H and C.get_next_leaf()==_S or E==_S and A._previous_leaf!=H)and C.parent.parent.type!=_T
			if O and M<B:
				N=C.parent;D=N.parent
				if D.type==_T:D=D.parent
				if D.children[int(D.type==_P)]!=N:F=302 if B==2 else 301;G=I%(B,M);A.add_issue(K,F,G)
			A._max_new_lines_in_prefix=0
		A._newline_count=0
	def visit_leaf(A,leaf):
		B=leaf;super().visit_leaf(B)
		for C in B._split_prefix():
			if C.type=='spacing':break
			A._visit_part(C,C.create_spacing_part(),B)
		A._analyse_non_prefix(B);A._visit_part(B,C,B);A._last_indentation_tos=A._indentation_tos;A._new_statement=B.type==_D
		if B.type==_D and A._indentation_tos.type==IndentationTypes.BACKSLASH:A._indentation_tos=A._indentation_tos.parent
		if B.value==_E and B.parent.type in _SUITE_INTRODUCERS:A._in_suite_introducer=_B
		elif B.value=='elif':A._in_suite_introducer=_C
		if not A._new_statement:A._reset_newlines(C,B);A._max_blank_lines=0
		A._previous_leaf=B;return B.value
	def _visit_part(A,part,spacing,leaf):
		K='xxx';L='])}';J=leaf;F=spacing;B=part;D=B.value;G=B.type
		if G==_H:return
		if D==','and B.parent.type==_a:A._indentation_tos=A._indentation_tos.parent
		C=A._indentation_tos
		if G==_L:
			if D.startswith('##'):
				if D.lstrip('#'):A.add_issue(B,266,"Too many leading '#' for block comment.")
			elif A._on_newline:
				if not re.match('#:? ',D)and not D=='#'and not(D.startswith('#!')and B.start_pos==(1,0)):A.add_issue(B,265,"Block comment should start with '# '")
			elif not re.match('#:? [^ ]',D):A.add_issue(B,262,"Inline comment should start with '# '")
			A._reset_newlines(F,J,is_comment=_C)
		elif G==_D:
			if A._newline_count>A._get_wanted_blank_lines_count():A.add_issue(B,303,'Too many blank lines (%s)'%A._newline_count)
			elif J in(_S,_R)and J.parent.parent.type==_T:A.add_issue(B,304,'Blank lines found after function decorator')
			A._newline_count+=1
		if G==_U:
			if C.type!=IndentationTypes.BACKSLASH:
				if C.type!=IndentationTypes.SUITE:A.add_issue(B,502,'The backslash is redundant between brackets')
				else:
					E=C.indentation
					if A._in_suite_introducer and C.type==IndentationTypes.SUITE:E+=A._config.indentation
					A._indentation_tos=BackslashNode(A._config,E,B,F,parent=A._indentation_tos)
		elif A._on_newline:
			E=F.value
			if C.type==IndentationTypes.BACKSLASH and A._previous_part.type==_D:A._indentation_tos=A._indentation_tos.parent
			if not A._check_tabs_spaces(F):
				H=C.indentation
				if G==_L:
					I=A._last_indentation_tos
					while _C:
						if len(E)>len(I.indentation):break
						H=I.indentation;A._last_indentation_tos=I
						if I==C:break
						I=I.parent
				if A._new_statement:
					if G==_D:
						if E:A.add_issue(F,291,_f)
					elif E!=H:M='%s %s'%(len(A._config.indentation),A._indentation_type);A.add_issue(B,111,'Indentation is not a multiple of '+M)
				else:
					if D in L:H=C.bracket_indentation
					else:H=C.indentation
					if A._in_suite_introducer and E==C.get_latest_suite_node().indentation+A._config.indentation:A.add_issue(B,129,'Line with same indent as next logical block')
					elif E!=H:
						if not A._check_tabs_spaces(F)and B.value not in{_F,'\r\n',_G}:
							if D in L:
								if C.type==IndentationTypes.VERTICAL_BRACKET:A.add_issue(B,124,'Closing bracket does not match visual indentation')
								else:A.add_issue(B,123,"Losing bracket does not match indentation of opening bracket's line")
							elif len(E)<len(H):
								if C.type==IndentationTypes.VERTICAL_BRACKET:A.add_issue(B,128,'Continuation line under-indented for visual indent')
								elif C.type==IndentationTypes.BACKSLASH:A.add_issue(B,122,'Continuation line missing indentation or outdented')
								elif C.type==IndentationTypes.IMPLICIT:A.add_issue(B,135,K)
								else:A.add_issue(B,121,'Continuation line under-indented for hanging indent')
							elif C.type==IndentationTypes.VERTICAL_BRACKET:A.add_issue(B,127,'Continuation line over-indented for visual indent')
							elif C.type==IndentationTypes.IMPLICIT:A.add_issue(B,136,K)
							else:A.add_issue(B,126,'Continuation line over-indented for hanging indent')
		else:A._check_spacing(B,F)
		A._check_line_length(B,F)
		if D and D in'()[]{}'and G!=_H and B.parent.type!=_V:
			if D in _OPENING_BRACKETS:A._indentation_tos=BracketNode(A._config,B,parent=A._indentation_tos,in_suite_introducer=A._in_suite_introducer)
			else:assert C.type!=IndentationTypes.IMPLICIT;A._indentation_tos=A._indentation_tos.parent
		elif D in('=',_E)and A._implicit_indentation_possible and B.parent.type in _IMPLICIT_INDENTATION_TYPES:E=C.indentation;A._indentation_tos=ImplicitNode(A._config,B,parent=A._indentation_tos)
		A._on_newline=G in(_D,_U,'bom');A._previous_part=B;A._previous_spacing=F
	def _check_line_length(B,part,spacing):
		A=part
		if A.type==_U:C=A.start_pos[1]+1
		else:C=A.end_pos[1]
		if C>B._config.max_characters and spacing.start_pos[1]<=B._config.max_characters:
			D=_C
			if A.type==_L:
				E=A.value[1:].split()
				if len(E)==1 and A.end_pos[1]-len(E[0])<72:D=_B
			if D:B.add_issue(A,501,'Line too long (%s > %s characters)'%(C,B._config.max_characters))
	def _check_spacing(D,part,spacing):
		M='Missing whitespace between tokens';I='param';J="Whitespace before '%s'";C=spacing;A=part
		def G(*A):
			if F:return D.add_issue(*A)
		def H(*A):
			if not F:return D.add_issue(*A)
		F=C.value;B=D._previous_part
		if B is not _A and B.type==_H or A.type==_H:return
		K=A.type
		if _I in F:D.add_issue(C,223,'Used tab to separate tokens')
		elif K==_L:
			if len(F)<D._config.spaces_before_comment:D.add_issue(C,261,'At least two spaces before inline comment')
		elif K==_D:G(C,291,_f)
		elif len(F)>1:D.add_issue(C,221,'Multiple spaces used')
		elif B in _OPENING_BRACKETS:E="Whitespace after '%s'"%A.value;G(C,201,E)
		elif A in _CLOSING_BRACKETS:E=J%A.value;G(C,202,E)
		elif A in(',',';')or A==_E and A.parent.type not in _POSSIBLE_SLICE_PARENTS:E=J%A.value;G(C,203,E)
		elif B==_E and B.parent.type in _POSSIBLE_SLICE_PARENTS:0
		elif B in(',',';',_E):H(C,231,"missing whitespace after '%s'")
		elif A==_E:0
		elif A in('*','**')and A.parent.type not in _NON_STAR_TYPES or B in('*','**')and B.parent.type not in _NON_STAR_TYPES:0
		elif B in _FACTOR and B.parent.type=='factor':0
		elif B=='@'and B.parent.type==_e:0
		elif A in _NEEDS_SPACE or B in _NEEDS_SPACE:
			if A=='='and A.parent.type in(_N,I)or B=='='and B.parent.type in(_N,I):
				if A=='=':L=A.parent
				else:L=B.parent
				if L.type==I and L.annotation:H(C,252,'Expected spaces around annotation equals')
				else:G(C,251,'Unexpected spaces around keyword / parameter equals')
			elif A in _BITWISE_OPERATOR or B in _BITWISE_OPERATOR:H(C,227,'Missing whitespace around bitwise or shift operator')
			elif A=='%'or B=='%':H(C,228,'Missing whitespace around modulo operator')
			else:N=M;H(C,225,N)
		elif K==_K or B.type==_K:H(C,275,'Missing whitespace around keyword')
		else:
			O=D._previous_spacing
			if B in _ALLOW_SPACE and F!=O.value and _F not in D._previous_leaf.prefix and _G not in D._previous_leaf.prefix:E="Whitespace before operator doesn't match with whitespace after";D.add_issue(C,229,E)
			if F and A not in _ALLOW_SPACE and B not in _ALLOW_SPACE:
				N=M
				if A in _OPENING_BRACKETS:E=J%A.value;G(C,211,E)
	def _analyse_non_prefix(B,leaf):
		H='function';A=leaf;F=A.type
		if F==_J and A.value in('l','O','I'):
			if A.is_definition():
				C="Do not define %s named 'l', 'O', or 'I' one line"
				if A.parent.type==_R and A.parent.name==A:B.add_issue(A,742,C%'classes')
				elif A.parent.type==H and A.parent.name==A:B.add_issue(A,743,C%H)
				else:B.add_issuadd_issue(741,C%'variables',A)
		elif A.value==_E:
			if isinstance(A.parent,(Flow,Scope))and A.parent.type!=_b:
				G=A.get_next_leaf()
				if G.type!=_D:
					if A.parent.type==_M:B.add_issue(G,704,'Multiple statements on one line (def)')
					else:B.add_issue(G,701,'Multiple statements on one line (colon)')
		elif A.value==';':
			if A.get_next_leaf().type in(_D,_Q):B.add_issue(A,703,'Statement ends with a semicolon')
			else:B.add_issue(A,702,'Multiple statements on one line (semicolon)')
		elif A.value in('==','!='):
			D=A.parent;I=D.children.index(A);J=D.children[I-1];K=D.children[I+1]
			for E in(J,K):
				if E.type==_K or E.type==_J:
					if E.value=='None':C="comparison to None should be 'if cond is None:'";B.add_issue(A,711,C);break
					elif E.value in('True','False'):C="comparison to False/True should be 'if cond is True:' or 'if cond:'";B.add_issue(A,712,C);break
		elif A.value in('in','is'):
			D=A.parent
			if D.type==_c and D.parent.type=='not_test':
				if A.value=='in':B.add_issue(A,713,"test for membership should be 'not in'")
				else:B.add_issue(A,714,"test for object identity should be 'is not'")
		elif F==_d:
			for(L,M)in enumerate(A.value.splitlines()[1:]):N=re.match('[ \\t]*',M).group(0);O=A.line+L,len(N);O
		elif F==_Q:
			if B._newline_count>=2:B.add_issue(A,391,_g)
	def add_issue(A,node,code,message):
		D=message;B=code;C=node
		if A._previous_leaf is not _A:
			if A._previous_leaf.search_ancestor(_V)is not _A:return
			if A._previous_leaf.type==_H:return
		if C.search_ancestor(_V)is not _A:return
		if B in(901,903):super().add_issue(C,B,D)
		else:super(ErrorFinder,A).add_issue(C,B,D)
class PEP8NormalizerConfig(ErrorFinderConfig):
	normalizer_class=PEP8Normalizer;'\n    Normalizing to PEP8. Not really implemented, yet.\n    '
	def __init__(A,indentation=' '*4,hanging_indentation=_A,max_characters=79,spaces_before_comment=2):
		C=indentation;B=hanging_indentation;A.indentation=C
		if B is _A:B=C
		A.hanging_indentation=B;A.closing_bracket_hanging_indentation='';A.break_after_binary=_B;A.max_characters=max_characters;A.spaces_before_comment=spaces_before_comment
class BlankLineAtEnd(Rule):
	code=392;message=_g
	def is_issue(A,leaf):return A._newline_count>=2