def console_exec(thread_id, frame_id, expression, dbg): """returns 'False' in case expression is partially correct """ frame = pydevd_vars.find_frame(thread_id, frame_id) is_multiline = expression.count('@LINE@') > 1 try: expression = str(expression.replace('@LINE@', '\n')) except UnicodeEncodeError as e: expression = expression.replace('@LINE@', '\n') # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 # (Names not resolved in generator expression in method) # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html updated_globals = {} updated_globals.update(frame.f_globals) updated_globals.update( frame.f_locals ) # locals later because it has precedence over the actual globals if PYTEST_RUN_CONFIG: enable_pytest_output() if IPYTHON: need_more = exec_code(CodeFragment(expression), updated_globals, updated_globals, dbg) if not need_more: update_frame_local_variables_and_save(frame, updated_globals) return need_more interpreter = ConsoleWriter() if not is_multiline: try: code = compile_command(expression) except (OverflowError, SyntaxError, ValueError): # Case 1 interpreter.showsyntaxerror() return False if code is None: # Case 2 return True else: code = expression # Case 3 try: # It is important that globals and locals we pass to the exec function are the same object. # Otherwise generator expressions can confuse their scope. Passing updated_globals dictionary seems to be a safe option here # because it contains globals and locals in the right precedence. # See: https://stackoverflow.com/questions/15866398/why-is-a-python-generator-confusing-its-scope-with-global-in-an-execd-script. Exec(code, updated_globals, updated_globals) except SystemExit: raise except: interpreter.showtraceback() else: update_frame_local_variables_and_save(frame, updated_globals) return False
def console_exec(thread_id, frame_id, expression, dbg): """returns 'False' in case expression is partially correct """ frame = pydevd_vars.find_frame(thread_id, frame_id) is_multiline = expression.count('@LINE@') > 1 try: expression = str(expression.replace('@LINE@', '\n')) except UnicodeEncodeError as e: expression = expression.replace('@LINE@', '\n') # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 # (Names not resolved in generator expression in method) # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html updated_globals = {} updated_globals.update(frame.f_globals) updated_globals.update( frame.f_locals ) # locals later because it has precedence over the actual globals if PYTEST_RUN_CONFIG: enable_pytest_output() if IPYTHON: need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg) if not need_more: pydevd_save_locals.save_locals(frame) return need_more interpreter = ConsoleWriter() if not is_multiline: try: code = compile_command(expression) except (OverflowError, SyntaxError, ValueError): # Case 1 interpreter.showsyntaxerror() return False if code is None: # Case 2 return True else: code = expression # Case 3 try: Exec(code, updated_globals, frame.f_locals) except SystemExit: raise except: interpreter.showtraceback() else: pydevd_save_locals.save_locals(frame) return False
def do_exec_code(self, code, is_single_line): try: code_fragment = CodeFragment(code, is_single_line) more = self.need_more(code_fragment) if not more: code_fragment = self.buffer self.buffer = None self.exec_queue.put(code_fragment) return more except: traceback.print_exc() return False
def test_command_run(mocker, code, result): from _pydev_bundle.pydev_console_types import CodeFragment, Command mock = mocker.MagicMock() command = Command(mock, CodeFragment(code)) command.run() command.interpreter.runsource.assert_called_once_with( result, "<input>", "single", )
def test_console_requests(self): self.original_stdout = sys.stdout sys.stdout = pydevd_io.IOBuf() try: rpc_client = self.start_client_thread() #@UnusedVariable import time time.sleep(.3) #let's give it some time to start the threads from _pydev_bundle import pydev_localhost from _pydev_bundle.pydev_console_types import CodeFragment interpreter = pydevconsole.InterpreterInterface(threading.current_thread(), rpc_client=rpc_client) sys.stdout = pydevd_io.IOBuf() interpreter.add_exec(CodeFragment('class Foo:\n CONSTANT=1\n')) interpreter.add_exec(CodeFragment('foo=Foo()')) interpreter.add_exec(CodeFragment('foo.__doc__=None')) interpreter.add_exec(CodeFragment('val = %s()' % (raw_input_name,))) interpreter.add_exec(CodeFragment('50')) interpreter.add_exec(CodeFragment('print (val)')) found = sys.stdout.getvalue().split() try: self.assertEqual(['50', 'input_request'], found) except: try: self.assertEqual(['input_request'], found) #IPython except: self.assertEqual([u'50', u'input_request'], found[1:]) # IPython 5.1 self.assertTrue(found[0].startswith(u'Out')) comps = interpreter.do_get_completions('foo.', 'foo.') self.assertTrue( ('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \ 'Found: %s' % comps ) comps = interpreter.do_get_completions('"".', '"".') self.assertTrue( ('__add__', 'x.__add__(y) <==> x+y', '', '3') in comps or ('__add__', '', '', '4') in comps or ('__add__', 'x.__add__(y) <==> x+y\r\nx.__add__(y) <==> x+y', '()', '2') in comps or ('__add__', 'x.\n__add__(y) <==> x+yx.\n__add__(y) <==> x+y', '()', '2'), 'Did not find __add__ in : %s' % (comps,) ) completions = interpreter.do_get_completions('', '') for c in completions: if c[0] == 'AssertionError': break else: self.fail('Could not find AssertionError') completions = interpreter.do_get_completions('Assert', 'Assert') for c in completions: if c[0] == 'RuntimeError': self.fail('Did not expect to find RuntimeError there') self.assertTrue(('__doc__', None, '', '3') not in interpreter.do_get_completions('foo.CO', 'foo.')) comps = interpreter.do_get_completions('va', 'va') self.assertTrue(('val', '', '', '3') in comps or ('vars', '', '', '4') in comps) interpreter.add_exec(CodeFragment('s = "mystring"')) desc = interpreter.getDescription('val') self.assertTrue(desc.find('str(object) -> string') >= 0 or desc == "'input_request'" or desc.find('str(string[, encoding[, errors]]) -> str') >= 0 or desc.find('str(Char* value)') >= 0 or desc.find('str(object=\'\') -> string') >= 0 or desc.find('str(value: Char*)') >= 0 or desc.find('str(object=\'\') -> str') >= 0 or desc.find('unicode(object=\'\') -> unicode object') >= 0 or desc.find('The most base type') >= 0 # Jython 2.7 is providing this :P , 'Could not find what was needed in %s' % desc) desc = interpreter.getDescription('val.join') self.assertTrue(desc.find('S.join(sequence) -> string') >= 0 or desc.find('S.join(sequence) -> str') >= 0 or desc.find('S.join(iterable) -> string') >= 0 or desc == "<builtin method 'join'>" or desc == "<built-in method join of str object>" or desc.find('str join(str self, list sequence)') >= 0 or desc.find('S.join(iterable) -> str') >= 0 or desc.find('S.join(iterable) -> unicode') >= 0 or desc.find('join(self: str, sequence: list) -> str') >= 0 or desc.find('Concatenate any number of strings.') >= 0, "Could not recognize: %s" % (desc,)) finally: sys.stdout = self.original_stdout