diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1b81f5ee..3fe9d310 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,10 @@ jobs: - 30.2 # - snapshot python_version: + - 3.11 - 3.12 + - 3.13 + - 3.14 steps: # Checkout - uses: actions/checkout@v4 diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..e4fba218 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/elpy/tests/support.py b/elpy/tests/support.py index ff76d477..7446d01b 100644 --- a/elpy/tests/support.py +++ b/elpy/tests/support.py @@ -618,20 +618,31 @@ def test_should_raise_fault(self): class RPCGetCalltipTests(GenericRPCTests): METHOD = "rpc_get_calltip" + def _assert_thread_calltip(self, actual): + """Assert that a Thread calltip has the expected structure. + + We check name and index exactly, and verify that all known-stable + params are present. Extra params (added in newer Python versions) + are allowed. + """ + self.assertEqual(actual['name'], 'Thread') + self.assertEqual(actual['index'], 0) + for param in self.THREAD_CALLTIP_REQUIRED_PARAMS: + self.assertIn(param, actual['params']) + def test_should_get_calltip(self): - expected = self.THREAD_CALLTIP source, offset = source_and_offset( "import threading\nthreading.Thread(_|_") filename = self.project_file("test.py", source) calltip = self.backend.rpc_get_calltip(filename, source, offset) - self.assertEqual(calltip, expected) + self._assert_thread_calltip(calltip) calltip = self.backend.rpc_get_calltip_or_oneline_docstring(filename, source, offset) calltip.pop('kind') - self.assertEqual(calltip, expected) + self._assert_thread_calltip(calltip) def test_should_get_calltip_even_after_parens(self): source, offset = source_and_offset( @@ -640,12 +651,12 @@ def test_should_get_calltip_even_after_parens(self): actual = self.backend.rpc_get_calltip(filename, source, offset) - self.assertEqual(self.THREAD_CALLTIP, actual) + self._assert_thread_calltip(actual) actual = self.backend.rpc_get_calltip_or_oneline_docstring(filename, source, offset) actual.pop('kind') - self.assertEqual(self.THREAD_CALLTIP, actual) + self._assert_thread_calltip(actual) def test_should_get_calltip_at_closing_paren(self): source, offset = source_and_offset( @@ -654,7 +665,7 @@ def test_should_get_calltip_at_closing_paren(self): actual = self.backend.rpc_get_calltip(filename, source, offset) - self.assertEqual(self.THREAD_CALLTIP, actual) + self._assert_thread_calltip(actual) actual = self.backend.rpc_get_calltip_or_oneline_docstring(filename, source, offset) diff --git a/elpy/tests/test_jedibackend.py b/elpy/tests/test_jedibackend.py index 12a5b8a8..75cb0c0c 100644 --- a/elpy/tests/test_jedibackend.py +++ b/elpy/tests/test_jedibackend.py @@ -95,16 +95,17 @@ def __init__(self, *args, **kwargs): ' ``bytearray`` instance containing a JSON' ' document) to a Python object.' ) - if sys.version_info >= (3, 12): - self.JSON_DOCSTRING = ( - "JSON (JavaScript Object Notation) " - " is a subset of JavaScript syntax (ECMA-262" - " 3rd edition) used as a lightweight data interchange format.") - else: - self.JSON_DOCSTRING = ( - "JSON (JavaScript Object Notation) " - " is a subset of JavaScript syntax (ECMA-262" - " 3rd edition) used as a lightweight data interchange format.") + # The json module docstring URL changed from http to https in + # CPython 3.12, but jedi uses bundled typeshed stubs which may + # have either version regardless of runtime. We don't set + # JSON_DOCSTRING here; instead we override check_module_docstring. + + def check_module_docstring(self, docstring): + # Accept either http or https since jedi's typeshed stubs may differ + self.assertIn("JSON (JavaScript Object Notation)