microsoft / microsoft/multilspy

Tests fails to clean up test environment on Windows if test doesn't pass (PermissionError)

Open
#95 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
610
Forks
111
PR merge metrics
No merged PRs in 30d

Description

If test passes, there's no issues

py -m pytest -p no:pytest-blender tests\multilspy\test_multilspy_python.py
# tests\multilspy\test_multilspy_python.py::test_multilspy_python_black PASSED

But if test fails, it fails with the error below and folder .multispy/hash is not removed.

To make it fail, let's add exception to this part:
https://github.com/microsoft/multilspy/blob/db809145c4f516e07ef88801b5137e48430a47c5/tests/multilspy/test_multilspy_python.py#L30-L34

E.g.

        async with lsp.start_server():
            raise Exception
            result = await lsp.request_definition(str(PurePath("src/black/mode.py")), 163, 4)

Error:

tests\multilspy\test_multilspy_python.py::test_multilspy_python_black FAILED

================================================================================= FAILURES =================================================================================
_______________________________________________________________________ test_multilspy_python_black ________________________________________________________________________

    @pytest.mark.asyncio
    async def test_multilspy_python_black():
        """
        Test the working of multilspy with python repository - black
        """
        code_language = Language.PYTHON
        params = {
            "code_language": code_language,
            "repo_url": "https://github.com/psf/black/",
            "repo_commit": "f3b50e466969f9142393ec32a4b2a383ffbe5f23"
        }
        with create_test_context(params) as context:
            lsp = LanguageServer.create(context.config, context.logger, context.source_directory)

            # All the communication with the language server must be performed inside the context manager
            # The server process is started when the context manager is entered and is terminated when the context manager is exited.
            # The context manager is an asynchronous context manager, so it must be used with async with.
            async with lsp.start_server():
>               raise Exception
E               Exception

tests\multilspy\test_multilspy_python.py:31: Exception

During handling of the above exception, another exception occurred:

    @pytest.mark.asyncio
    async def test_multilspy_python_black():
        """
        Test the working of multilspy with python repository - black
        """
        code_language = Language.PYTHON
        params = {
            "code_language": code_language,
            "repo_url": "https://github.com/psf/black/",
            "repo_commit": "f3b50e466969f9142393ec32a4b2a383ffbe5f23"
        }
>       with create_test_context(params) as context:

tests\multilspy\test_multilspy_python.py:24:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\software\Python311\Lib\contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
tests\test_utils.py:36: in create_test_context
    shutil.rmtree(temp_extract_directory)
C:\software\Python311\Lib\shutil.py:787: in rmtree
    return _rmtree_unsafe(path, onerror)
C:\software\Python311\Lib\shutil.py:629: in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
C:\software\Python311\Lib\shutil.py:638: in _rmtree_unsafe
    onerror(os.rmdir, path, sys.exc_info())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

path = 'C:\\.multilspy\\eced8f41c8ca472697ff15b023cbb571\\black-f3b50e466969f9142393ec32a4b2a383ffbe5f23'
onerror = <function rmtree.<locals>.onerror at 0x0000020844806C00>

    def _rmtree_unsafe(path, onerror):
        try:
            with os.scandir(path) as scandir_it:
                entries = list(scandir_it)
        except OSError:
            onerror(os.scandir, path, sys.exc_info())
            entries = []
        for entry in entries:
            fullname = entry.path
            if _rmtree_isdir(entry):
                try:
                    if entry.is_symlink():
                        # This can only happen if someone replaces
                        # a directory with a symlink after the call to
                        # os.scandir or entry.is_dir above.
                        raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(os.path.islink, fullname, sys.exc_info())
                    continue
                _rmtree_unsafe(fullname, onerror)
            else:
                try:
                    os.unlink(fullname)
                except OSError:
                    onerror(os.unlink, fullname, sys.exc_info())
        try:
>           os.rmdir(path)
E           PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\.multilspy\\eced8f41c8ca472697ff15b023cbb571\\black-f3b50e466969f9142393ec32a4b2a383ffbe5f23'

C:\software\Python311\Lib\shutil.py:636: PermissionError
---------------------------------------------------------------------------- Captured log call -----------------------------------------------------------------------------
INFO     multilspy:multilspy_logger.py:56 {"time": "2025-03-29 11:26:29", "level": "INFO", "caller_file": "multilspy\\tests\\..\\src\\multilspy\\language_servers\\jedi_language_server\\jedi_server.py", "caller_name": "start_server", "caller_line": 99, "message": "Starting jedi-language-server server process"}
INFO     multilspy:multilspy_logger.py:56 {"time": "2025-03-29 11:26:29", "level": "INFO", "caller_file": "multilspy\\tests\\..\\src\\multilspy\\language_servers\\jedi_language_server\\jedi_server.py", "caller_name": "start_server", "caller_line": 103, "message": "Sending initialize request from LSP client to LSP server and awaiting response"}
========================================================================= short test summary info ==========================================================================
FAILED tests\multilspy\test_multilspy_python.py::test_multilspy_python_black - PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\.multilspy\\eced8f41c8ca472697ff15b02...
============================================================================ 1 failed in 3.83s =============================================================================

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with create_test_context in tests/test_utils.py and the failing test in tests/multilspy/test_multilspy_python.py. Run the provided pytest command on Windows with an exception inside lsp.start_server(). Done means the temporary .multilspy directory is removed without a PermissionError when the test fails.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.