Merging upstream version 3.0.27.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
479a0e81b5
commit
7807e8a7bd
25 changed files with 105 additions and 56 deletions
|
@ -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
|
||||
------------------
|
||||
|
||||
|
|
26
README.rst
26
README.rst
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
"""
|
||||
""" """
|
||||
|
||||
from ptpython.repl import embed
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
"""
|
||||
""" """
|
||||
|
||||
from ptpython.python_input import PythonInput
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
Make `python -m ptpython` an alias for running `./ptpython`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .entry_points.run_ptpython import run
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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"),
|
||||
]
|
||||
|
|
|
@ -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", "]:"),
|
||||
("", " "),
|
||||
]
|
||||
|
|
|
@ -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
|
||||
},
|
||||
),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
For internal use only.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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"]
|
||||
|
|
24
setup.py
24
setup.py
|
@ -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]
|
||||
),
|
||||
|
|
Loading…
Add table
Reference in a new issue