Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit number of completions to 5k (for performance). #576

Merged
merged 4 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/asyncio-python-embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
to stdout, it won't break the input line, but instead writes nicely above the
prompt.
"""

import asyncio

from ptpython.repl import embed
Expand Down
1 change: 1 addition & 0 deletions examples/asyncio-ssh-python-embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

Run this example and then SSH to localhost, port 8222.
"""

import asyncio
import logging

Expand Down
1 change: 1 addition & 0 deletions examples/ptpython_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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
Expand Down
1 change: 1 addition & 0 deletions examples/python-embed-with-custom-prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions examples/python-embed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
"""
""" """

from ptpython.repl import embed


Expand Down
4 changes: 2 additions & 2 deletions examples/python-input.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
"""
""" """

from ptpython.python_input import PythonInput


Expand Down
1 change: 1 addition & 0 deletions examples/test-cases/ptpython-in-other-thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
(For testing whether it's working fine if it's not embedded in the main
thread.)
"""

import threading

from ptpython.repl import embed
Expand Down
1 change: 1 addition & 0 deletions ptpython/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Make `python -m ptpython` an alias for running `./ptpython`.
"""

from __future__ import annotations

from .entry_points.run_ptpython import run
Expand Down
6 changes: 5 additions & 1 deletion ptpython/completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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 (
Expand Down Expand Up @@ -617,7 +618,10 @@ def __init__(
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

Expand Down
1 change: 1 addition & 0 deletions ptpython/contrib/asyncssh_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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
Expand Down
1 change: 1 addition & 0 deletions ptpython/entry_points/run_ptpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
PTPYTHON_CONFIG_HOME: a configuration directory to use
PYTHONSTARTUP: file executed on interactive startup (no default)
"""

from __future__ import annotations

import argparse
Expand Down
1 change: 1 addition & 0 deletions ptpython/eventloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
will fix it for Tk.)
"""

from __future__ import annotations

import sys
Expand Down
3 changes: 2 additions & 1 deletion ptpython/history_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
`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
Expand Down Expand Up @@ -410,7 +411,7 @@ def __init__(

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
Expand Down
10 changes: 5 additions & 5 deletions ptpython/ipython.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
offer.

"""

from __future__ import annotations

from typing import Iterable
Expand Down Expand Up @@ -156,7 +157,7 @@ def get_completions(

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):
Expand All @@ -172,7 +173,7 @@ def get_completions(

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):
Expand Down Expand Up @@ -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()

Expand Down
5 changes: 3 additions & 2 deletions ptpython/layout.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Creation of the `Layout` instance for the Python input/REPL.
"""

from __future__ import annotations

import platform
Expand Down Expand Up @@ -131,7 +132,7 @@ def goto_next(mouse_event: MouseEvent) -> None:
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]", ""))
Expand Down Expand Up @@ -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"),
]
Expand Down
4 changes: 2 additions & 2 deletions ptpython/prompt_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, python_input: PythonInput) -> None:
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", "]: "),
]

Expand All @@ -58,7 +58,7 @@ def in2_prompt(self, width: int) -> AnyFormattedText:
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", "]:"),
("", " "),
]
Expand Down
26 changes: 12 additions & 14 deletions ptpython/python_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -98,8 +99,7 @@
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")
Expand Down Expand Up @@ -347,14 +347,6 @@ def __init__(
"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()
Expand Down Expand Up @@ -425,6 +417,12 @@ def __init__(
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)
Expand Down Expand Up @@ -880,18 +878,18 @@ def get_values() -> dict[str, Callable[[], bool]]:
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
},
),
Expand Down
18 changes: 10 additions & 8 deletions ptpython/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
embed(globals(), locals(), vi_mode=False)

"""

from __future__ import annotations

import asyncio
Expand All @@ -18,7 +19,8 @@
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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -347,7 +349,7 @@ def _store_eval_result(self, result: object) -> None:
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,
Expand Down Expand Up @@ -458,13 +460,13 @@ def enter_to_continue() -> 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:
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions ptpython/signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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
Expand Down
1 change: 1 addition & 0 deletions ptpython/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
For internal use only.
"""

from __future__ import annotations

import re
Expand Down
2 changes: 1 addition & 1 deletion ptpython/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ def validate(self, document: Document) -> None:
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}")
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.ruff]
target-version = "py37"
select = [
lint.select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
Expand All @@ -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.
Expand All @@ -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"]
Loading
Loading