From 7a6e27222c3bebdbaeb83c63676e99b0d93df133 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Mon, 13 Apr 2020 12:22:11 +0100 Subject: [PATCH 01/11] Expanded completion annotations to include type hints --- elpy/jedibackend.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/elpy/jedibackend.py b/elpy/jedibackend.py index e33d3e8a2..053f2970b 100644 --- a/elpy/jedibackend.py +++ b/elpy/jedibackend.py @@ -46,7 +46,7 @@ def rpc_get_completions(self, filename, source, offset): for proposal in proposals) return [{'name': proposal.name.rstrip("="), 'suffix': proposal.complete.rstrip("="), - 'annotation': proposal.type, + 'annotation': get_annotation(proposal), 'meta': proposal.description} for proposal in proposals] @@ -263,7 +263,13 @@ def rpc_get_oneline_docstring(self, filename, source, offset): else: onelinedoc = onelinedoc[0] if onelinedoc == '': - onelinedoc = "No documentation" + if definition.type == "instance": + try: + onelinedoc = definition.get_type_hint() + except AttributeError: + onelinedoc = "No documentation" + else: + onelinedoc = "No documentation" return {"name": name, "doc": onelinedoc} return None @@ -362,6 +368,17 @@ def linecol_to_pos(text, line, col): return offset +def get_annotation(proposal): + if proposal.type in ("instance", "statement", "param"): + try: + hint = proposal.get_type_hint() + except AttributeError: + hint = "" + return "{} ({})".format(proposal.type, hint) + else: + return proposal.type + + def run_with_debug(jedi, name, *args, **kwargs): re_raise = kwargs.pop('re_raise', ()) try: From 7b4c3615461c2ce040a03b62d1b97f95926d4ae3 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sat, 2 May 2020 13:10:57 +0100 Subject: [PATCH 02/11] Retain previous annotation formatting where type hint not available --- elpy/jedibackend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elpy/jedibackend.py b/elpy/jedibackend.py index 053f2970b..21b2ced4f 100644 --- a/elpy/jedibackend.py +++ b/elpy/jedibackend.py @@ -371,10 +371,10 @@ def linecol_to_pos(text, line, col): def get_annotation(proposal): if proposal.type in ("instance", "statement", "param"): try: - hint = proposal.get_type_hint() + hint = " ({})".format(proposal.get_type_hint()) except AttributeError: hint = "" - return "{} ({})".format(proposal.type, hint) + return proposal.type + hint else: return proposal.type From e7b83c127b6045990957bc3ac5d2a4bcb5ceb238 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sat, 2 May 2020 13:11:33 +0100 Subject: [PATCH 03/11] Added test for completion with type hint --- test/elpy-rpc-get-completions-test.el | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index 86443b008..3ea823d20 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -33,6 +33,22 @@ (should (string= (alist-get 'meta compl2) "def addition2")) (should (string= (alist-get 'annotation compl2) "function"))))) +(ert-deftest elpy-rpc-get-completions-should-include-type-hints () + (elpy-testcase ((:project project-root "test.py") + (:emacs-required "25.1")) + (find-file (f-join project-root "test.py")) + (elpy-enable) + (python-mode) + (insert "test_var: int = 3\n" + "test_") + (let* ((compls (elpy-rpc-get-completions)) + (compl1 (car compls)) + (compl2 (car (cdr compls)))) + (should (string= (alist-get 'name compl1) "test_var")) + (should (string= (alist-get 'suffix compl1) "var")) + (should (string= (alist-get 'meta compl1) "test_var: int = 3")) + (should (string= (alist-get 'annotation compl1) "statement (int)"))))) + (ert-deftest elpy-rpc-get-completions-should-not-return-completion-for-numbers () (elpy-testcase ((:project project-root "test.py") (:emacs-required "25.1")) From b7c882f1921e7449eb9410f9d4da4da7fbeb8a7a Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sat, 2 May 2020 14:10:01 +0100 Subject: [PATCH 04/11] Included type hints for function completion proposals --- elpy/jedibackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elpy/jedibackend.py b/elpy/jedibackend.py index 21b2ced4f..57ef4833b 100644 --- a/elpy/jedibackend.py +++ b/elpy/jedibackend.py @@ -369,7 +369,7 @@ def linecol_to_pos(text, line, col): def get_annotation(proposal): - if proposal.type in ("instance", "statement", "param"): + if proposal.type in ("instance", "statement", "param", "function"): try: hint = " ({})".format(proposal.get_type_hint()) except AttributeError: From 45ef103e1bc2205b6af3e894d6fe9d562ea138c2 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sat, 2 May 2020 16:57:00 +0100 Subject: [PATCH 05/11] Incremented jedi dependency to 0.17.0 --- requirements-rpc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-rpc.txt b/requirements-rpc.txt index c34c65a47..4a78b466f 100644 --- a/requirements-rpc.txt +++ b/requirements-rpc.txt @@ -1,4 +1,4 @@ -jedi==0.16.0 +jedi==0.17.0 rope==0.16.0 autopep8==1.5 yapf==0.29 From 07bf67e1867d3c6cc7d383e403e731a469785ac2 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sun, 3 May 2020 11:06:37 +0100 Subject: [PATCH 06/11] Cover additional exceptions that jedi can throw --- elpy/jedibackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elpy/jedibackend.py b/elpy/jedibackend.py index 57ef4833b..09b969962 100644 --- a/elpy/jedibackend.py +++ b/elpy/jedibackend.py @@ -372,7 +372,7 @@ def get_annotation(proposal): if proposal.type in ("instance", "statement", "param", "function"): try: hint = " ({})".format(proposal.get_type_hint()) - except AttributeError: + except (AttributeError, TypeError, NotImplementedError): hint = "" return proposal.type + hint else: From 2572a34d52b8cef39ac2ea49a0550748f8968fa7 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Sun, 3 May 2020 16:42:20 +0100 Subject: [PATCH 07/11] Updated expected output of completion tests --- test/elpy-rpc-get-completions-test.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index 3ea823d20..95efc4c54 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -27,11 +27,11 @@ (should (string= (alist-get 'name compl1) "addition")) (should (string= (alist-get 'suffix compl1) "ition")) (should (string= (alist-get 'meta compl1) "def addition")) - (should (string= (alist-get 'annotation compl1) "function")) + (should (string= (alist-get 'annotation compl1) "function (addition(x, y))")) (should (string= (alist-get 'name compl2) "addition2")) (should (string= (alist-get 'suffix compl2) "ition2")) (should (string= (alist-get 'meta compl2) "def addition2")) - (should (string= (alist-get 'annotation compl2) "function"))))) + (should (string= (alist-get 'annotation compl2) "function (addition2(x, y))"))))) (ert-deftest elpy-rpc-get-completions-should-include-type-hints () (elpy-testcase ((:project project-root "test.py") @@ -74,4 +74,4 @@ (should (string= (alist-get 'name compl) "foo12345")) (should (string= (alist-get 'suffix compl) "345")) (should (string= (alist-get 'meta compl) "def foo12345")) - (should (string= (alist-get 'annotation compl) "function"))))) + (should (string= (alist-get 'annotation compl) "function (foo12345(x, y))"))))) From f95e11acb6dce4b59054b51e63108ffeff779508 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Wed, 20 May 2020 22:05:23 +0100 Subject: [PATCH 08/11] Simplified type hint test --- test/elpy-rpc-get-completions-test.el | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index 95efc4c54..e98649272 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -41,13 +41,12 @@ (python-mode) (insert "test_var: int = 3\n" "test_") - (let* ((compls (elpy-rpc-get-completions)) - (compl1 (car compls)) - (compl2 (car (cdr compls)))) - (should (string= (alist-get 'name compl1) "test_var")) - (should (string= (alist-get 'suffix compl1) "var")) - (should (string= (alist-get 'meta compl1) "test_var: int = 3")) - (should (string= (alist-get 'annotation compl1) "statement (int)"))))) + (let ((compl (car (elpy-rpc-get-completions)))) + (should (string= (alist-get 'name compl) "test_var")) + (should (string= (alist-get 'suffix compl) "var")) + (should (string= (alist-get 'meta compl) "test_var: int = 3")) + (should (string= (alist-get 'annotation compl) "statement (int)"))))) + (ert-deftest elpy-rpc-get-completions-should-not-return-completion-for-numbers () (elpy-testcase ((:project project-root "test.py") From a11242c2d9990db8185e67634a9525ac3bdaa6ba Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Wed, 20 May 2020 22:06:17 +0100 Subject: [PATCH 09/11] Added conditional execution for type hint test - python>=3.6 --- test/elpy-rpc-get-completions-test.el | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index e98649272..9ef5e6290 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -1,3 +1,16 @@ +(defsubst elpy-rpc-get-completions--type-hints-supported () + (if (boundp '*elpy-rpc-get-completions--type-hints-supported*) + *elpy-rpc-get-completions--type-hints-supported* + (setq *elpy-rpc-get-completions--type-hints-supported* + (not (string< (or (getenv "TRAVIS_PYTHON_VERSION") + (with-temp-buffer + (call-process elpy-rpc-python-command + nil '(t t) nil "--version") + (goto-char (point-min)) + (re-search-forward "\\([0-9.]+\\)" nil t) + (or (match-string 1) ""))) + "3.6"))))) + (ert-deftest elpy-rpc-get-completions () (elpy-testcase () (mletf* ((called-args nil) @@ -33,7 +46,9 @@ (should (string= (alist-get 'meta compl2) "def addition2")) (should (string= (alist-get 'annotation compl2) "function (addition2(x, y))"))))) -(ert-deftest elpy-rpc-get-completions-should-include-type-hints () + +(when (elpy-rpc-get-completions--type-hints-supported) + (ert-deftest elpy-rpc-get-completions-should-include-type-hints () (elpy-testcase ((:project project-root "test.py") (:emacs-required "25.1")) (find-file (f-join project-root "test.py")) @@ -45,7 +60,7 @@ (should (string= (alist-get 'name compl) "test_var")) (should (string= (alist-get 'suffix compl) "var")) (should (string= (alist-get 'meta compl) "test_var: int = 3")) - (should (string= (alist-get 'annotation compl) "statement (int)"))))) + (should (string= (alist-get 'annotation compl) "statement (int)")))))) (ert-deftest elpy-rpc-get-completions-should-not-return-completion-for-numbers () From 30f3c17d272afc5afe926ba65f86b4b43340121d Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Wed, 20 May 2020 22:37:08 +0100 Subject: [PATCH 10/11] Workaround for FileNotFoundError bug in Jedi --- elpy/jedibackend.py | 2 +- test/elpy-rpc-get-completions-test.el | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/elpy/jedibackend.py b/elpy/jedibackend.py index 09b969962..940ffbd74 100644 --- a/elpy/jedibackend.py +++ b/elpy/jedibackend.py @@ -372,7 +372,7 @@ def get_annotation(proposal): if proposal.type in ("instance", "statement", "param", "function"): try: hint = " ({})".format(proposal.get_type_hint()) - except (AttributeError, TypeError, NotImplementedError): + except (AttributeError, TypeError, NotImplementedError, NameError): hint = "" return proposal.type + hint else: diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index 9ef5e6290..72cad7703 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -23,6 +23,14 @@ (nil "" 0) nil nil)))))) +;; temporary workaround for bug in jedi==0.17.0 +;; see https://github.com/davidhalter/jedi/pull/1589 +(setq annot1 "function" + annot2 "function") +(when (elpy-rpc-get-completions--type-hints-supported) + (setq annot1 "function (addition(x, y))" + annot2 "function (addition2(x, y))")) + (ert-deftest elpy-rpc-get-completions-should-return-completion () (elpy-testcase ((:project project-root "test.py") (:emacs-required "25.1")) @@ -40,11 +48,11 @@ (should (string= (alist-get 'name compl1) "addition")) (should (string= (alist-get 'suffix compl1) "ition")) (should (string= (alist-get 'meta compl1) "def addition")) - (should (string= (alist-get 'annotation compl1) "function (addition(x, y))")) + (should (string= (alist-get 'annotation compl1) annot1)) (should (string= (alist-get 'name compl2) "addition2")) (should (string= (alist-get 'suffix compl2) "ition2")) (should (string= (alist-get 'meta compl2) "def addition2")) - (should (string= (alist-get 'annotation compl2) "function (addition2(x, y))"))))) + (should (string= (alist-get 'annotation compl2) annot2))))) (when (elpy-rpc-get-completions--type-hints-supported) @@ -75,6 +83,12 @@ (let ((compl (elpy-rpc-get-completions))) (should (equal compl nil))))) +;; temporary workaround for bug in jedi==0.17.0 +;; see https://github.com/davidhalter/jedi/pull/1589 +(setq annot3 "function") +(when (elpy-rpc-get-completions--type-hints-supported) + (setq annot3 "function (foo12345(x, y))")) + (ert-deftest elpy-rpc-get-completions-should-return-completion-for-variable-with-numbers () (elpy-testcase ((:project project-root "test.py") (:emacs-required "25.1")) @@ -88,4 +102,4 @@ (should (string= (alist-get 'name compl) "foo12345")) (should (string= (alist-get 'suffix compl) "345")) (should (string= (alist-get 'meta compl) "def foo12345")) - (should (string= (alist-get 'annotation compl) "function (foo12345(x, y))"))))) + (should (string= (alist-get 'annotation compl) annot3))))) From b6537edb2dc49fc5663fc1294069f05daf41c0b5 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Thu, 21 May 2020 09:18:11 +0100 Subject: [PATCH 11/11] Discriminate between python 2.7 and python 3.5 cases --- test/elpy-rpc-get-completions-test.el | 29 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/test/elpy-rpc-get-completions-test.el b/test/elpy-rpc-get-completions-test.el index 72cad7703..e84f9a399 100644 --- a/test/elpy-rpc-get-completions-test.el +++ b/test/elpy-rpc-get-completions-test.el @@ -11,6 +11,19 @@ (or (match-string 1) ""))) "3.6"))))) +(defsubst elpy-rpc-get-completions--python-2 () + (if (boundp '*elpy-rpc-get-completions--python-2*) + *elpy-rpc-get-completions--python-2* + (setq *elpy-rpc-get-completions--python-2* + (string< (or (getenv "TRAVIS_PYTHON_VERSION") + (with-temp-buffer + (call-process elpy-rpc-python-command + nil '(t t) nil "--version") + (goto-char (point-min)) + (re-search-forward "\\([0-9.]+\\)" nil t) + (or (match-string 1) ""))) + "3.5")))) + (ert-deftest elpy-rpc-get-completions () (elpy-testcase () (mletf* ((called-args nil) @@ -25,11 +38,11 @@ ;; temporary workaround for bug in jedi==0.17.0 ;; see https://github.com/davidhalter/jedi/pull/1589 -(setq annot1 "function" - annot2 "function") -(when (elpy-rpc-get-completions--type-hints-supported) - (setq annot1 "function (addition(x, y))" - annot2 "function (addition2(x, y))")) +(setq annot1 "function (addition(x, y))" + annot2 "function (addition2(x, y))") +(when (elpy-rpc-get-completions--python-2) + (setq annot1 "function" + annot2 "function")) (ert-deftest elpy-rpc-get-completions-should-return-completion () (elpy-testcase ((:project project-root "test.py") @@ -85,9 +98,9 @@ ;; temporary workaround for bug in jedi==0.17.0 ;; see https://github.com/davidhalter/jedi/pull/1589 -(setq annot3 "function") -(when (elpy-rpc-get-completions--type-hints-supported) - (setq annot3 "function (foo12345(x, y))")) +(setq annot3 "function (foo12345(x, y))") +(when (elpy-rpc-get-completions--python-2) + (setq annot3 "function")) (ert-deftest elpy-rpc-get-completions-should-return-completion-for-variable-with-numbers () (elpy-testcase ((:project project-root "test.py")