<s> import re <EOL> import os <EOL> import keyword <EOL> from jedi import cache <EOL> from jedi import common <EOL> from jedi . parser import tokenize , Parser <EOL> from jedi . _compatibility import u <EOL> from jedi . parser . fast import FastParser <EOL> from jedi . parser import tree <EOL> from jedi import debug <EOL> from jedi . common import PushBackIterator <EOL> REPLACE_STR = r"<STR_LIT>" + ( r"<STR_LIT>" + <EOL> '<STR_LIT:|>' + <EOL> r'<STR_LIT>' ) <EOL> REPLACE_STR = re . compile ( REPLACE_STR ) <EOL> class UserContext ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , source , position ) : <EOL> self . source = source <EOL> self . position = position <EOL> self . _line_cache = None <EOL> self . _relevant_temp = None <EOL> @ cache . underscore_memoization <EOL> def get_path_until_cursor ( self ) : <EOL> """<STR_LIT>""" <EOL> path , self . _start_cursor_pos = self . _calc_path_until_cursor ( self . position ) <EOL> return path <EOL> def _backwards_line_generator ( self , start_pos ) : <EOL> self . _line_temp , self . _column_temp = start_pos <EOL> first_line = self . get_line ( start_pos [ <NUM_LIT:0> ] ) [ : self . _column_temp ] <EOL> self . _line_length = self . _column_temp <EOL> yield first_line [ : : - <NUM_LIT:1> ] + '<STR_LIT:\n>' <EOL> while True : <EOL> self . _line_temp -= <NUM_LIT:1> <EOL> line = self . get_line ( self . _line_temp ) <EOL> self . _line_length = len ( line ) <EOL> yield line [ : : - <NUM_LIT:1> ] + '<STR_LIT:\n>' <EOL> def _get_backwards_tokenizer ( self , start_pos , line_gen = None ) : <EOL> if line_gen is None : <EOL> line_gen = self . _backwards_line_generator ( start_pos ) <EOL> token_gen = tokenize . generate_tokens ( lambda : next ( line_gen ) ) <EOL> for typ , tok_str , tok_start_pos , prefix in token_gen : <EOL> line = self . get_line ( self . _line_temp ) <EOL> if tok_start_pos [ <NUM_LIT:0> ] == <NUM_LIT:1> : <EOL> column = start_pos [ <NUM_LIT:1> ] - tok_start_pos [ <NUM_LIT:1> ] <EOL> else : <EOL> column = len ( line ) - tok_start_pos [ <NUM_LIT:1> ] <EOL> first_line = common . splitlines ( tok_str ) [ <NUM_LIT:0> ] <EOL> column -= len ( first_line ) <EOL> yield typ , tok_str [ : : - <NUM_LIT:1> ] , ( self . _line_temp , column ) , prefix [ : : - <NUM_LIT:1> ] <EOL> def _calc_path_until_cursor ( self , start_pos ) : <EOL> """<STR_LIT>""" <EOL> open_brackets = [ '<STR_LIT:(>' , '<STR_LIT:[>' , '<STR_LIT:{>' ] <EOL> close_brackets = [ '<STR_LIT:)>' , '<STR_LIT:]>' , '<STR_LIT:}>' ] <EOL> start_cursor = start_pos <EOL> gen = PushBackIterator ( self . _get_backwards_tokenizer ( start_pos ) ) <EOL> string = u ( '<STR_LIT>' ) <EOL> level = <NUM_LIT:0> <EOL> force_point = False <EOL> last_type = None <EOL> is_first = True <EOL> for tok_type , tok_str , tok_start_pos , prefix in gen : <EOL> if is_first : <EOL> if prefix : <EOL> return u ( '<STR_LIT>' ) , start_cursor <EOL> is_first = False <EOL> if last_type == tok_type == tokenize . NAME : <EOL> string = '<STR_LIT:U+0020>' + string <EOL> if level : <EOL> if tok_str in close_brackets : <EOL> level += <NUM_LIT:1> <EOL> elif tok_str in open_brackets : <EOL> level -= <NUM_LIT:1> <EOL> elif tok_str == '<STR_LIT:.>' : <EOL> force_point = False <EOL> elif force_point : <EOL> if tok_type == tokenize . NUMBER and tok_str [ - <NUM_LIT:1> ] == '<STR_LIT:.>' or tok_type == tokenize . NAME and last_type == tokenize . STRING and tok_str . lower ( ) in ( '<STR_LIT:b>' , '<STR_LIT:u>' , '<STR_LIT:r>' , '<STR_LIT>' , '<STR_LIT>' ) : <EOL> force_point = False <EOL> else : <EOL> break <EOL> elif tok_str in close_brackets : <EOL> level += <NUM_LIT:1> <EOL> elif tok_type in [ tokenize . NAME , tokenize . STRING ] : <EOL> if keyword . iskeyword ( tok_str ) and string : <EOL> break <EOL> force_point = True <EOL> elif tok_type == tokenize . NUMBER : <EOL> pass <EOL> else : <EOL> if tok_str == '<STR_LIT:->' : <EOL> next_tok = next ( gen ) <EOL> if next_tok [ <NUM_LIT:1> ] == '<STR_LIT:e>' : <EOL> gen . push_back ( next_tok ) <EOL> else : <EOL> break <EOL> else : <EOL> break <EOL> start_cursor = tok_start_pos <EOL> string = tok_str + prefix + string <EOL> last_type = tok_type <EOL> return string . strip ( ) , start_cursor <EOL> def get_path_under_cursor ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . get_path_until_cursor ( ) + self . get_path_after_cursor ( ) <EOL> def get_path_after_cursor ( self ) : <EOL> line = self . get_line ( self . position [ <NUM_LIT:0> ] ) <EOL> return re . search ( "<STR_LIT>" , line [ self . position [ <NUM_LIT:1> ] : ] ) . group ( <NUM_LIT:0> ) <EOL> def get_operator_under_cursor ( self ) : <EOL> line = self . get_line ( self . position [ <NUM_LIT:0> ] ) <EOL> after = re . match ( "<STR_LIT>" , line [ self . position [ <NUM_LIT:1> ] : ] ) <EOL> before = re . match ( "<STR_LIT>" , line [ : self . position [ <NUM_LIT:1> ] ] [ : : - <NUM_LIT:1> ] ) <EOL> return ( before . group ( <NUM_LIT:0> ) if before is not None else '<STR_LIT>' ) + ( after . group ( <NUM_LIT:0> ) if after is not None else '<STR_LIT>' ) <EOL> def call_signature ( self ) : <EOL> """<STR_LIT>""" <EOL> def get_line ( pos ) : <EOL> def simplify_str ( match ) : <EOL> """<STR_LIT>""" <EOL> mark = match . group ( <NUM_LIT:1> ) or match . group ( <NUM_LIT:2> ) <EOL> return mark + '<STR_LIT:U+0020>' * ( len ( match . group ( <NUM_LIT:0> ) ) - <NUM_LIT:2> ) + mark <EOL> line_gen = self . _backwards_line_generator ( pos ) <EOL> for line in line_gen : <EOL> line = line [ : : - <NUM_LIT:1> ] <EOL> modified = re . sub ( REPLACE_STR , simplify_str , line ) <EOL> yield modified [ : : - <NUM_LIT:1> ] <EOL> index = <NUM_LIT:0> <EOL> level = <NUM_LIT:0> <EOL> next_must_be_name = False <EOL> next_is_key = False <EOL> key_name = None <EOL> generator = self . _get_backwards_tokenizer ( self . position , get_line ( self . position ) ) <EOL> for tok_type , tok_str , start_pos , prefix in generator : <EOL> if tok_str in tokenize . ALWAYS_BREAK_TOKENS : <EOL> break <EOL> elif next_must_be_name : <EOL> if tok_type == tokenize . NUMBER : <EOL> tok_type , t , _ , _ = next ( generator ) <EOL> if tok_type == tokenize . NAME : <EOL> end_pos = start_pos [ <NUM_LIT:0> ] , start_pos [ <NUM_LIT:1> ] + len ( tok_str ) <EOL> call , start_pos = self . _calc_path_until_cursor ( start_pos = end_pos ) <EOL> return call , index , key_name , start_pos <EOL> index = <NUM_LIT:0> <EOL> next_must_be_name = False <EOL> elif next_is_key : <EOL> if tok_type == tokenize . NAME : <EOL> key_name = tok_str <EOL> next_is_key = False <EOL> if tok_str == '<STR_LIT:(>' : <EOL> level += <NUM_LIT:1> <EOL> if level == <NUM_LIT:1> : <EOL> next_must_be_name = True <EOL> level = <NUM_LIT:0> <EOL> elif tok_str == '<STR_LIT:)>' : <EOL> level -= <NUM_LIT:1> <EOL> elif tok_str == '<STR_LIT:U+002C>' : <EOL> index += <NUM_LIT:1> <EOL> elif tok_str == '<STR_LIT:=>' : <EOL> next_is_key = True <EOL> return None , <NUM_LIT:0> , None , ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> def get_context ( self , yield_positions = False ) : <EOL> self . get_path_until_cursor ( ) <EOL> pos = self . _start_cursor_pos <EOL> while True : <EOL> line = self . get_line ( pos [ <NUM_LIT:0> ] ) <EOL> while True : <EOL> if pos [ <NUM_LIT:1> ] == <NUM_LIT:0> : <EOL> line = self . get_line ( pos [ <NUM_LIT:0> ] - <NUM_LIT:1> ) <EOL> if line and line [ - <NUM_LIT:1> ] == '<STR_LIT:\\>' : <EOL> pos = pos [ <NUM_LIT:0> ] - <NUM_LIT:1> , len ( line ) - <NUM_LIT:1> <EOL> continue <EOL> else : <EOL> break <EOL> if line [ pos [ <NUM_LIT:1> ] - <NUM_LIT:1> ] . isspace ( ) : <EOL> pos = pos [ <NUM_LIT:0> ] , pos [ <NUM_LIT:1> ] - <NUM_LIT:1> <EOL> else : <EOL> break <EOL> try : <EOL> result , pos = self . _calc_path_until_cursor ( start_pos = pos ) <EOL> if yield_positions : <EOL> yield pos <EOL> else : <EOL> yield result <EOL> except StopIteration : <EOL> if yield_positions : <EOL> yield None <EOL> else : <EOL> yield '<STR_LIT>' <EOL> def get_line ( self , line_nr ) : <EOL> if not self . _line_cache : <EOL> self . _line_cache = common . splitlines ( self . source ) <EOL> if line_nr == <NUM_LIT:0> : <EOL> return u ( '<STR_LIT>' ) <EOL> if line_nr < <NUM_LIT:0> : <EOL> raise StopIteration ( ) <EOL> try : <EOL> return self . _line_cache [ line_nr - <NUM_LIT:1> ] <EOL> except IndexError : <EOL> raise StopIteration ( ) <EOL> def get_position_line ( self ) : <EOL> return self . get_line ( self . position [ <NUM_LIT:0> ] ) [ : self . position [ <NUM_LIT:1> ] ] <EOL> class UserContextParser ( object ) : <EOL> def __init__ ( self , grammar , source , path , position , user_context , <EOL> parser_done_callback , use_fast_parser = True ) : <EOL> self . _grammar = grammar <EOL> self . _source = source <EOL> self . _path = path and os . path . abspath ( path ) <EOL> self . _position = position <EOL> self . _user_context = user_context <EOL> self . _use_fast_parser = use_fast_parser <EOL> self . _parser_done_callback = parser_done_callback <EOL> @ cache . underscore_memoization <EOL> def _parser ( self ) : <EOL> cache . invalidate_star_import_cache ( self . _path ) <EOL> if self . _use_fast_parser : <EOL> parser = FastParser ( self . _grammar , self . _source , self . _path ) <EOL> cache . save_parser ( self . _path , parser , pickling = False ) <EOL> else : <EOL> parser = Parser ( self . _grammar , self . _source , self . _path ) <EOL> self . _parser_done_callback ( parser ) <EOL> return parser <EOL> @ cache . underscore_memoization <EOL> def user_stmt ( self ) : <EOL> module = self . module ( ) <EOL> debug . speed ( '<STR_LIT>' ) <EOL> return module . get_statement_for_position ( self . _position ) <EOL> @ cache . underscore_memoization <EOL> def user_stmt_with_whitespace ( self ) : <EOL> """<STR_LIT>""" <EOL> user_stmt = self . user_stmt ( ) <EOL> if not user_stmt : <EOL> if self . _user_context . get_path_under_cursor ( ) : <EOL> debug . warning ( '<STR_LIT>' ) <EOL> return <EOL> pos = next ( self . _user_context . get_context ( yield_positions = True ) ) <EOL> user_stmt = self . module ( ) . get_statement_for_position ( pos ) <EOL> return user_stmt <EOL> @ cache . underscore_memoization <EOL> def user_scope ( self ) : <EOL> """<STR_LIT>""" <EOL> user_stmt = self . user_stmt ( ) <EOL> if user_stmt is None : <EOL> def scan ( scope ) : <EOL> for s in scope . children : <EOL> if s . start_pos <= self . _position <= s . end_pos : <EOL> if isinstance ( s , ( tree . Scope , tree . Flow ) ) : <EOL> if isinstance ( s , tree . Flow ) : <EOL> return s <EOL> return scan ( s ) or s <EOL> elif s . type in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> return scan ( s ) <EOL> return scan ( self . module ( ) ) or self . module ( ) <EOL> else : <EOL> return user_stmt . get_parent_scope ( include_flows = True ) <EOL> def module ( self ) : <EOL> return self . _parser ( ) . module </s>
