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 CHANGELOG
========= =========
3.0.27: 2024-05-27
------------------
- Limit number of completions to 5k (for performance).
- Several typing fixes.
3.0.26: 2024-02-06 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 .. image :: https://github.com/jonathanslenders/ptpython/raw/master/docs/images/example1.png
Ptpython is an advanced Python REPL. It should work on all 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). BSD, OS X and Windows).
Note: this version of ptpython requires at least Python 3.6. Install ptpython 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 .. 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 FAQ
*** ***
@ -288,12 +304,12 @@ Special thanks to
- `wcwidth <https://github.com/jquast/wcwidth>`_: Determine columns needed for a wide characters. - `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. - `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 .. |Build Status| image:: https://github.com/prompt-toolkit/ptpython/actions/workflows/test.yaml/badge.svg
:target: https://travis-ci.org/prompt-toolkit/ptpython# :target: https://github.com/prompt-toolkit/ptpython/actions/workflows/test.yaml
.. |License| image:: https://img.shields.io/github/license/prompt-toolkit/ptpython.svg .. |License| image:: https://img.shields.io/github/license/prompt-toolkit/ptpython.svg
:target: https://github.com/prompt-toolkit/ptpython/blob/master/LICENSE :target: https://github.com/prompt-toolkit/ptpython/blob/master/LICENSE
.. |PyPI| image:: https://pypip.in/version/ptpython/badge.svg .. |PyPI| image:: https://img.shields.io/pypi/v/ptpython.svg
:target: https://pypi.python.org/pypi/ptpython/ :target: https://pypi.org/project/ptpython/
:alt: Latest Version :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 to stdout, it won't break the input line, but instead writes nicely above the
prompt. prompt.
""" """
import asyncio import asyncio
from ptpython.repl import embed 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. Run this example and then SSH to localhost, port 8222.
""" """
import asyncio import asyncio
import logging 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 Linux, this is: ~/.config/ptpython/config.py
On macOS, this is: ~/Library/Application Support/ptpython/config.py On macOS, this is: ~/Library/Application Support/ptpython/config.py
""" """
from prompt_toolkit.filters import ViInsertMode from prompt_toolkit.filters import ViInsertMode
from prompt_toolkit.key_binding.key_processor import KeyPress from prompt_toolkit.key_binding.key_processor import KeyPress
from prompt_toolkit.keys import Keys from prompt_toolkit.keys import Keys

View file

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

