ec5f52c7c6
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>
141 lines
4.2 KiB
Python
141 lines
4.2 KiB
Python
'''
|
|
@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
|