Adding upstream version 3.0.29.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
51331ec610
commit
b6d29f411e
6 changed files with 90 additions and 13 deletions
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
||||||
- name: Type Checker
|
- name: Type Checker
|
||||||
run: |
|
run: |
|
||||||
mypy ptpython
|
mypy ptpython
|
||||||
ruff .
|
ruff check .
|
||||||
ruff format --check .
|
ruff format --check .
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
|
|
20
CHANGELOG
20
CHANGELOG
|
@ -1,6 +1,26 @@
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
3.0.29: 2024-07-22
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- Further improve performance of dictionary completions.
|
||||||
|
|
||||||
|
|
||||||
|
3.0.28: 2024-07-22
|
||||||
|
------------------
|
||||||
|
|
||||||
|
New features:
|
||||||
|
- Custom 'exit' function to return from REPL that
|
||||||
|
* doesn't terminate `sys.stdin` when `exit` is called (important for
|
||||||
|
`embed()`).
|
||||||
|
* doesn't require to be called with parentheses.
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- Clean up signatures on control-c.
|
||||||
|
|
||||||
|
|
||||||
3.0.27: 2024-05-27
|
3.0.27: 2024-05-27
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -476,20 +476,34 @@ class DictionaryCompleter(Completer):
|
||||||
Complete dictionary keys.
|
Complete dictionary keys.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def meta_repr(value: object) -> Callable[[], str]:
|
def meta_repr(obj: object, key: object) -> Callable[[], str]:
|
||||||
"Abbreviate meta text, make sure it fits on one line."
|
"Abbreviate meta text, make sure it fits on one line."
|
||||||
|
cached_result: str | None = None
|
||||||
|
|
||||||
# We return a function, so that it gets computed when it's needed.
|
# We return a function, so that it gets computed when it's needed.
|
||||||
# When there are many completions, that improves the performance
|
# When there are many completions, that improves the performance
|
||||||
# quite a bit (for the multi-column completion menu, we only need
|
# quite a bit (for the multi-column completion menu, we only need
|
||||||
# to display one meta text).
|
# to display one meta text).
|
||||||
|
# Note that we also do the lookup itself in here (`obj[key]`),
|
||||||
|
# because this part can also be slow for some mapping
|
||||||
|
# implementations.
|
||||||
def get_value_repr() -> str:
|
def get_value_repr() -> str:
|
||||||
text = self._do_repr(value)
|
nonlocal cached_result
|
||||||
|
if cached_result is not None:
|
||||||
|
return cached_result
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = obj[key] # type: ignore
|
||||||
|
|
||||||
|
text = self._do_repr(value)
|
||||||
|
except BaseException:
|
||||||
|
return "-"
|
||||||
|
|
||||||
# Take first line, if multiple lines.
|
# Take first line, if multiple lines.
|
||||||
if "\n" in text:
|
if "\n" in text:
|
||||||
text = text.split("\n", 1)[0] + "..."
|
text = text.split("\n", 1)[0] + "..."
|
||||||
|
|
||||||
|
cached_result = text
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return get_value_repr
|
return get_value_repr
|
||||||
|
@ -504,24 +518,24 @@ class DictionaryCompleter(Completer):
|
||||||
# If this object is a dictionary, complete the keys.
|
# If this object is a dictionary, complete the keys.
|
||||||
if isinstance(result, (dict, collections_abc.Mapping)):
|
if isinstance(result, (dict, collections_abc.Mapping)):
|
||||||
# Try to evaluate the key.
|
# Try to evaluate the key.
|
||||||
key_obj = key
|
key_obj_str = str(key)
|
||||||
for k in [key, key + '"', key + "'"]:
|
for k in [key, key + '"', key + "'"]:
|
||||||
try:
|
try:
|
||||||
key_obj = ast.literal_eval(k)
|
key_obj_str = str(ast.literal_eval(k))
|
||||||
except (SyntaxError, ValueError):
|
except (SyntaxError, ValueError):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
for k, v in result.items():
|
for k in result:
|
||||||
if str(k).startswith(str(key_obj)):
|
if str(k).startswith(key_obj_str):
|
||||||
try:
|
try:
|
||||||
k_repr = self._do_repr(k)
|
k_repr = self._do_repr(k)
|
||||||
yield Completion(
|
yield Completion(
|
||||||
k_repr + "]",
|
k_repr + "]",
|
||||||
-len(key),
|
-len(key),
|
||||||
display=f"[{k_repr}]",
|
display=f"[{k_repr}]",
|
||||||
display_meta=meta_repr(v),
|
display_meta=meta_repr(result, k),
|
||||||
)
|
)
|
||||||
except ReprFailedError:
|
except ReprFailedError:
|
||||||
pass
|
pass
|
||||||
|
@ -537,7 +551,7 @@ class DictionaryCompleter(Completer):
|
||||||
k_repr + "]",
|
k_repr + "]",
|
||||||
-len(key),
|
-len(key),
|
||||||
display=f"[{k_repr}]",
|
display=f"[{k_repr}]",
|
||||||
display_meta=meta_repr(result[k]),
|
display_meta=meta_repr(result, k),
|
||||||
)
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# `result[k]` lookup failed. Trying to complete
|
# `result[k]` lookup failed. Trying to complete
|
||||||
|
|
|
@ -1116,4 +1116,5 @@ class PythonInput:
|
||||||
return result
|
return result
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# Abort - try again.
|
# Abort - try again.
|
||||||
|
self.signatures = []
|
||||||
self.default_buffer.document = Document()
|
self.default_buffer.document = Document()
|
||||||
|
|
|
@ -20,7 +20,7 @@ import types
|
||||||
import warnings
|
import warnings
|
||||||
from dis import COMPILER_FLAG_NAMES
|
from dis import COMPILER_FLAG_NAMES
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, ContextManager, Iterable, Sequence
|
from typing import Any, Callable, ContextManager, Iterable, NoReturn, Sequence
|
||||||
|
|
||||||
from prompt_toolkit.formatted_text import OneStyleAndTextTuple
|
from prompt_toolkit.formatted_text import OneStyleAndTextTuple
|
||||||
from prompt_toolkit.patch_stdout import patch_stdout as patch_stdout_context
|
from prompt_toolkit.patch_stdout import patch_stdout as patch_stdout_context
|
||||||
|
@ -40,7 +40,15 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PyCF_ALLOW_TOP_LEVEL_AWAIT = 0
|
PyCF_ALLOW_TOP_LEVEL_AWAIT = 0
|
||||||
|
|
||||||
__all__ = ["PythonRepl", "enable_deprecation_warnings", "run_config", "embed"]
|
|
||||||
|
__all__ = [
|
||||||
|
"PythonRepl",
|
||||||
|
"enable_deprecation_warnings",
|
||||||
|
"run_config",
|
||||||
|
"embed",
|
||||||
|
"exit",
|
||||||
|
"ReplExit",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def _get_coroutine_flag() -> int | None:
|
def _get_coroutine_flag() -> int | None:
|
||||||
|
@ -91,9 +99,16 @@ class PythonRepl(PythonInput):
|
||||||
raise
|
raise
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
raise
|
raise
|
||||||
|
except ReplExit:
|
||||||
|
raise
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
self._handle_exception(e)
|
self._handle_exception(e)
|
||||||
else:
|
else:
|
||||||
|
if isinstance(result, exit):
|
||||||
|
# When `exit` is evaluated without parentheses.
|
||||||
|
# Automatically trigger the `ReplExit` exception.
|
||||||
|
raise ReplExit
|
||||||
|
|
||||||
# Print.
|
# Print.
|
||||||
if result is not None:
|
if result is not None:
|
||||||
self._show_result(result)
|
self._show_result(result)
|
||||||
|
@ -155,7 +170,10 @@ class PythonRepl(PythonInput):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Run it; display the result (or errors if applicable).
|
# Run it; display the result (or errors if applicable).
|
||||||
self.run_and_show_expression(text)
|
try:
|
||||||
|
self.run_and_show_expression(text)
|
||||||
|
except ReplExit:
|
||||||
|
return
|
||||||
finally:
|
finally:
|
||||||
if self.terminal_title:
|
if self.terminal_title:
|
||||||
clear_title()
|
clear_title()
|
||||||
|
@ -383,6 +401,7 @@ class PythonRepl(PythonInput):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
globals["get_ptpython"] = get_ptpython
|
globals["get_ptpython"] = get_ptpython
|
||||||
|
globals["exit"] = exit()
|
||||||
|
|
||||||
def _remove_from_namespace(self) -> None:
|
def _remove_from_namespace(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -459,6 +478,29 @@ def run_config(repl: PythonInput, config_file: str | None = None) -> None:
|
||||||
enter_to_continue()
|
enter_to_continue()
|
||||||
|
|
||||||
|
|
||||||
|
class exit:
|
||||||
|
"""
|
||||||
|
Exit the ptpython REPL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This custom exit function ensures that the `embed` function returns from
|
||||||
|
# where we are embedded, and Python doesn't close `sys.stdin` like
|
||||||
|
# the default `exit` from `_sitebuiltins.Quitter` does.
|
||||||
|
|
||||||
|
def __call__(self) -> NoReturn:
|
||||||
|
raise ReplExit
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
# (Same message as the built-in Python REPL.)
|
||||||
|
return "Use exit() or Ctrl-D (i.e. EOF) to exit"
|
||||||
|
|
||||||
|
|
||||||
|
class ReplExit(Exception):
|
||||||
|
"""
|
||||||
|
Exception raised by ptpython's exit function.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def embed(
|
def embed(
|
||||||
globals: dict[str, Any] | None = None,
|
globals: dict[str, Any] | None = None,
|
||||||
locals: dict[str, Any] | None = None,
|
locals: dict[str, Any] | None = None,
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -11,7 +11,7 @@ with open(os.path.join(os.path.dirname(__file__), "README.rst")) as f:
|
||||||
setup(
|
setup(
|
||||||
name="ptpython",
|
name="ptpython",
|
||||||
author="Jonathan Slenders",
|
author="Jonathan Slenders",
|
||||||
version="3.0.27",
|
version="3.0.29",
|
||||||
url="https://github.com/prompt-toolkit/ptpython",
|
url="https://github.com/prompt-toolkit/ptpython",
|
||||||
description="Python REPL build on top of prompt_toolkit",
|
description="Python REPL build on top of prompt_toolkit",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
|
Loading…
Add table
Reference in a new issue