utils.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """
  2. Utilities for end-users.
  3. """
  4. import __main__
  5. from collections import namedtuple
  6. import logging
  7. import traceback
  8. import re
  9. import os
  10. import sys
  11. from jedi import Interpreter
  12. READLINE_DEBUG = False
  13. def setup_readline(namespace_module=__main__, fuzzy=False):
  14. """
  15. This function sets up :mod:`readline` to use Jedi in a Python interactive
  16. shell.
  17. If you want to use a custom ``PYTHONSTARTUP`` file (typically
  18. ``$HOME/.pythonrc.py``), you can add this piece of code::
  19. try:
  20. from jedi.utils import setup_readline
  21. except ImportError:
  22. # Fallback to the stdlib readline completer if it is installed.
  23. # Taken from http://docs.python.org/2/library/rlcompleter.html
  24. print("Jedi is not installed, falling back to readline")
  25. try:
  26. import readline
  27. import rlcompleter
  28. readline.parse_and_bind("tab: complete")
  29. except ImportError:
  30. print("Readline is not installed either. No tab completion is enabled.")
  31. else:
  32. setup_readline()
  33. This will fallback to the readline completer if Jedi is not installed.
  34. The readline completer will only complete names in the global namespace,
  35. so for example::
  36. ran<TAB>
  37. will complete to ``range``.
  38. With Jedi the following code::
  39. range(10).cou<TAB>
  40. will complete to ``range(10).count``, this does not work with the default
  41. cPython :mod:`readline` completer.
  42. You will also need to add ``export PYTHONSTARTUP=$HOME/.pythonrc.py`` to
  43. your shell profile (usually ``.bash_profile`` or ``.profile`` if you use
  44. bash).
  45. """
  46. if READLINE_DEBUG:
  47. logging.basicConfig(
  48. filename='/tmp/jedi.log',
  49. filemode='a',
  50. level=logging.DEBUG
  51. )
  52. class JediRL:
  53. def complete(self, text, state):
  54. """
  55. This complete stuff is pretty weird, a generator would make
  56. a lot more sense, but probably due to backwards compatibility
  57. this is still the way how it works.
  58. The only important part is stuff in the ``state == 0`` flow,
  59. everything else has been copied from the ``rlcompleter`` std.
  60. library module.
  61. """
  62. if state == 0:
  63. sys.path.insert(0, os.getcwd())
  64. # Calling python doesn't have a path, so add to sys.path.
  65. try:
  66. logging.debug("Start REPL completion: " + repr(text))
  67. interpreter = Interpreter(text, [namespace_module.__dict__])
  68. completions = interpreter.complete(fuzzy=fuzzy)
  69. logging.debug("REPL completions: %s", completions)
  70. self.matches = [
  71. text[:len(text) - c._like_name_length] + c.name_with_symbols
  72. for c in completions
  73. ]
  74. except:
  75. logging.error("REPL Completion error:\n" + traceback.format_exc())
  76. raise
  77. finally:
  78. sys.path.pop(0)
  79. try:
  80. return self.matches[state]
  81. except IndexError:
  82. return None
  83. try:
  84. # Need to import this one as well to make sure it's executed before
  85. # this code. This didn't use to be an issue until 3.3. Starting with
  86. # 3.4 this is different, it always overwrites the completer if it's not
  87. # already imported here.
  88. import rlcompleter # noqa: F401
  89. import readline
  90. except ImportError:
  91. print("Jedi: Module readline not available.")
  92. else:
  93. readline.set_completer(JediRL().complete)
  94. readline.parse_and_bind("tab: complete")
  95. # jedi itself does the case matching
  96. readline.parse_and_bind("set completion-ignore-case on")
  97. # because it's easier to hit the tab just once
  98. readline.parse_and_bind("set show-all-if-unmodified")
  99. readline.parse_and_bind("set show-all-if-ambiguous on")
  100. # don't repeat all the things written in the readline all the time
  101. readline.parse_and_bind("set completion-prefix-display-length 2")
  102. # No delimiters, Jedi handles that.
  103. readline.set_completer_delims('')
  104. def version_info():
  105. """
  106. Returns a namedtuple of Jedi's version, similar to Python's
  107. ``sys.version_info``.
  108. """
  109. Version = namedtuple('Version', 'major, minor, micro')
  110. from jedi import __version__
  111. tupl = re.findall(r'[a-z]+|\d+', __version__)
  112. return Version(*[x if i == 3 else int(x) for i, x in enumerate(tupl)])