1
0
Fork 0

Merging upstream version 3.0.27.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 18:34:28 +01:00
parent 479a0e81b5
commit 7807e8a7bd
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
25 changed files with 105 additions and 56 deletions

View file

@ -1,6 +1,13 @@
CHANGELOG
=========
3.0.27: 2024-05-27
------------------
- Limit number of completions to 5k (for performance).
- Several typing fixes.
3.0.26: 2024-02-06
------------------

View file

@ -12,7 +12,7 @@ ptpython
.. image :: https://github.com/jonathanslenders/ptpython/raw/master/docs/images/example1.png
Ptpython is an advanced Python REPL. It should work on all
Python versions from 2.6 up to 3.9 and work cross platform (Linux,
Python versions from 2.6 up to 3.11 and work cross platform (Linux,
BSD, OS X and Windows).
Note: this version of ptpython requires at least Python 3.6. Install ptpython
@ -255,6 +255,22 @@ Windows. Some things might not work, but it is usable:
.. image :: https://github.com/jonathanslenders/ptpython/raw/master/docs/images/windows.png
Windows terminal integration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are using the `Windows Terminal <https://aka.ms/terminal>`_ and want to
integrate ``ptpython`` as a profile, go to *Settings -> Open JSON file* and add the
following profile under *profiles.list*:
.. code-block:: JSON
{
"commandline": "%SystemRoot%\\System32\\cmd.exe /k ptpython",
"guid": "{f91d49a3-741b-409c-8a15-c4360649121f}",
"hidden": false,
"icon": "https://upload.wikimedia.org/wikipedia/commons/e/e6/Python_Windows_interpreter_icon_2006%E2%80%932016_Tiny.png",
"name": "ptpython@cmd"
}
FAQ
***
@ -288,12 +304,12 @@ Special thanks to
- `wcwidth <https://github.com/jquast/wcwidth>`_: Determine columns needed for a wide characters.
- `prompt_toolkit <http://github.com/jonathanslenders/python-prompt-toolkit>`_ for the interface.
.. |Build Status| image:: https://api.travis-ci.org/prompt-toolkit/ptpython.svg?branch=master
:target: https://travis-ci.org/prompt-toolkit/ptpython#
.. |Build Status| image:: https://github.com/prompt-toolkit/ptpython/actions/workflows/test.yaml/badge.svg
:target: https://github.com/prompt-toolkit/ptpython/actions/workflows/test.yaml
.. |License| image:: https://img.shields.io/github/license/prompt-toolkit/ptpython.svg
:target: https://github.com/prompt-toolkit/ptpython/blob/master/LICENSE
.. |PyPI| image:: https://pypip.in/version/ptpython/badge.svg
:target: https://pypi.python.org/pypi/ptpython/
.. |PyPI| image:: https://img.shields.io/pypi/v/ptpython.svg
:target: https://pypi.org/project/ptpython/
:alt: Latest Version

View file

@ -11,6 +11,7 @@ The ``patch_stdout`` option makes sure that when another coroutine is writing
to stdout, it won't break the input line, but instead writes nicely above the
prompt.
"""
import asyncio
from ptpython.repl import embed

View file

@ -5,6 +5,7 @@ This requires Python 3, asyncio and asyncssh.
Run this example and then SSH to localhost, port 8222.
"""
import asyncio
import logging

View file

@ -5,6 +5,7 @@ Copy this file to $XDG_CONFIG_HOME/ptpython/config.py
On Linux, this is: ~/.config/ptpython/config.py
On macOS, this is: ~/Library/Application Support/ptpython/config.py
"""
from prompt_toolkit.filters import ViInsertMode
from prompt_toolkit.key_binding.key_processor import KeyPress
from prompt_toolkit.keys import Keys

View file

@ -2,6 +2,7 @@
"""
Example of embedding a Python REPL, and setting a custom prompt.
"""
from prompt_toolkit.formatted_text import HTML, AnyFormattedText
from ptpython.prompt_style import PromptStyle

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
"""
""" """
from ptpython.repl import embed

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
"""
""" """
from ptpython.python_input import PythonInput

View file

@ -5,6 +5,7 @@ Example of running ptpython in another thread.
(For testing whether it's working fine if it's not embedded in the main
thread.)
"""
import threading
from ptpython.repl import embed

View file

@ -1,6 +1,7 @@
"""
Make `python -m ptpython` an alias for running `./ptpython`.
"""
from __future__ import annotations
from .entry_points.run_ptpython import run

View file

@ -6,6 +6,7 @@ import inspect
import keyword
import re
from enum import Enum
from itertools import islice
from typing import TYPE_CHECKING, Any, Callable, Iterable
from prompt_toolkit.completion import (
@ -617,7 +618,10 @@ class HidePrivateCompleter(Completer):
def get_completions(
self, document: Document, complete_event: CompleteEvent
) -> Iterable[Completion]:
completions = list(self.completer.get_completions(document, complete_event))
completions = list(
# Limit at 5k completions for performance.
islice(self.completer.get_completions(document, complete_event), 0, 5000)
)
complete_private_attributes = self.complete_private_attributes()
hide_private = False

View file

@ -6,6 +6,7 @@ Note that the code in this file is Python 3 only. However, we
should make sure not to use Python 3-only syntax, because this
package should be installable in Python 2 as well!
"""
from __future__ import annotations
import asyncio

View file

@ -22,6 +22,7 @@ environment variables:
PTPYTHON_CONFIG_HOME: a configuration directory to use
PYTHONSTARTUP: file executed on interactive startup (no default)
"""
from __future__ import annotations
import argparse

View file

@ -7,6 +7,7 @@ way we don't block the UI of for instance ``turtle`` and other Tk libraries.
in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
will fix it for Tk.)
"""
from __future__ import annotations
import sys
@ -23,9 +24,8 @@ def _inputhook_tk(inputhook_context: InputHookContext) -> None:
Run the Tk eventloop until prompt-toolkit needs to process the next input.
"""
# Get the current TK application.
import tkinter
import _tkinter # Keep this imports inline!
import tkinter
root = tkinter._default_root # type: ignore

View file

@ -4,6 +4,7 @@ Utility to easily select lines from the history and execute them again.
`create_history_application` creates an `Application` instance that runs will
run as a sub application of the Repl/PythonInput.
"""
from __future__ import annotations
from functools import partial
@ -410,7 +411,7 @@ class HistoryMapping:
if len(history_strings) > HISTORY_COUNT:
history_lines[0] = (
"# *** History has been truncated to %s lines ***" % HISTORY_COUNT
f"# *** History has been truncated to {HISTORY_COUNT} lines ***"
)
self.history_lines = history_lines

View file

@ -8,6 +8,7 @@ also the power of for instance all the %-magic functions that IPython has to
offer.
"""
from __future__ import annotations
from typing import Iterable
@ -156,7 +157,7 @@ class MagicsCompleter(Completer):
for m in sorted(self.magics_manager.magics["line"]):
if m.startswith(text):
yield Completion("%s" % m, -len(text))
yield Completion(f"{m}", -len(text))
class AliasCompleter(Completer):
@ -172,7 +173,7 @@ class AliasCompleter(Completer):
for a, cmd in sorted(aliases, key=lambda a: a[0]):
if a.startswith(text):
yield Completion("%s" % a, -len(text), display_meta=cmd)
yield Completion(f"{a}", -len(text), display_meta=cmd)
class IPythonInput(PythonInput):
@ -279,9 +280,8 @@ def initialize_extensions(shell, extensions):
shell.extension_manager.load_extension(ext)
except:
warn(
"Error in loading extension: %s" % ext
+ "\nCheck your config files in %s"
% ipy_utils.path.get_ipython_dir()
f"Error in loading extension: {ext}"
+ f"\nCheck your config files in {ipy_utils.path.get_ipython_dir()}"
)
shell.showtraceback()

View file

@ -1,6 +1,7 @@
"""
Creation of the `Layout` instance for the Python input/REPL.
"""
from __future__ import annotations
import platform
@ -131,7 +132,7 @@ def python_sidebar(python_input: PythonInput) -> Window:
tokens.append(("class:sidebar" + sel, " >" if selected else " "))
tokens.append(("class:sidebar.label" + sel, "%-24s" % label, select_item))
tokens.append(("class:sidebar.status" + sel, " ", select_item))
tokens.append(("class:sidebar.status" + sel, "%s" % status, goto_next))
tokens.append(("class:sidebar.status" + sel, f"{status}", goto_next))
if selected:
tokens.append(("[SetCursorPosition]", ""))
@ -528,7 +529,7 @@ def create_exit_confirmation(
def get_text_fragments() -> StyleAndTextTuples:
# Show "Do you really want to exit?"
return [
(style, "\n %s ([y]/n) " % python_input.exit_message),
(style, f"\n {python_input.exit_message} ([y]/n) "),
("[SetCursorPosition]", ""),
(style, " \n"),
]

View file

@ -48,7 +48,7 @@ class IPythonPrompt(PromptStyle):
def in_prompt(self) -> AnyFormattedText:
return [
("class:in", "In ["),
("class:in.number", "%s" % self.python_input.current_statement_index),
("class:in.number", f"{self.python_input.current_statement_index}"),
("class:in", "]: "),
]
@ -58,7 +58,7 @@ class IPythonPrompt(PromptStyle):
def out_prompt(self) -> AnyFormattedText:
return [
("class:out", "Out["),
("class:out.number", "%s" % self.python_input.current_statement_index),
("class:out.number", f"{self.python_input.current_statement_index}"),
("class:out", "]:"),
("", " "),
]

View file

@ -2,6 +2,7 @@
Application for reading Python input.
This can be used for creation of Python REPLs.
"""
from __future__ import annotations
from asyncio import get_running_loop
@ -98,8 +99,7 @@ if TYPE_CHECKING:
class _SupportsLessThan(Protocol):
# Taken from typeshed. _T_lt is used by "sorted", which needs anything
# sortable.
def __lt__(self, __other: Any) -> bool:
...
def __lt__(self, __other: Any) -> bool: ...
_T_lt = TypeVar("_T_lt", bound="_SupportsLessThan")
@ -347,14 +347,6 @@ class PythonInput:
"classic": ClassicPrompt(),
}
self.get_input_prompt = lambda: self.all_prompt_styles[
self.prompt_style
].in_prompt()
self.get_output_prompt = lambda: self.all_prompt_styles[
self.prompt_style
].out_prompt()
#: Load styles.
self.code_styles: dict[str, BaseStyle] = get_all_code_styles()
self.ui_styles = get_all_ui_styles()
@ -425,6 +417,12 @@ class PythonInput:
else:
self._app = None
def get_input_prompt(self) -> AnyFormattedText:
return self.all_prompt_styles[self.prompt_style].in_prompt()
def get_output_prompt(self) -> AnyFormattedText:
return self.all_prompt_styles[self.prompt_style].out_prompt()
def _accept_handler(self, buff: Buffer) -> bool:
app = get_app()
app.exit(result=buff.text)
@ -880,18 +878,18 @@ class PythonInput:
Option(
title="Min brightness",
description="Minimum brightness for the color scheme (default=0.0).",
get_current_value=lambda: "%.2f" % self.min_brightness,
get_current_value=lambda: f"{self.min_brightness:.2f}",
get_values=lambda: {
"%.2f" % value: partial(self._set_min_brightness, value)
f"{value:.2f}": partial(self._set_min_brightness, value)
for value in brightness_values
},
),
Option(
title="Max brightness",
description="Maximum brightness for the color scheme (default=1.0).",
get_current_value=lambda: "%.2f" % self.max_brightness,
get_current_value=lambda: f"{self.max_brightness:.2f}",
get_values=lambda: {
"%.2f" % value: partial(self._set_max_brightness, value)
f"{value:.2f}": partial(self._set_max_brightness, value)
for value in brightness_values
},
),

View file

@ -7,6 +7,7 @@ Utility for creating a Python repl.
embed(globals(), locals(), vi_mode=False)
"""
from __future__ import annotations
import asyncio
@ -18,7 +19,8 @@ import traceback
import types
import warnings
from dis import COMPILER_FLAG_NAMES
from typing import Any, Callable, ContextManager, Iterable
from pathlib import Path
from typing import Any, Callable, ContextManager, Iterable, Sequence
from prompt_toolkit.formatted_text import OneStyleAndTextTuple
from prompt_toolkit.patch_stdout import patch_stdout as patch_stdout_context
@ -63,7 +65,7 @@ def _has_coroutine_flag(code: types.CodeType) -> bool:
class PythonRepl(PythonInput):
def __init__(self, *a, **kw) -> None:
self._startup_paths = kw.pop("startup_paths", None)
self._startup_paths: Sequence[str | Path] | None = kw.pop("startup_paths", None)
super().__init__(*a, **kw)
self._load_start_paths()
@ -347,7 +349,7 @@ class PythonRepl(PythonInput):
def get_compiler_flags(self) -> int:
return super().get_compiler_flags() | PyCF_ALLOW_TOP_LEVEL_AWAIT
def _compile_with_flags(self, code: str, mode: str):
def _compile_with_flags(self, code: str, mode: str) -> Any:
"Compile code with the right compiler flags."
return compile(
code,
@ -458,13 +460,13 @@ def run_config(repl: PythonInput, config_file: str | None = None) -> None:
def embed(
globals=None,
locals=None,
globals: dict[str, Any] | None = None,
locals: dict[str, Any] | None = None,
configure: Callable[[PythonRepl], None] | None = None,
vi_mode: bool = False,
history_filename: str | None = None,
title: str | None = None,
startup_paths=None,
startup_paths: Sequence[str | Path] | None = None,
patch_stdout: bool = False,
return_asyncio_coroutine: bool = False,
) -> None:
@ -493,10 +495,10 @@ def embed(
locals = locals or globals
def get_globals():
def get_globals() -> dict[str, Any]:
return globals
def get_locals():
def get_locals() -> dict[str, Any]:
return locals
# Create REPL.

View file

@ -5,6 +5,7 @@ editing.
Either with the Jedi library, or using `inspect.signature` if Jedi fails and we
can use `eval()` to evaluate the function object.
"""
from __future__ import annotations
import inspect

View file

@ -1,6 +1,7 @@
"""
For internal use only.
"""
from __future__ import annotations
import re

View file

@ -59,4 +59,4 @@ class PythonValidator(Validator):
except ValueError as e:
# In Python 2, compiling "\x9" (an invalid escape sequence) raises
# ValueError instead of SyntaxError.
raise ValidationError(0, "Syntax Error: %s" % e)
raise ValidationError(0, f"Syntax Error: {e}")

View file

@ -1,6 +1,6 @@
[tool.ruff]
target-version = "py37"
select = [
lint.select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
@ -12,14 +12,14 @@ select = [
"RUF100", # unused-noqa
"Q", # quotes
]
ignore = [
lint.ignore = [
"E501", # Line too long, handled by black
"C901", # Too complex
"E722", # bare except.
]
[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"examples/*" = ["T201"] # Print allowed in examples.
"examples/ptpython_config/config.py" = ["F401"] # Unused imports in config.
"ptpython/entry_points/run_ptipython.py" = ["T201", "F401"] # Print, import usage.
@ -30,6 +30,6 @@ ignore = [
"tests/run_tests.py" = ["F401"] # Unused imports.
[tool.ruff.isort]
[tool.ruff.lint.isort]
known-first-party = ["ptpython"]
known-third-party = ["prompt_toolkit", "pygments", "asyncssh"]

View file

@ -11,18 +11,26 @@ with open(os.path.join(os.path.dirname(__file__), "README.rst")) as f:
setup(
name="ptpython",
author="Jonathan Slenders",
version="3.0.26",
version="3.0.27",
url="https://github.com/prompt-toolkit/ptpython",
description="Python REPL build on top of prompt_toolkit",
long_description=long_description,
package_urls={
"Changelog": "https://github.com/prompt-toolkit/ptpython/blob/master/CHANGELOG",
},
project_urls={
"Bug Tracker": "https://github.com/prompt-toolkit/ptpython/issues",
"Source Code": "https://github.com/prompt-toolkit/ptpython",
"Changelog": "https://github.com/prompt-toolkit/ptpython/blob/master/CHANGELOG",
},
packages=find_packages("."),
package_data={"ptpython": ["py.typed"]},
install_requires=[
"appdirs",
"importlib_metadata;python_version<'3.8'",
"jedi>=0.16.0",
# Use prompt_toolkit 3.0.34, because of `OneStyleAndTextTuple` import.
"prompt_toolkit>=3.0.34,<3.1.0",
# Use prompt_toolkit 3.0.43, because of `OneStyleAndTextTuple` import.
"prompt_toolkit>=3.0.43,<3.1.0",
"pygments",
],
python_requires=">=3.7",
@ -30,8 +38,11 @@ setup(
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python",
],
@ -39,12 +50,11 @@ setup(
"console_scripts": [
"ptpython = ptpython.entry_points.run_ptpython:run",
"ptipython = ptpython.entry_points.run_ptipython:run",
"ptpython%s = ptpython.entry_points.run_ptpython:run" % sys.version_info[0],
f"ptpython{sys.version_info[0]} = ptpython.entry_points.run_ptpython:run",
"ptpython{}.{} = ptpython.entry_points.run_ptpython:run".format(
*sys.version_info[:2]
),
"ptipython%s = ptpython.entry_points.run_ptipython:run"
% sys.version_info[0],
f"ptipython{sys.version_info[0]} = ptpython.entry_points.run_ptipython:run",
"ptipython{}.{} = ptpython.entry_points.run_ptipython:run".format(
*sys.version_info[:2]
),