Vendor debugpy for VS Code attach debugging

Bundles debugpy 1.7.0 directly in python/ so "Maya: Attach (debugpy)"
works with no per-machine pip install step. Installed via Maya 2022's
own pip so it resolved a version actually compatible with Python 3.7
(Maya 2022's interpreter), then verified import + listen() succeeds
under all three target Maya Python versions (3.7/3.9/3.10).

Also fixes a latent __file__-under-exec() bug in
start_debug_server.py (same pitfall as Maya's own plugin loader,
never hit until this exercised it) and corrects the README's Maya
Python version claim -- 2022 ships Python 3.7, not 3.9 as previously
stated, which was never independently verified until now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 09:01:16 +08:00
parent e2f2e6668a
commit ec5f52c7c6
623 changed files with 236815 additions and 12 deletions
@@ -0,0 +1,113 @@
import threading
import unittest
import os
import pytest
import pydevconsole
from _pydev_bundle.pydev_imports import xmlrpclib, SimpleXMLRPCServer
from _pydev_bundle.pydev_localhost import get_localhost
try:
raw_input
raw_input_name = 'raw_input'
except NameError:
raw_input_name = 'input'
try:
from IPython import core # @UnusedImport
has_ipython = True
except:
has_ipython = False
#=======================================================================================================================
# Test
#=======================================================================================================================
@pytest.mark.skipif(os.environ.get('TRAVIS') == 'true' or not has_ipython, reason='Too flaky on Travis (and requires IPython).')
class Test(unittest.TestCase):
def start_client_thread(self, client_port):
class ClientThread(threading.Thread):
def __init__(self, client_port):
threading.Thread.__init__(self)
self.client_port = client_port
def run(self):
class HandleRequestInput:
def RequestInput(self):
client_thread.requested_input = True
return 'RequestInput: OK'
def NotifyFinished(self, *args, **kwargs):
client_thread.notified_finished += 1
return 1
handle_request_input = HandleRequestInput()
from _pydev_bundle import pydev_localhost
self.client_server = client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
client_server.register_function(handle_request_input.RequestInput)
client_server.register_function(handle_request_input.NotifyFinished)
client_server.serve_forever()
def shutdown(self):
return
self.client_server.shutdown()
client_thread = ClientThread(client_port)
client_thread.requested_input = False
client_thread.notified_finished = 0
client_thread.daemon = True
client_thread.start()
return client_thread
def get_free_addresses(self):
from _pydev_bundle.pydev_localhost import get_socket_names
socket_names = get_socket_names(2, close=True)
return [socket_name[1] for socket_name in socket_names]
def test_server(self):
# Just making sure that the singleton is created in this thread.
from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend
get_pydev_frontend(get_localhost(), 0)
client_port, server_port = self.get_free_addresses()
class ServerThread(threading.Thread):
def __init__(self, client_port, server_port):
threading.Thread.__init__(self)
self.client_port = client_port
self.server_port = server_port
def run(self):
from _pydev_bundle import pydev_localhost
print('Starting server with:', pydev_localhost.get_localhost(), self.server_port, self.client_port)
pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port)
server_thread = ServerThread(client_port, server_port)
server_thread.daemon = True
server_thread.start()
client_thread = self.start_client_thread(client_port) #@UnusedVariable
try:
import time
time.sleep(.3) #let's give it some time to start the threads
from _pydev_bundle import pydev_localhost
server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
server.execLine("import sys; print('Running with: %s %s' % (sys.executable or sys.platform, sys.version))")
server.execLine('class Foo:')
server.execLine(' pass')
server.execLine('')
server.execLine('foo = Foo()')
server.execLine('a = %s()' % raw_input_name)
initial = time.time()
while not client_thread.requested_input:
if time.time() - initial > 2:
raise AssertionError('Did not get the return asked before the timeout.')
time.sleep(.1)
frame_xml = server.getFrame()
self.assertTrue('RequestInput' in frame_xml, 'Did not fid RequestInput in:\n%s' % (frame_xml,))
finally:
client_thread.shutdown()
@@ -0,0 +1,125 @@
import sys
import threading
import time
import unittest
import pytest
from _pydevd_bundle import pydevd_referrers
from io import StringIO
from tests_python.debugger_unittest import IS_PYPY
try:
import gc
gc.get_referrers(unittest)
has_referrers = True
except NotImplementedError:
has_referrers = False
# Only do get referrers tests if it's actually available.
@pytest.mark.skipif(not has_referrers or IS_PYPY, reason='gc.get_referrers not implemented')
class Test(unittest.TestCase):
def test_get_referrers1(self):
container = []
contained = [1, 2]
container.append(0)
container.append(contained)
# Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
# we should skip temporary references inside the get_referrer_info.
result = pydevd_referrers.get_referrer_info(contained)
assert 'list[1]' in result
pydevd_referrers.print_referrers(contained, stream=StringIO())
def test_get_referrers2(self):
class MyClass(object):
def __init__(self):
pass
contained = [1, 2]
obj = MyClass()
obj.contained = contained
del contained
# Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
# we should skip temporary references inside the get_referrer_info.
result = pydevd_referrers.get_referrer_info(obj.contained)
assert 'found_as="contained"' in result
assert 'MyClass' in result
def test_get_referrers3(self):
class MyClass(object):
def __init__(self):
pass
contained = [1, 2]
obj = MyClass()
obj.contained = contained
del contained
# Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
# we should skip temporary references inside the get_referrer_info.
result = pydevd_referrers.get_referrer_info(obj.contained)
assert 'found_as="contained"' in result
assert 'MyClass' in result
def test_get_referrers4(self):
class MyClass(object):
def __init__(self):
pass
obj = MyClass()
obj.me = obj
# Let's see if we detect the cycle...
result = pydevd_referrers.get_referrer_info(obj)
assert 'found_as="me"' in result # Cyclic ref
def test_get_referrers5(self):
container = dict(a=[1])
# Let's see if we detect the cycle...
result = pydevd_referrers.get_referrer_info(container['a'])
assert 'test_get_referrers5' not in result # I.e.: NOT in the current method
assert 'found_as="a"' in result
assert 'dict' in result
assert str(id(container)) in result
def test_get_referrers6(self):
import sys
container = dict(a=[1])
def should_appear(obj):
# Let's see if we detect the cycle...
return pydevd_referrers.get_referrer_info(obj)
result = should_appear(container['a'])
if sys.version_info[:2] >= (3, 7):
# In Python 3.7 the frame is not appearing in gc.get_referrers.
assert 'should_appear' not in result
else:
assert 'should_appear' in result
def test_get_referrers7(self):
class MyThread(threading.Thread):
def run(self):
# Note: we do that because if we do
self.frame = sys._getframe()
t = MyThread()
t.start()
while not hasattr(t, 'frame'):
time.sleep(0.01)
result = pydevd_referrers.get_referrer_info(t.frame)
assert 'MyThread' in result
@@ -0,0 +1,140 @@
'''
@author Fabio Zadrozny
'''
import sys
import unittest
import socket
import urllib
import pytest
import pycompletionserver
IS_JYTHON = sys.platform.find('java') != -1
DEBUG = 0
def dbg(s):
if DEBUG:
sys.stdout.write('TEST %s\n' % s)
@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test')
class TestJython(unittest.TestCase):
def test_it(self):
dbg('ok')
def test_message(self):
t = pycompletionserver.CompletionServer(0)
t.exit_process_on_kill = False
l = []
l.append(('Def', 'description' , 'args'))
l.append(('Def1', 'description1', 'args1'))
l.append(('Def2', 'description2', 'args2'))
msg = t.processor.format_completion_message('test_jyserver.py', l)
self.assertEqual('@@COMPLETIONS(test_jyserver.py,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg)
l = []
l.append(('Def', 'desc,,r,,i()ption', ''))
l.append(('Def(1', 'descriptio(n1', ''))
l.append(('De,f)2', 'de,s,c,ription2', ''))
msg = t.processor.format_completion_message(None, l)
expected = '@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@'
self.assertEqual(expected, msg)
def test_completion_sockets_and_messages(self):
dbg('test_completion_sockets_and_messages')
t, socket = self.create_connections()
self.socket = socket
dbg('connections created')
try:
#now that we have the connections all set up, check the code completion messages.
msg = urllib.quote_plus('math')
toWrite = '@@IMPORTS:%sEND@@' % msg
dbg('writing' + str(toWrite))
socket.send(toWrite) #math completions
completions = self.read_msg()
dbg(urllib.unquote_plus(completions))
start = '@@COMPLETIONS('
self.assertTrue(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start))
self.assertTrue(completions.find('@@COMPLETIONS') != -1)
self.assertTrue(completions.find('END@@') != -1)
msg = urllib.quote_plus('__builtin__.str')
toWrite = '@@IMPORTS:%sEND@@' % msg
dbg('writing' + str(toWrite))
socket.send(toWrite) #math completions
completions = self.read_msg()
dbg(urllib.unquote_plus(completions))
start = '@@COMPLETIONS('
self.assertTrue(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start))
self.assertTrue(completions.find('@@COMPLETIONS') != -1)
self.assertTrue(completions.find('END@@') != -1)
finally:
try:
self.send_kill_msg(socket)
while not t.ended:
pass #wait until it receives the message and quits.
socket.close()
except:
pass
def get_free_port(self):
from _pydev_bundle.pydev_localhost import get_socket_name
return get_socket_name(close=True)[1]
def create_connections(self):
'''
Creates the connections needed for testing.
'''
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((pycompletionserver.HOST, 0))
server.listen(1) #socket to receive messages.
from thread import start_new_thread
t = pycompletionserver.CompletionServer(server.getsockname()[1])
t.exit_process_on_kill = False
start_new_thread(t.run, ())
sock, _addr = server.accept()
return t, sock
def read_msg(self):
msg = '@@PROCESSING_END@@'
while msg.startswith('@@PROCESSING'):
msg = self.socket.recv(1024)
if msg.startswith('@@PROCESSING:'):
dbg('Status msg:' + str(msg))
while msg.find('END@@') == -1:
msg += self.socket.recv(1024)
return msg
def send_kill_msg(self, socket):
socket.send(pycompletionserver.MSG_KILL_SERVER)
# Run for jython in command line:
# c:\bin\jython2.7.0\bin\jython.exe -m py.test tests\test_jyserver.py
@@ -0,0 +1,242 @@
import unittest
import os
import sys
import pytest
# Note: ant.jar and junit.jar must be in the PYTHONPATH (see jython_test_deps)
IS_JYTHON = False
if sys.platform.find('java') != -1:
IS_JYTHON = True
from _pydev_bundle._pydev_jy_imports_tipper import ismethod
from _pydev_bundle._pydev_jy_imports_tipper import isclass
from _pydev_bundle._pydev_jy_imports_tipper import dir_obj
from _pydev_bundle import _pydev_jy_imports_tipper
from java.lang.reflect import Method # @UnresolvedImport
from java.lang import System # @UnresolvedImport
from java.lang import String # @UnresolvedImport
from java.lang.System import arraycopy # @UnresolvedImport
from java.lang.System import out # @UnresolvedImport
import java.lang.String # @UnresolvedImport
import org.python.core.PyDictionary # @UnresolvedImport
__DBG = 0
def dbg(s):
if __DBG:
sys.stdout.write('%s\n' % (s,))
@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test')
class TestMod(unittest.TestCase):
def assert_args(self, tok, args, tips):
for a in tips:
if tok == a[0]:
self.assertEqual(args, a[2])
return
raise AssertionError('%s not in %s', tok, tips)
def assert_in(self, tok, tips):
self.assertEqual(4, len(tips[0]))
for a in tips:
if tok == a[0]:
return a
s = ''
for a in tips:
s += str(a)
s += '\n'
raise AssertionError('%s not in %s' % (tok, s))
def test_imports1a(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('java.util.HashMap')
if f is None:
return # Not ok with java 9
assert f.endswith('rt.jar')
def test_imports1c(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('java.lang.Class')
if f is None:
return # Not ok with java 9
assert f.endswith('rt.jar')
def test_imports1b(self):
try:
f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.m')
self.fail('err')
except:
pass
def test_imports1(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('junit.framework.TestCase')
assert f.endswith('junit.jar')
ret = self.assert_in('assertEquals', tip)
# self.assertEqual('', ret[2])
def test_imports2(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('junit.framework')
assert f.endswith('junit.jar')
ret = self.assert_in('TestCase', tip)
self.assertEqual('', ret[2])
def test_imports2a(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('org.apache.tools.ant')
assert f.endswith('ant.jar')
ret = self.assert_in('Task', tip)
self.assertEqual('', ret[2])
def test_imports3(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('os')
assert f.endswith('os.py')
ret = self.assert_in('path', tip)
self.assertEqual('', ret[2])
def test_tip_on_string(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('string')
self.assert_in('join', tip)
self.assert_in('uppercase', tip)
def test_imports(self):
tip = _pydev_jy_imports_tipper.generate_tip('__builtin__')[1]
self.assert_in('tuple' , tip)
self.assert_in('RuntimeError' , tip)
self.assert_in('RuntimeWarning' , tip)
def test_imports5(self):
f, tip = _pydev_jy_imports_tipper.generate_tip('java.lang')
if f is None:
return # Not ok with java 9
assert f.endswith('rt.jar')
tup = self.assert_in('String' , tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_CLASS), tup[3])
tip = _pydev_jy_imports_tipper.generate_tip('java')[1]
tup = self.assert_in('lang' , tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_IMPORT), tup[3])
tip = _pydev_jy_imports_tipper.generate_tip('java.lang.String')[1]
tup = self.assert_in('indexOf' , tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
tip = _pydev_jy_imports_tipper.generate_tip('java.lang.String')[1]
tup = self.assert_in('charAt' , tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
self.assertEqual('(int)', tup[2])
tup = self.assert_in('format' , tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
self.assertEqual('(string, objectArray)', tup[2])
self.assertTrue(tup[1].find('[Ljava.lang.Object;') == -1)
tup = self.assert_in('getBytes', tip)
self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
assert '[B' not in tup[1]
assert 'byte[]' in tup[1]
f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.str')
assert f is None or f.endswith('jython.jar') # Depends on jython version
self.assert_in('find' , tip)
f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.dict')
assert f is None or f.endswith('jython.jar') # Depends on jython version
self.assert_in('get' , tip)
@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test')
class TestSearch(unittest.TestCase):
def test_search_on_jython(self):
assert _pydev_jy_imports_tipper.search_definition('os')[0][0].split(os.sep)[-1] in ('javaos.py', 'os.py')
self.assertEqual(0, _pydev_jy_imports_tipper.search_definition('os')[0][1])
assert _pydev_jy_imports_tipper.search_definition('os.makedirs')[0][0].split(os.sep)[-1] in ('javaos.py', 'os.py')
self.assertNotEqual(0, _pydev_jy_imports_tipper.search_definition('os.makedirs')[0][1])
# print _pydev_jy_imports_tipper.search_definition('os.makedirs')
@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test')
class TestCompl(unittest.TestCase):
def test_getting_info_on_jython(self):
dbg('\n\n--------------------------- java')
assert not ismethod(java)[0]
assert not isclass(java)
assert _pydev_jy_imports_tipper.ismodule(java)
dbg('\n\n--------------------------- java.lang')
assert not ismethod(java.lang)[0]
assert not isclass(java.lang)
assert _pydev_jy_imports_tipper.ismodule(java.lang)
dbg('\n\n--------------------------- Method')
assert not ismethod(Method)[0]
assert isclass(Method)
dbg('\n\n--------------------------- System')
assert not ismethod(System)[0]
assert isclass(System)
dbg('\n\n--------------------------- String')
assert not ismethod(System)[0]
assert isclass(String)
assert len(dir_obj(String)) > 10
dbg('\n\n--------------------------- arraycopy')
isMet = ismethod(arraycopy)
assert isMet[0]
assert isMet[1][0].basic_as_str() == "function:arraycopy args=['java.lang.Object', 'int', 'java.lang.Object', 'int', 'int'], varargs=None, kwargs=None, docs:None"
assert not isclass(arraycopy)
dbg('\n\n--------------------------- out')
isMet = ismethod(out)
assert not isMet[0]
assert not isclass(out)
dbg('\n\n--------------------------- out.println')
isMet = ismethod(out.println) # @UndefinedVariable
assert isMet[0]
assert len(isMet[1]) == 10
self.assertEqual(isMet[1][0].basic_as_str(), "function:println args=[], varargs=None, kwargs=None, docs:None")
assert isMet[1][1].basic_as_str() == "function:println args=['long'], varargs=None, kwargs=None, docs:None"
assert not isclass(out.println) # @UndefinedVariable
dbg('\n\n--------------------------- str')
isMet = ismethod(str)
# the code below should work, but is failing on jython 22a1
# assert isMet[0]
# assert isMet[1][0].basic_as_str() == "function:str args=['org.python.core.PyObject'], varargs=None, kwargs=None, docs:None"
assert not isclass(str)
def met1():
a = 3
return a
dbg('\n\n--------------------------- met1')
isMet = ismethod(met1)
assert isMet[0]
assert isMet[1][0].basic_as_str() == "function:met1 args=[], varargs=None, kwargs=None, docs:None"
assert not isclass(met1)
def met2(arg1, arg2, *vararg, **kwarg):
'''docmet2'''
a = 1
return a
dbg('\n\n--------------------------- met2')
isMet = ismethod(met2)
assert isMet[0]
assert isMet[1][0].basic_as_str() == "function:met2 args=['arg1', 'arg2'], varargs=vararg, kwargs=kwarg, docs:docmet2"
assert not isclass(met2)
# Run for jython in command line:
# On Windows:
# c:/bin/jython2.7.0/bin/jython.exe -Dpython.path=jython_test_deps/ant.jar;jython_test_deps/junit.jar -m py.test tests/test_jysimpleTipper.py
# On Linux (different path separator for jars)
# jython -Dpython.path=jython_test_deps/ant.jar:jython_test_deps/junit.jar -m py.test tests/test_jysimpleTipper.py
@@ -0,0 +1,308 @@
import sys
import unittest
import threading
import os
from _pydev_bundle.pydev_imports import SimpleXMLRPCServer
from _pydev_bundle.pydev_localhost import get_localhost
from _pydev_bundle.pydev_console_utils import StdIn
import socket
import time
from _pydevd_bundle import pydevd_io
import pytest
def eq_(a, b):
if a != b:
raise AssertionError('%s != %s' % (a, b))
try:
from IPython import core
has_ipython = True
except:
has_ipython = False
@pytest.mark.skipif(not has_ipython, reason='IPython not available')
class TestBase(unittest.TestCase):
def setUp(self):
from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend
# PyDevFrontEnd depends on singleton in IPython, so you
# can't make multiple versions. So we reuse self.front_end for
# all the tests
self.front_end = get_pydev_frontend(get_localhost(), 0)
from pydev_ipython.inputhook import set_return_control_callback
set_return_control_callback(lambda:True)
self.front_end.clear_buffer()
def tearDown(self):
pass
def add_exec(self, code, expected_more=False):
more = self.front_end.add_exec(code)
eq_(expected_more, more)
def redirect_stdout(self):
from IPython.utils import io
self.original_stdout = sys.stdout
sys.stdout = io.stdout = pydevd_io.IOBuf()
def restore_stdout(self):
from IPython.utils import io
io.stdout = sys.stdout = self.original_stdout
@pytest.mark.skipif(not has_ipython, reason='IPython not available')
class TestPyDevFrontEnd(TestBase):
def testAddExec_1(self):
self.add_exec('if True:', True)
def testAddExec_2(self):
# Change: 'more' must now be controlled in the client side after the initial 'True' returned.
self.add_exec('if True:\n testAddExec_a = 10\n', False)
assert 'testAddExec_a' in self.front_end.get_namespace()
def testAddExec_3(self):
assert 'testAddExec_x' not in self.front_end.get_namespace()
self.add_exec('if True:\n testAddExec_x = 10\n\n')
assert 'testAddExec_x' in self.front_end.get_namespace()
eq_(self.front_end.get_namespace()['testAddExec_x'], 10)
def test_get_namespace(self):
assert 'testGetNamespace_a' not in self.front_end.get_namespace()
self.add_exec('testGetNamespace_a = 10')
assert 'testGetNamespace_a' in self.front_end.get_namespace()
eq_(self.front_end.get_namespace()['testGetNamespace_a'], 10)
def test_complete(self):
unused_text, matches = self.front_end.complete('%')
assert len(matches) > 1, 'at least one magic should appear in completions'
def test_complete_does_not_do_python_matches(self):
# Test that IPython's completions do not do the things that
# PyDev's completions will handle
self.add_exec('testComplete_a = 5')
self.add_exec('testComplete_b = 10')
self.add_exec('testComplete_c = 15')
unused_text, matches = self.front_end.complete('testComplete_')
assert len(matches) == 0
def testGetCompletions_1(self):
# Test the merged completions include the standard completions
self.add_exec('testComplete_a = 5')
self.add_exec('testComplete_b = 10')
self.add_exec('testComplete_c = 15')
res = self.front_end.getCompletions('testComplete_', 'testComplete_')
matches = [f[0] for f in res]
assert len(matches) == 3
eq_(set(['testComplete_a', 'testComplete_b', 'testComplete_c']), set(matches))
def testGetCompletions_2(self):
# Test that we get IPython completions in results
# we do this by checking kw completion which PyDev does
# not do by default
self.add_exec('def ccc(ABC=123): pass')
res = self.front_end.getCompletions('ccc(', '')
matches = [f[0] for f in res]
assert 'ABC=' in matches
def testGetCompletions_3(self):
# Test that magics return IPYTHON magic as type
res = self.front_end.getCompletions('%cd', '%cd')
assert len(res) == 1
eq_(res[0][3], '12') # '12' == IToken.TYPE_IPYTHON_MAGIC
assert len(res[0][1]) > 100, 'docstring for %cd should be a reasonably long string'
@pytest.mark.skipif(not has_ipython, reason='IPython not available')
class TestRunningCode(TestBase):
def test_print(self):
self.redirect_stdout()
try:
self.add_exec('print("output")')
eq_(sys.stdout.getvalue(), 'output\n')
finally:
self.restore_stdout()
def testQuestionMark_1(self):
self.redirect_stdout()
try:
self.add_exec('?')
found = sys.stdout.getvalue()
if len(found) < 1000:
raise AssertionError('Expected IPython help to be big. Found: %s' % (found,))
finally:
self.restore_stdout()
def testQuestionMark_2(self):
self.redirect_stdout()
try:
self.add_exec('int?')
found = sys.stdout.getvalue()
if 'Convert' not in found:
raise AssertionError('Expected to find "Convert" in %s' % (found,))
finally:
self.restore_stdout()
def test_gui(self):
try:
import Tkinter
except:
return
else:
from pydev_ipython.inputhook import get_inputhook
assert get_inputhook() is None
self.add_exec('%gui tk')
# we can't test the GUI works here because we aren't connected to XML-RPC so
# nowhere for hook to run
assert get_inputhook() is not None
self.add_exec('%gui none')
assert get_inputhook() is None
def test_history(self):
''' Make sure commands are added to IPython's history '''
self.redirect_stdout()
try:
self.add_exec('a=1')
self.add_exec('b=2')
_ih = self.front_end.get_namespace()['_ih']
eq_(_ih[-1], 'b=2')
eq_(_ih[-2], 'a=1')
self.add_exec('history')
hist = sys.stdout.getvalue().split('\n')
eq_(hist[-1], '')
eq_(hist[-2], 'history')
eq_(hist[-3], 'b=2')
eq_(hist[-4], 'a=1')
finally:
self.restore_stdout()
def test_edit(self):
''' Make sure we can issue an edit command'''
if os.environ.get('TRAVIS') == 'true':
# This test is too flaky on travis.
return
from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend
called_RequestInput = [False]
called_IPythonEditor = [False]
def start_client_thread(client_port):
class ClientThread(threading.Thread):
def __init__(self, client_port):
threading.Thread.__init__(self)
self.client_port = client_port
def run(self):
class HandleRequestInput:
def RequestInput(self):
called_RequestInput[0] = True
return '\n'
def IPythonEditor(self, name, line):
called_IPythonEditor[0] = (name, line)
return True
handle_request_input = HandleRequestInput()
from _pydev_bundle import pydev_localhost
self.client_server = client_server = SimpleXMLRPCServer(
(pydev_localhost.get_localhost(), self.client_port), logRequests=False)
client_server.register_function(handle_request_input.RequestInput)
client_server.register_function(handle_request_input.IPythonEditor)
client_server.serve_forever()
def shutdown(self):
return
self.client_server.shutdown()
client_thread = ClientThread(client_port)
client_thread.daemon = True
client_thread.start()
return client_thread
# PyDevFrontEnd depends on singleton in IPython, so you
# can't make multiple versions. So we reuse self.front_end for
# all the tests
s = socket.socket()
s.bind(('', 0))
self.client_port = client_port = s.getsockname()[1]
s.close()
self.front_end = get_pydev_frontend(get_localhost(), client_port)
client_thread = start_client_thread(self.client_port)
orig_stdin = sys.stdin
sys.stdin = StdIn(self, get_localhost(), self.client_port)
try:
filename = 'made_up_file.py'
self.add_exec('%edit ' + filename)
for i in range(10):
if called_IPythonEditor[0] == (os.path.abspath(filename), '0'):
break
time.sleep(.1)
if not called_IPythonEditor[0]:
# File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2883, in run_code
# exec(code_obj, self.user_global_ns, self.user_ns)
# File "<ipython-input-15-09583ca3bce1>", line 1, in <module>
# get_ipython().magic('edit made_up_file.py')
# File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2205, in magic
# return self.run_line_magic(magic_name, magic_arg_s)
# File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2126, in run_line_magic
# result = fn(*args,**kwargs)
# File "<string>", line 2, in edit
# File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/magic.py", line 193, in <lambda>
# call = lambda f, *a, **k: f(*a, **k)
# File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/magics/code.py", line 662, in edit
# self.shell.hooks.editor(filename,lineno)
# File "/home/travis/build/fabioz/PyDev.Debugger/pydev_ipython_console_011.py", line 70, in call_editor
# server.IPythonEditor(filename, str(line))
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1090, in __call__
# return self.__send(self.__name, args)
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1419, in __request
# verbose=self.__verbose
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1132, in request
# return self.single_request(host, handler, request_body, verbose)
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1143, in single_request
# http_conn = self.send_request(host, handler, request_body, verbose)
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1255, in send_request
# self.send_content(connection, request_body)
# File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1285, in send_content
# connection.endheaders(request_body)
# File "/home/travis/miniconda/lib/python3.3/http/client.py", line 1061, in endheaders
# self._send_output(message_body)
# File "/home/travis/miniconda/lib/python3.3/http/client.py", line 906, in _send_output
# self.send(msg)
# File "/home/travis/miniconda/lib/python3.3/http/client.py", line 844, in send
# self.connect()
# File "/home/travis/miniconda/lib/python3.3/http/client.py", line 822, in connect
# self.timeout, self.source_address)
# File "/home/travis/miniconda/lib/python3.3/socket.py", line 435, in create_connection
# raise err
# File "/home/travis/miniconda/lib/python3.3/socket.py", line 426, in create_connection
# sock.connect(sa)
# ConnectionRefusedError: [Errno 111] Connection refused
# I.e.: just warn that the test failing, don't actually fail.
sys.stderr.write('Test failed: this test is brittle in travis because sometimes the connection is refused (as above) and we do not have a callback.\n')
return
eq_(called_IPythonEditor[0], (os.path.abspath(filename), '0'))
assert called_RequestInput[0], "Make sure the 'wait' parameter has been respected"
finally:
sys.stdin = orig_stdin
client_thread.shutdown()
@@ -0,0 +1,277 @@
import threading
import unittest
import sys
import pydevconsole
from _pydev_bundle.pydev_imports import xmlrpclib, SimpleXMLRPCServer
from _pydevd_bundle import pydevd_io
from contextlib import contextmanager
import pytest
try:
from ast import PyCF_ALLOW_TOP_LEVEL_AWAIT # @UnusedImport
CAN_EVALUATE_TOP_LEVEL_ASYNC = True
except:
CAN_EVALUATE_TOP_LEVEL_ASYNC = False
#=======================================================================================================================
# Test
#=======================================================================================================================
class Test(unittest.TestCase):
@contextmanager
def interpreter(self):
self.original_stdout = sys.stdout
self.original_stderr = sys.stderr
sys.stdout = pydevd_io.IOBuf()
sys.stderr = pydevd_io.IOBuf()
try:
sys.stdout.encoding = sys.stdin.encoding
sys.stderr.encoding = sys.stdin.encoding
except AttributeError:
# In Python 3 encoding is not writable (whereas in Python 2 it doesn't exist).
pass
try:
client_port, _server_port = self.get_free_addresses()
client_thread = self.start_client_thread(client_port) # @UnusedVariable
import time
time.sleep(.3) # let's give it some time to start the threads
from _pydev_bundle import pydev_localhost
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.current_thread())
yield interpreter
except:
# if there's some error, print the output to the actual output.
self.original_stdout.write(sys.stdout.getvalue())
self.original_stderr.write(sys.stderr.getvalue())
raise
finally:
sys.stderr = self.original_stderr
sys.stdout = self.original_stdout
def test_console_hello(self):
with self.interpreter() as interpreter:
(result,) = interpreter.hello("Hello pydevconsole")
self.assertEqual(result, "Hello eclipse")
@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async.')
def test_console_async(self):
with self.interpreter() as interpreter:
from _pydev_bundle.pydev_console_utils import CodeFragment
more = interpreter.add_exec(CodeFragment('''
async def async_func(a):
return a
'''))
assert not more
assert not sys.stderr.getvalue()
assert not sys.stdout.getvalue()
more = interpreter.add_exec(CodeFragment('''x = await async_func(1111)'''))
assert not more
assert not sys.stderr.getvalue()
assert not sys.stdout.getvalue()
more = interpreter.add_exec(CodeFragment('''print(x)'''))
assert not more
assert not sys.stderr.getvalue()
assert '1111' in sys.stdout.getvalue()
def test_console_requests(self):
with self.interpreter() as interpreter:
from _pydev_bundle.pydev_console_utils import CodeFragment
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 = input()'))
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.getCompletions('foo.', 'foo.')
self.assertTrue(
('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \
'Found: %s' % comps
)
comps = interpreter.getCompletions('"".', '"".')
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.getCompletions('', '')
for c in completions:
if c[0] == 'AssertionError':
break
else:
self.fail('Could not find AssertionError')
completions = interpreter.getCompletions('Assert', 'Assert')
for c in completions:
if c[0] == 'RuntimeError':
self.fail('Did not expect to find RuntimeError there')
assert ('__doc__', None, '', '3') not in interpreter.getCompletions('foo.CO', 'foo.')
comps = interpreter.getCompletions('va', 'va')
assert ('val', '', '', '3') in comps or ('val', '', '', '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('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('join(self: str, sequence: list) -> str') >= 0 or
desc.find('Concatenate any number of strings.') >= 0 or
desc.find('bound method str.join') >= 0, # PyPy
"Could not recognize: %s" % (desc,))
def start_client_thread(self, client_port):
class ClientThread(threading.Thread):
def __init__(self, client_port):
threading.Thread.__init__(self)
self.client_port = client_port
def run(self):
class HandleRequestInput:
def RequestInput(self):
client_thread.requested_input = True
return 'input_request'
def NotifyFinished(self, *args, **kwargs):
client_thread.notified_finished += 1
return 1
handle_request_input = HandleRequestInput()
from _pydev_bundle import pydev_localhost
client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
client_server.register_function(handle_request_input.RequestInput)
client_server.register_function(handle_request_input.NotifyFinished)
client_server.serve_forever()
client_thread = ClientThread(client_port)
client_thread.requested_input = False
client_thread.notified_finished = 0
client_thread.daemon = True
client_thread.start()
return client_thread
def start_debugger_server_thread(self, debugger_port, socket_code):
class DebuggerServerThread(threading.Thread):
def __init__(self, debugger_port, socket_code):
threading.Thread.__init__(self)
self.debugger_port = debugger_port
self.socket_code = socket_code
def run(self):
import socket
s = socket.socket()
s.bind(('', debugger_port))
s.listen(1)
socket, unused_addr = s.accept()
socket_code(socket)
debugger_thread = DebuggerServerThread(debugger_port, socket_code)
debugger_thread.daemon = True
debugger_thread.start()
return debugger_thread
def get_free_addresses(self):
from _pydev_bundle.pydev_localhost import get_socket_names
socket_names = get_socket_names(2, True)
port0 = socket_names[0][1]
port1 = socket_names[1][1]
assert port0 != port1
assert port0 > 0
assert port1 > 0
return port0, port1
def test_server(self):
self.original_stdout = sys.stdout
sys.stdout = pydevd_io.IOBuf()
try:
client_port, server_port = self.get_free_addresses()
class ServerThread(threading.Thread):
def __init__(self, client_port, server_port):
threading.Thread.__init__(self)
self.client_port = client_port
self.server_port = server_port
def run(self):
from _pydev_bundle import pydev_localhost
pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port)
server_thread = ServerThread(client_port, server_port)
server_thread.daemon = True
server_thread.start()
client_thread = self.start_client_thread(client_port) # @UnusedVariable
import time
time.sleep(.3) # let's give it some time to start the threads
sys.stdout = pydevd_io.IOBuf()
from _pydev_bundle import pydev_localhost
server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
server.execLine('class Foo:')
server.execLine(' pass')
server.execLine('')
server.execLine('foo = Foo()')
server.execLine('a = input()')
server.execLine('print (a)')
initial = time.time()
while not client_thread.requested_input:
if time.time() - initial > 2:
raise AssertionError('Did not get the return asked before the timeout.')
time.sleep(.1)
found = sys.stdout.getvalue()
while ['input_request'] != found.split():
found += sys.stdout.getvalue()
if time.time() - initial > 2:
break
time.sleep(.1)
self.assertEqual(['input_request'], found.split())
finally:
sys.stdout = self.original_stdout
@@ -0,0 +1,155 @@
import sys
from _pydev_bundle._pydev_saved_modules import thread
import pycompletionserver
import socket
from urllib.parse import quote_plus
start_new_thread = thread.start_new_thread
BUILTIN_MOD = 'builtins'
def send(s, msg):
s.send(bytearray(msg, 'utf-8'))
import unittest
class TestCPython(unittest.TestCase):
def test_message(self):
t = pycompletionserver.CompletionServer(0)
l = []
l.append(('Def', 'description' , 'args'))
l.append(('Def1', 'description1', 'args1'))
l.append(('Def2', 'description2', 'args2'))
msg = t.processor.format_completion_message(None, l)
self.assertEqual('@@COMPLETIONS(None,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg)
l = []
l.append(('Def', 'desc,,r,,i()ption', ''))
l.append(('Def(1', 'descriptio(n1', ''))
l.append(('De,f)2', 'de,s,c,ription2', ''))
msg = t.processor.format_completion_message(None, l)
self.assertEqual('@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@', msg)
def create_connections(self):
'''
Creates the connections needed for testing.
'''
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((pycompletionserver.HOST, 0))
server.listen(1) # socket to receive messages.
t = pycompletionserver.CompletionServer(server.getsockname()[1])
t.exit_process_on_kill = False
start_new_thread(t.run, ())
s, _addr = server.accept()
return t, s
def read_msg(self):
finish = False
msg = ''
while finish == False:
m = self.socket.recv(1024 * 4)
m = m.decode('utf-8')
if m.startswith('@@PROCESSING'):
sys.stdout.write('Status msg: %s\n' % (msg,))
else:
msg += m
if msg.find('END@@') != -1:
finish = True
return msg
def test_completion_sockets_and_messages(self):
t, socket = self.create_connections()
self.socket = socket
try:
# now that we have the connections all set up, check the code completion messages.
msg = quote_plus('math')
send(socket, '@@IMPORTS:%sEND@@' % msg) # math completions
completions = self.read_msg()
# print_ unquote_plus(completions)
# math is a builtin and because of that, it starts with None as a file
start = '@@COMPLETIONS(None,(__doc__,'
start_2 = '@@COMPLETIONS(None,(__name__,'
if ('/math.so,' in completions or
'/math.cpython-33m.so,' in completions or
'/math.cpython-34m.so,' in completions or
'math.cpython-35m' in completions or
'math.cpython-36m' in completions or
'math.cpython-37m' in completions or
'math.cpython-38' in completions or
'math.cpython-39' in completions or
'math.cpython-310' in completions or
'math.cpython-311' in completions
):
return
self.assertTrue(completions.startswith(start) or completions.startswith(start_2), '%s DOESNT START WITH %s' % (completions, (start, start_2)))
self.assertTrue('@@COMPLETIONS' in completions)
self.assertTrue('END@@' in completions)
# now, test i
msg = quote_plus('%s.list' % BUILTIN_MOD)
send(socket, "@@IMPORTS:%s\nEND@@" % msg)
found = self.read_msg()
self.assertTrue('sort' in found, 'Could not find sort in: %s' % (found,))
# now, test search
msg = quote_plus('inspect.ismodule')
send(socket, '@@SEARCH%sEND@@' % msg) # math completions
found = self.read_msg()
self.assertTrue('inspect.py' in found)
for i in range(33, 100):
if str(i) in found:
break
else:
self.fail('Could not find the ismodule line in %s' % (found,))
# now, test search
msg = quote_plus('inspect.CO_NEWLOCALS')
send(socket, '@@SEARCH%sEND@@' % msg) # math completions
found = self.read_msg()
self.assertTrue('inspect.py' in found)
self.assertTrue('CO_NEWLOCALS' in found)
# now, test search
msg = quote_plus('inspect.BlockFinder.tokeneater')
send(socket, '@@SEARCH%sEND@@' % msg)
found = self.read_msg()
self.assertTrue('inspect.py' in found)
# self.assertTrue('CO_NEWLOCALS' in found)
# reload modules test
# send(socket, '@@RELOAD_MODULES_END@@')
# ok = self.read_msg()
# self.assertEqual('@@MSG_OK_END@@' , ok)
# this test is not executed because it breaks our current enviroment.
finally:
try:
sys.stdout.write('succedded...sending kill msg\n')
self.send_kill_msg(socket)
# while not hasattr(t, 'ended'):
# pass #wait until it receives the message and quits.
socket.close()
self.socket.close()
except:
pass
def send_kill_msg(self, socket):
socket.send(pycompletionserver.MSG_KILL_SERVER)
@@ -0,0 +1,243 @@
'''
@author Fabio Zadrozny
'''
from _pydev_bundle import _pydev_imports_tipper
import inspect
import pytest
import sys
import unittest
try:
import __builtin__ # @UnusedImport
BUILTIN_MOD = '__builtin__'
except ImportError:
BUILTIN_MOD = 'builtins'
IS_JYTHON = sys.platform.find('java') != -1
HAS_WX = False
@pytest.mark.skipif(IS_JYTHON, reason='CPython related test')
class TestCPython(unittest.TestCase):
def p(self, t):
for a in t:
sys.stdout.write('%s\n' % (a,))
def test_imports3(self):
tip = _pydev_imports_tipper.generate_tip('os')
ret = self.assert_in('path', tip)
self.assertEqual('', ret[2])
def test_imports2(self):
try:
tip = _pydev_imports_tipper.generate_tip('OpenGL.GLUT')
self.assert_in('glutDisplayFunc', tip)
self.assert_in('glutInitDisplayMode', tip)
except ImportError:
pass
def test_imports4(self):
try:
tip = _pydev_imports_tipper.generate_tip('mx.DateTime.mxDateTime.mxDateTime')
self.assert_in('now', tip)
except ImportError:
pass
def test_imports5(self):
tip = _pydev_imports_tipper.generate_tip('%s.list' % BUILTIN_MOD)
s = self.assert_in('sort', tip)
self.check_args(
s,
'(cmp=None, key=None, reverse=False)',
'(self, object cmp, object key, bool reverse)',
'(self, cmp: object, key: object, reverse: bool)',
'(key=None, reverse=False)',
'(self, key=None, reverse=False)',
'(self, cmp, key, reverse)',
'(self, key, reverse)',
)
def test_imports2a(self):
tips = _pydev_imports_tipper.generate_tip('%s.RuntimeError' % BUILTIN_MOD)
self.assert_in('__doc__', tips)
def test_imports2b(self):
try:
file
except:
pass
else:
tips = _pydev_imports_tipper.generate_tip('%s' % BUILTIN_MOD)
t = self.assert_in('file' , tips)
self.assertTrue('->' in t[1].strip() or 'file' in t[1])
def test_imports2c(self):
try:
file # file is not available on py 3
except:
pass
else:
tips = _pydev_imports_tipper.generate_tip('%s.file' % BUILTIN_MOD)
t = self.assert_in('readlines' , tips)
self.assertTrue('->' in t[1] or 'sizehint' in t[1])
def test_imports(self):
'''
You can print_ the results to check...
'''
if HAS_WX:
tip = _pydev_imports_tipper.generate_tip('wxPython.wx')
self.assert_in('wxApp' , tip)
tip = _pydev_imports_tipper.generate_tip('wxPython.wx.wxApp')
try:
tip = _pydev_imports_tipper.generate_tip('qt')
self.assert_in('QWidget' , tip)
self.assert_in('QDialog' , tip)
tip = _pydev_imports_tipper.generate_tip('qt.QWidget')
self.assert_in('rect' , tip)
self.assert_in('rect' , tip)
self.assert_in('AltButton' , tip)
tip = _pydev_imports_tipper.generate_tip('qt.QWidget.AltButton')
self.assert_in('__xor__' , tip)
tip = _pydev_imports_tipper.generate_tip('qt.QWidget.AltButton.__xor__')
self.assert_in('__class__' , tip)
except ImportError:
pass
tip = _pydev_imports_tipper.generate_tip(BUILTIN_MOD)
# for t in tip[1]:
# print_ t
self.assert_in('object' , tip)
self.assert_in('tuple' , tip)
self.assert_in('list' , tip)
self.assert_in('RuntimeError' , tip)
self.assert_in('RuntimeWarning' , tip)
# Remove cmp as it's not available on py 3
# t = self.assert_in('cmp' , tip)
# self.check_args(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
t = self.assert_in('isinstance' , tip)
self.check_args(
t,
'(object, class_or_type_or_tuple)',
'(object o, type typeinfo)',
'(o: object, typeinfo: type)',
'(obj, class_or_tuple)',
'(obj, klass_or_tuple)',
) # args
t = self.assert_in('compile' , tip)
self.check_args(
t,
'(source, filename, mode)',
'()',
'(o: object, name: str, val: object)',
'(source, filename, mode, flags, dont_inherit, optimize)',
'(source, filename, mode, flags, dont_inherit)',
'(source, filename, mode, flags, dont_inherit, optimize, _feature_version=-1)'
) # args
t = self.assert_in('setattr' , tip)
self.check_args(
t,
'(object, name, value)',
'(object o, str name, object val)',
'(o: object, name: str, val: object)',
'(obj, name, value)',
'(object, name, val)',
) # args
try:
import compiler
compiler_module = 'compiler'
except ImportError:
try:
import ast
compiler_module = 'ast'
except ImportError:
compiler_module = None
if compiler_module is not None: # Not available in iron python
tip = _pydev_imports_tipper.generate_tip(compiler_module)
if compiler_module == 'compiler':
self.assert_args('parse', '(buf, mode)', tip)
self.assert_args('walk', '(tree, visitor, walker, verbose)', tip)
self.assert_in('parseFile' , tip)
else:
self.assert_args('parse', [
'(source, filename, mode)',
'(source, filename, mode, type_comments=False, feature_version=None)'
], tip
)
self.assert_args('walk', '(node)', tip)
self.assert_in('parse' , tip)
def check_args(self, t, *expected):
for x in expected:
if x == t[2]:
return
self.fail('Found: %s. Expected: %s' % (t[2], expected))
def assert_args(self, tok, args, tips):
if not isinstance(args, (list, tuple)):
args = (args,)
for a in tips[1]:
if tok == a[0]:
for arg in args:
if arg == a[2]:
return
raise AssertionError('%s not in %s', a[2], args)
raise AssertionError('%s not in %s', tok, tips)
def assert_in(self, tok, tips):
for a in tips[1]:
if tok == a[0]:
return a
raise AssertionError('%s not in %s' % (tok, tips))
def test_search(self):
s = _pydev_imports_tipper.search_definition('inspect.ismodule')
(f, line, col), foundAs = s
self.assertTrue(line > 0)
def test_dot_net_libraries(self):
if sys.platform == 'cli':
tip = _pydev_imports_tipper.generate_tip('System.Drawing')
self.assert_in('Brushes' , tip)
tip = _pydev_imports_tipper.generate_tip('System.Drawing.Brushes')
self.assert_in('Aqua' , tip)
def test_tips_hasattr_failure(self):
class MyClass(object):
def __getattribute__(self, attr):
raise RuntimeError()
obj = MyClass()
_pydev_imports_tipper.generate_imports_tip_for_module(obj)
def test_inspect(self):
class C(object):
def metA(self, a, b):
pass
obj = C.metA
if inspect.ismethod (obj):
pass
# print_ obj.im_func
# print_ inspect.getargspec(obj.im_func)