View file

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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """ """
"""
from ptpython.python_input import PythonInput 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 (For testing whether it's working fine if it's not embedded in the main
thread.) thread.)
""" """
import threading import threading
from ptpython.repl import embed from ptpython.repl import embed

View file

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

View file

@ -6,6 +6,7 @@ import inspect
import keyword import keyword
import re import re
from enum import Enum from enum import Enum
from itertools import islice
from typing import TYPE_CHECKING, Any, Callable, Iterable from typing import TYPE_CHECKING, Any, Callable, Iterable
from prompt_toolkit.completion import ( from prompt_toolkit.completion import (
@ -617,7 +618,10 @@ class HidePrivateCompleter(Completer):
def get_completions( def get_completions(
self, document: Document, complete_event: CompleteEvent self, document: Document, complete_event: CompleteEvent
) -> Iterable[Completion]: ) -> 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() complete_private_attributes = self.complete_private_attributes()
hide_private = False 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 should make sure not to use Python 3-only syntax, because this
package should be installable in Python 2 as well! package should be installable in Python 2 as well!
""" """
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio

View file

@ -22,6 +22,7 @@ environment variables:
PTPYTHON_CONFIG_HOME: a configuration directory to use PTPYTHON_CONFIG_HOME: a configuration directory to use
PYTHONSTARTUP: file executed on interactive startup (no default) PYTHONSTARTUP: file executed on interactive startup (no default)
""" """
from __future__ import annotations from __future__ import annotations
import argparse 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 in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
will fix it for Tk.) will fix it for Tk.)
""" """
from __future__ import annotations from __future__ import annotations
import sys 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. Run the Tk eventloop until prompt-toolkit needs to process the next input.
""" """
# Get the current TK application. # Get the current TK application.
import tkinter
import _tkinter # Keep this imports inline! import _tkinter # Keep this imports inline!
import tkinter
root = tkinter._default_root # type: ignore 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 `create_history_application` creates an `Application` instance that runs will
run as a sub application of the Repl/PythonInput. run as a sub application of the Repl/PythonInput.
""" """
from __future__ import annotations from __future__ import annotations
from functools import partial from functools import partial
@ -410,7 +411,7 @@ class HistoryMapping:
if len(history_strings) > HISTORY_COUNT: if len(history_strings) > HISTORY_COUNT:
history_lines[0] = ( 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 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. offer.
""" """
from __future__ import annotations from __future__ import annotations
from typing import Iterable from typing import Iterable
@ -156,7 +157,7 @@ class MagicsCompleter(Completer):
for m in sorted(self.magics_manager.magics["line"]): for m in sorted(self.magics_manager.magics["line"]):
if m.startswith(text): if m.startswith(text):
yield Completion("%s" % m, -len(text)) yield Completion(f"{m}", -len(text))
class AliasCompleter(Completer): class AliasCompleter(Completer):
@ -172,7 +173,7 @@ class AliasCompleter(Completer):
for a, cmd in sorted(aliases, key=lambda a: a[0]): for a, cmd in sorted(aliases, key=lambda a: a[0]):
if a.startswith(text): 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): class IPythonInput(PythonInput):
@ -279,9 +280,8 @@ def initialize_extensions(shell, extensions):
shell.extension_manager.load_extension(ext) shell.extension_manager.load_extension(ext)
except: except:
warn( warn(
"Error in loading extension: %s" % ext f"Error in loading extension: {ext}"
+ "\nCheck your config files in %s" + f"\nCheck your config files in {ipy_utils.path.get_ipython_dir()}"
% ipy_utils.path.get_ipython_dir()
) )
shell.showtraceback() shell.showtraceback()

View file

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

View file

@ -48,7 +48,7 @@ class IPythonPrompt(PromptStyle):
def in_prompt(self) -> AnyFormattedText: def in_prompt(self) -> AnyFormattedText:
return [ return [
("class:in", "In ["), ("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", "]: "), ("class:in", "]: "),
] ]
@ -58,7 +58,7 @@ class IPythonPrompt(PromptStyle):
def out_prompt(self) -> AnyFormattedText: def out_prompt(self) -> AnyFormattedText:
return [ return [
("class:out", "Out["), ("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", "]:"), ("class:out", "]:"),
("", " "), ("", " "),
] ]

View file

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

View file

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

View file

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

View file

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

View file

@ -59,4 +59,4 @@ class PythonValidator(Validator):
except ValueError as e: except ValueError as e:
# In Python 2, compiling "\x9" (an invalid escape sequence) raises # In Python 2, compiling "\x9" (an invalid escape sequence) raises
# ValueError instead of SyntaxError. # 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] [tool.ruff]
target-version = "py37" target-version = "py37"
select = [ lint.select = [
"E", # pycodestyle errors "E", # pycodestyle errors
"W", # pycodestyle warnings "W", # pycodestyle warnings
"F", # pyflakes "F", # pyflakes
@ -12,14 +12,14 @@ select = [
"RUF100", # unused-noqa "RUF100", # unused-noqa
"Q", # quotes "Q", # quotes
] ]
ignore = [ lint.ignore = [
"E501", # Line too long, handled by black "E501", # Line too long, handled by black
"C901", # Too complex "C901", # Too complex
"E722", # bare except. "E722", # bare except.
] ]
[tool.ruff.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"examples/*" = ["T201"] # Print allowed in examples. "examples/*" = ["T201"] # Print allowed in examples.
"examples/ptpython_config/config.py" = ["F401"] # Unused imports in config. "examples/ptpython_config/config.py" = ["F401"] # Unused imports in config.
"ptpython/entry_points/run_ptipython.py" = ["T201", "F401"] # Print, import usage. "ptpython/entry_points/run_ptipython.py" = ["T201", "F401"] # Print, import usage.
@ -30,6 +30,6 @@ ignore = [
"tests/run_tests.py" = ["F401"] # Unused imports. "tests/run_tests.py" = ["F401"] # Unused imports.
[tool.ruff.isort] [tool.ruff.lint.isort]
known-first-party = ["ptpython"] known-first-party = ["ptpython"]
known-third-party = ["prompt_toolkit", "pygments", "asyncssh"] 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( setup(
name="ptpython", name="ptpython",
author="Jonathan Slenders", author="Jonathan Slenders",
version="3.0.26", version="3.0.27",
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,
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("."), packages=find_packages("."),
package_data={"ptpython": ["py.typed"]}, package_data={"ptpython": ["py.typed"]},
install_requires=[ install_requires=[
"appdirs", "appdirs",
"importlib_metadata;python_version<'3.8'", "importlib_metadata;python_version<'3.8'",
"jedi>=0.16.0", "jedi>=0.16.0",
# Use prompt_toolkit 3.0.34, because of `OneStyleAndTextTuple` import. # Use prompt_toolkit 3.0.43, because of `OneStyleAndTextTuple` import.
"prompt_toolkit>=3.0.34,<3.1.0", "prompt_toolkit>=3.0.43,<3.1.0",
"pygments", "pygments",
], ],
python_requires=">=3.7", python_requires=">=3.7",
@ -30,8 +38,11 @@ setup(
"License :: OSI Approved :: BSD License", "License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8", "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 :: 3 :: Only",
"Programming Language :: Python", "Programming Language :: Python",
], ],
@ -39,12 +50,11 @@ setup(
"console_scripts": [ "console_scripts": [
"ptpython = ptpython.entry_points.run_ptpython:run", "ptpython = ptpython.entry_points.run_ptpython:run",
"ptipython = ptpython.entry_points.run_ptipython: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( "ptpython{}.{} = ptpython.entry_points.run_ptpython:run".format(
*sys.version_info[:2] *sys.version_info[:2]
), ),
"ptipython%s = ptpython.entry_points.run_ptipython:run" f"ptipython{sys.version_info[0]} = ptpython.entry_points.run_ptipython:run",
% sys.version_info[0],
"ptipython{}.{} = ptpython.entry_points.run_ptipython:run".format( "ptipython{}.{} = ptpython.entry_points.run_ptipython:run".format(
*sys.version_info[:2] *sys.version_info[:2]
), ),