diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d53bfcc..c62bdc3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,32 +10,29 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] steps: - - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: actions/checkout@v2 + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - - name: Type Checking + - name: Install Dependencies run: | - uvx --with . mypy src/ptpython/ - uvx --with . mypy examples/ - - name: Code formatting - if: ${{ matrix.python-version == '3.13' }} + sudo apt remove python3-pip + python -m pip install --upgrade pip + python -m pip install . ruff mypy pytest readme_renderer + pip list + - name: Type Checker run: | - uvx ruff check . - uvx ruff format --check . - - name: Typos - if: ${{ matrix.python-version == '3.13' }} + mypy ptpython + ruff check . + ruff format --check . + - name: Run Tests run: | - uvx typos . - - name: Unit test - run: | - uvx --with . pytest tests/ + ./tests/run_tests.py - name: Validate README.md - if: ${{ matrix.python-version == '3.13' }} # Ensure that the README renders correctly (required for uploading to PyPI). run: | - uv pip install readme_renderer python -m readme_renderer README.rst > /dev/null diff --git a/CHANGELOG b/CHANGELOG index 7706260..bef7d07 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,17 +1,6 @@ CHANGELOG ========= -3.0.30: 2025-04-15 ------------------- - -New features: -- Show exception cause/context when printing chained exceptions. -- Reworked project layout and use pyproject.toml instead of setup.py. - -Breaking changes: -- Drop Python 3.7 support. - - 3.0.29: 2024-07-22 ------------------ diff --git a/debian/changelog b/debian/changelog index 6052c88..e774e1e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,3 @@ -ptpython (3.0.30-1) sid; urgency=medium - - * Merging upstream version 3.0.30. - * Updating year in upstream copyright for 2025. - - -- Daniel Baumann Wed, 16 Apr 2025 08:49:26 +0200 - ptpython (3.0.29-3) sid; urgency=medium * Updating to standards version 4.7.1. diff --git a/debian/copyright b/debian/copyright index 0f914e6..696ea6a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,7 +4,7 @@ Upstream-Contact: Jonathan Slenders Source: https://github.com/prompt-toolkit/ptpython/tags Files: * -Copyright: 2015-2025 Jonathan Slenders +Copyright: 2015-2024 Jonathan Slenders License: BSD-3-clause Files: debian/* diff --git a/examples/asyncio-python-embed.py b/examples/asyncio-python-embed.py index cb90973..38cc1c2 100755 --- a/examples/asyncio-python-embed.py +++ b/examples/asyncio-python-embed.py @@ -25,7 +25,7 @@ async def print_counter() -> None: Coroutine that prints counters and saves it in a global variable. """ while True: - print(f"Counter: {counter[0]}") + print("Counter: %i" % counter[0]) counter[0] += 1 await asyncio.sleep(3) diff --git a/examples/asyncio-ssh-python-embed.py b/examples/asyncio-ssh-python-embed.py index bf79df7..9bbad86 100755 --- a/examples/asyncio-ssh-python-embed.py +++ b/examples/asyncio-ssh-python-embed.py @@ -44,8 +44,8 @@ async def main(port: int = 8222) -> None: def create_server() -> MySSHServer: return MySSHServer(lambda: environ) - print(f"Listening on: {port}") - print(f'To connect, do "ssh localhost -p {port}"') + print("Listening on :%i" % port) + print('To connect, do "ssh localhost -p %i"' % port) await asyncssh.create_server( create_server, "", port, server_host_keys=["/etc/ssh/ssh_host_dsa_key"] diff --git a/examples/ssh-and-telnet-embed.py b/examples/ssh-and-telnet-embed.py index 2b293e6..62fa76d 100755 --- a/examples/ssh-and-telnet-embed.py +++ b/examples/ssh-and-telnet-embed.py @@ -6,8 +6,6 @@ Thanks to Vincent Michel for this! https://gist.github.com/vxgmichel/7685685b3e5ead04ada4a3ba75a48eef """ -from __future__ import annotations - import asyncio import pathlib @@ -17,7 +15,7 @@ from prompt_toolkit.contrib.ssh.server import ( PromptToolkitSSHServer, PromptToolkitSSHSession, ) -from prompt_toolkit.contrib.telnet.server import TelnetConnection, TelnetServer +from prompt_toolkit.contrib.telnet.server import TelnetServer from ptpython.repl import embed @@ -30,7 +28,7 @@ def ensure_key(filename: str = "ssh_host_key") -> str: return str(path) -async def interact(connection: PromptToolkitSSHSession | TelnetConnection) -> None: +async def interact(connection: PromptToolkitSSHSession) -> None: global_dict = {**globals(), "print": print_formatted_text} await embed(return_asyncio_coroutine=True, globals=global_dict) diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..5a7ef2e --- /dev/null +++ b/mypy.ini @@ -0,0 +1,6 @@ +[mypy] +ignore_missing_imports = True +no_implicit_optional = True +platform = win32 +strict_equality = True +strict_optional = True diff --git a/src/ptpython/__init__.py b/ptpython/__init__.py similarity index 100% rename from src/ptpython/__init__.py rename to ptpython/__init__.py diff --git a/src/ptpython/__main__.py b/ptpython/__main__.py similarity index 100% rename from src/ptpython/__main__.py rename to ptpython/__main__.py diff --git a/src/ptpython/completer.py b/ptpython/completer.py similarity index 100% rename from src/ptpython/completer.py rename to ptpython/completer.py diff --git a/src/ptpython/contrib/__init__.py b/ptpython/contrib/__init__.py similarity index 100% rename from src/ptpython/contrib/__init__.py rename to ptpython/contrib/__init__.py diff --git a/src/ptpython/contrib/asyncssh_repl.py b/ptpython/contrib/asyncssh_repl.py similarity index 100% rename from src/ptpython/contrib/asyncssh_repl.py rename to ptpython/contrib/asyncssh_repl.py diff --git a/src/ptpython/entry_points/__init__.py b/ptpython/entry_points/__init__.py similarity index 100% rename from src/ptpython/entry_points/__init__.py rename to ptpython/entry_points/__init__.py diff --git a/src/ptpython/entry_points/run_ptipython.py b/ptpython/entry_points/run_ptipython.py similarity index 100% rename from src/ptpython/entry_points/run_ptipython.py rename to ptpython/entry_points/run_ptipython.py diff --git a/src/ptpython/entry_points/run_ptpython.py b/ptpython/entry_points/run_ptpython.py similarity index 97% rename from src/ptpython/entry_points/run_ptpython.py rename to ptpython/entry_points/run_ptpython.py index d083858..05df971 100644 --- a/src/ptpython/entry_points/run_ptpython.py +++ b/ptpython/entry_points/run_ptpython.py @@ -30,9 +30,8 @@ import asyncio import os import pathlib import sys -from importlib import metadata from textwrap import dedent -from typing import Protocol +from typing import IO import appdirs from prompt_toolkit.formatted_text import HTML @@ -40,15 +39,17 @@ from prompt_toolkit.shortcuts import print_formatted_text from ptpython.repl import PythonRepl, embed, enable_deprecation_warnings, run_config +try: + from importlib import metadata # type: ignore +except ImportError: + import importlib_metadata as metadata # type: ignore + + __all__ = ["create_parser", "get_config_and_history_file", "run"] -class _SupportsWrite(Protocol): - def write(self, s: str, /) -> object: ... - - class _Parser(argparse.ArgumentParser): - def print_help(self, file: _SupportsWrite | None = None) -> None: + def print_help(self, file: IO[str] | None = None) -> None: super().print_help() print( dedent( diff --git a/src/ptpython/eventloop.py b/ptpython/eventloop.py similarity index 100% rename from src/ptpython/eventloop.py rename to ptpython/eventloop.py diff --git a/src/ptpython/filters.py b/ptpython/filters.py similarity index 100% rename from src/ptpython/filters.py rename to ptpython/filters.py diff --git a/src/ptpython/history_browser.py b/ptpython/history_browser.py similarity index 99% rename from src/ptpython/history_browser.py rename to ptpython/history_browser.py index 72bc576..ae0ac03 100644 --- a/src/ptpython/history_browser.py +++ b/ptpython/history_browser.py @@ -58,15 +58,13 @@ from ptpython.layout import get_inputmode_fragments from .utils import if_mousedown if TYPE_CHECKING: - from typing_extensions import TypeAlias - from .python_input import PythonInput HISTORY_COUNT = 2000 __all__ = ["HistoryLayout", "PythonHistory"] -E: TypeAlias = KeyPressEvent +E = KeyPressEvent HELP_TEXT = """ This interface is meant to select multiple lines from the diff --git a/src/ptpython/ipython.py b/ptpython/ipython.py similarity index 100% rename from src/ptpython/ipython.py rename to ptpython/ipython.py diff --git a/src/ptpython/key_bindings.py b/ptpython/key_bindings.py similarity index 99% rename from src/ptpython/key_bindings.py rename to ptpython/key_bindings.py index 48c5f5a..d7bb575 100644 --- a/src/ptpython/key_bindings.py +++ b/ptpython/key_bindings.py @@ -22,8 +22,6 @@ from prompt_toolkit.keys import Keys from .utils import document_is_multiline_python if TYPE_CHECKING: - from typing_extensions import TypeAlias - from .python_input import PythonInput __all__ = [ @@ -32,7 +30,7 @@ __all__ = [ "load_confirm_exit_bindings", ] -E: TypeAlias = KeyPressEvent +E = KeyPressEvent @Condition diff --git a/src/ptpython/layout.py b/ptpython/layout.py similarity index 98% rename from src/ptpython/layout.py rename to ptpython/layout.py index 9768598..622df59 100644 --- a/src/ptpython/layout.py +++ b/ptpython/layout.py @@ -108,7 +108,7 @@ def python_sidebar(python_input: PythonInput) -> Window: tokens.extend( [ ("class:sidebar", " "), - ("class:sidebar.title", f" {category.title:36}"), + ("class:sidebar.title", " %-36s" % category.title), ("class:sidebar", "\n"), ] ) @@ -130,7 +130,7 @@ def python_sidebar(python_input: PythonInput) -> Window: sel = ",selected" if selected else "" tokens.append(("class:sidebar" + sel, " >" if selected else " ")) - tokens.append(("class:sidebar.label" + sel, f"{label:24}", 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, f"{status}", goto_next)) @@ -332,7 +332,7 @@ class PythonPromptMargin(PromptMargin): width: int, line_number: int, is_soft_wrap: bool ) -> StyleAndTextTuples: if python_input.show_line_numbers and not is_soft_wrap: - text = f"{line_number + 1} ".rjust(width) + text = ("%i " % (line_number + 1)).rjust(width) return [("class:line-number", text)] else: return to_formatted_text(get_prompt_style().in2_prompt(width)) @@ -368,7 +368,8 @@ def status_bar(python_input: PythonInput) -> Container: append( ( TB, - f"{python_buffer.working_index + 1}/{len(python_buffer._working_lines)} ", + "%i/%i " + % (python_buffer.working_index + 1, len(python_buffer._working_lines)), ) ) @@ -491,7 +492,8 @@ def show_sidebar_button_info(python_input: PythonInput) -> Container: ("class:status-toolbar", " - "), ( "class:status-toolbar.python-version", - f"{platform.python_implementation()} {version[0]}.{version[1]}.{version[2]}", + "%s %i.%i.%i" + % (platform.python_implementation(), version[0], version[1], version[2]), ), ("class:status-toolbar", " "), ] diff --git a/src/ptpython/lexer.py b/ptpython/lexer.py similarity index 100% rename from src/ptpython/lexer.py rename to ptpython/lexer.py diff --git a/src/ptpython/printer.py b/ptpython/printer.py similarity index 95% rename from src/ptpython/printer.py rename to ptpython/printer.py index a3578de..85bd9c8 100644 --- a/src/ptpython/printer.py +++ b/ptpython/printer.py @@ -1,5 +1,6 @@ from __future__ import annotations +import sys import traceback from dataclasses import dataclass from enum import Enum @@ -253,7 +254,8 @@ class OutputPrinter: columns_in_buffer += width current_line.append((style, c)) - yield current_line + if len(current_line) > 0: + yield current_line def _print_paginated_formatted_text( self, lines: Iterable[StyleAndTextTuples] @@ -321,20 +323,14 @@ class OutputPrinter: def _format_exception_output( self, e: BaseException, highlight: bool ) -> Generator[OneStyleAndTextTuple, None, None]: - if e.__cause__: - yield from self._format_exception_output(e.__cause__, highlight=highlight) - yield ( - "", - "\nThe above exception was the direct cause of the following exception:\n\n", - ) - elif e.__context__: - yield from self._format_exception_output(e.__context__, highlight=highlight) - yield ( - "", - "\nDuring handling of the above exception, another exception occurred:\n\n", - ) + # Instead of just calling ``traceback.format_exc``, we take the + # traceback and skip the bottom calls of this framework. + t, v, tb = sys.exc_info() - tblist = list(traceback.extract_tb(e.__traceback__)) + # Required for pdb.post_mortem() to work. + sys.last_type, sys.last_value, sys.last_traceback = t, v, tb + + tblist = list(traceback.extract_tb(tb)) for line_nr, tb_tuple in enumerate(tblist): if tb_tuple[0] == "": @@ -344,7 +340,7 @@ class OutputPrinter: tb_list = traceback.format_list(tblist) if tb_list: tb_list.insert(0, "Traceback (most recent call last):\n") - tb_list.extend(traceback.format_exception_only(type(e), e)) + tb_list.extend(traceback.format_exception_only(t, v)) tb_str = "".join(tb_list) diff --git a/src/ptpython/prompt_style.py b/ptpython/prompt_style.py similarity index 100% rename from src/ptpython/prompt_style.py rename to ptpython/prompt_style.py diff --git a/src/ptpython/py.typed b/ptpython/py.typed similarity index 100% rename from src/ptpython/py.typed rename to ptpython/py.typed diff --git a/src/ptpython/python_input.py b/ptpython/python_input.py similarity index 100% rename from src/ptpython/python_input.py rename to ptpython/python_input.py diff --git a/src/ptpython/repl.py b/ptpython/repl.py similarity index 93% rename from src/ptpython/repl.py rename to ptpython/repl.py index 469ed69..6b60018 100644 --- a/src/ptpython/repl.py +++ b/ptpython/repl.py @@ -20,17 +20,7 @@ import types import warnings from dis import COMPILER_FLAG_NAMES from pathlib import Path -from typing import ( - Any, - Callable, - ContextManager, - Coroutine, - Iterable, - Literal, - NoReturn, - Sequence, - overload, -) +from typing import Any, Callable, ContextManager, Iterable, NoReturn, Sequence from prompt_toolkit.formatted_text import OneStyleAndTextTuple from prompt_toolkit.patch_stdout import patch_stdout as patch_stdout_context @@ -372,7 +362,7 @@ class PythonRepl(PythonInput): def _store_eval_result(self, result: object) -> None: locals: dict[str, Any] = self.get_locals() - locals["_"] = locals[f"_{self.current_statement_index}"] = result + locals["_"] = locals["_%i" % self.current_statement_index] = result def get_compiler_flags(self) -> int: return super().get_compiler_flags() | PyCF_ALLOW_TOP_LEVEL_AWAIT @@ -388,10 +378,6 @@ class PythonRepl(PythonInput): ) def _handle_exception(self, e: BaseException) -> None: - # Required for pdb.post_mortem() to work. - t, v, tb = sys.exc_info() - sys.last_type, sys.last_value, sys.last_traceback = t, v, tb - self._get_output_printer().display_exception( e, highlight=self.enable_syntax_highlighting, @@ -515,34 +501,6 @@ class ReplExit(Exception): """ -@overload -def embed( - globals: dict[str, Any] | None = ..., - locals: dict[str, Any] | None = ..., - configure: Callable[[PythonRepl], None] | None = ..., - vi_mode: bool = ..., - history_filename: str | None = ..., - title: str | None = ..., - startup_paths: Sequence[str | Path] | None = ..., - patch_stdout: bool = ..., - return_asyncio_coroutine: Literal[False] = ..., -) -> None: ... - - -@overload -def embed( - globals: dict[str, Any] | None = ..., - locals: dict[str, Any] | None = ..., - configure: Callable[[PythonRepl], None] | None = ..., - vi_mode: bool = ..., - history_filename: str | None = ..., - title: str | None = ..., - startup_paths: Sequence[str | Path] | None = ..., - patch_stdout: bool = ..., - return_asyncio_coroutine: Literal[True] = ..., -) -> Coroutine[Any, Any, None]: ... - - def embed( globals: dict[str, Any] | None = None, locals: dict[str, Any] | None = None, @@ -553,7 +511,7 @@ def embed( startup_paths: Sequence[str | Path] | None = None, patch_stdout: bool = False, return_asyncio_coroutine: bool = False, -) -> None | Coroutine[Any, Any, None]: +) -> None: """ Call this to embed Python shell at the current point in your program. It's similar to `IPython.embed` and `bpython.embed`. :: @@ -615,4 +573,3 @@ def embed( else: with patch_context: repl.run() - return None diff --git a/src/ptpython/signatures.py b/ptpython/signatures.py similarity index 100% rename from src/ptpython/signatures.py rename to ptpython/signatures.py diff --git a/src/ptpython/style.py b/ptpython/style.py similarity index 100% rename from src/ptpython/style.py rename to ptpython/style.py diff --git a/src/ptpython/utils.py b/ptpython/utils.py similarity index 100% rename from src/ptpython/utils.py rename to ptpython/utils.py diff --git a/src/ptpython/validator.py b/ptpython/validator.py similarity index 100% rename from src/ptpython/validator.py rename to ptpython/validator.py diff --git a/pyproject.toml b/pyproject.toml index 00e2d5f..ce42037 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,55 +1,3 @@ -[project] -name = "ptpython" -version = "3.0.30" -description = "Python REPL build on top of prompt_toolkit" -readme = "README.rst" -authors = [{ name = "Jonathan Slenders" }] -classifiers = [ - "License :: OSI Approved :: BSD License", - "Programming Language :: Python :: 3", - "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.13", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python", -] -requires-python = ">=3.8" -dependencies = [ - "appdirs", - "jedi>=0.16.0", - # Use prompt_toolkit 3.0.43, because of `OneStyleAndTextTuple` import. - "prompt_toolkit>=3.0.43,<3.1.0", - "pygments", -] - - -[project.urls] -Homepage = "https://github.com/prompt-toolkit/ptpython" -Changelog = "https://github.com/prompt-toolkit/ptpython/blob/master/CHANGELOG" -"Bug Tracker" = "https://github.com/prompt-toolkit/ptpython/issues" -"Source Code" = "https://github.com/prompt-toolkit/ptpython" - - -[project.scripts] -ptpython = "ptpython.entry_points.run_ptpython:run" -ptipython = "ptpython.entry_points.run_ptipython:run" - - -[project.optional-dependencies] -ptipython = ["ipython"] # For ptipython, we need to have IPython - - -[tool.mypy] -ignore_missing_imports = true -no_implicit_optional = true -platform = "win32" -strict_equality = true -strict_optional = true - - [tool.ruff] target-version = "py37" lint.select = [ @@ -74,22 +22,14 @@ lint.ignore = [ [tool.ruff.lint.per-file-ignores] "examples/*" = ["T201"] # Print allowed in examples. "examples/ptpython_config/config.py" = ["F401"] # Unused imports in config. -"src/ptpython/entry_points/run_ptipython.py" = ["T201", "F401"] # Print, import usage. -"src/ptpython/entry_points/run_ptpython.py" = ["T201"] # Print usage. -"src/ptpython/ipython.py" = ["T100"] # Import usage. -"src/ptpython/repl.py" = ["T201"] # Print usage. -"src/ptpython/printer.py" = ["T201"] # Print usage. +"ptpython/entry_points/run_ptipython.py" = ["T201", "F401"] # Print, import usage. +"ptpython/entry_points/run_ptpython.py" = ["T201"] # Print usage. +"ptpython/ipython.py" = ["T100"] # Import usage. +"ptpython/repl.py" = ["T201"] # Print usage. +"ptpython/printer.py" = ["T201"] # Print usage. +"tests/run_tests.py" = ["F401"] # Unused imports. [tool.ruff.lint.isort] known-first-party = ["ptpython"] known-third-party = ["prompt_toolkit", "pygments", "asyncssh"] - -[tool.typos.default] -extend-ignore-re = [ - "impotr" # Intentional typo in: ./examples/ptpython_config/config.py -] - -[build-system] -requires = ["setuptools>=68"] -build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..80dfec6 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,41 @@ +[bdist_wheel] +universal=1 + +[flake8] +exclude=__init__.py +max_line_length=150 +ignore= + E114, + E116, + E117, + E121, + E122, + E123, + E125, + E126, + E127, + E128, + E131, + E171, + E203, + E211, + E221, + E227, + E231, + E241, + E251, + E301, + E402, + E501, + E701, + E702, + E704, + E731, + E741, + F401, + F403, + F405, + F811, + W503, + W504, + E722 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..aa10176 --- /dev/null +++ b/setup.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +import os +import sys + +from setuptools import find_packages, setup + +with open(os.path.join(os.path.dirname(__file__), "README.rst")) as f: + long_description = f.read() + + +setup( + name="ptpython", + author="Jonathan Slenders", + version="3.0.29", + 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.43, because of `OneStyleAndTextTuple` import. + "prompt_toolkit>=3.0.43,<3.1.0", + "pygments", + ], + python_requires=">=3.7", + classifiers=[ + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3", + "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", + ], + entry_points={ + "console_scripts": [ + "ptpython = ptpython.entry_points.run_ptpython:run", + "ptipython = ptpython.entry_points.run_ptipython:run", + f"ptpython{sys.version_info[0]} = ptpython.entry_points.run_ptpython:run", + "ptpython{}.{} = ptpython.entry_points.run_ptpython:run".format( + *sys.version_info[:2] + ), + f"ptipython{sys.version_info[0]} = ptpython.entry_points.run_ptipython:run", + "ptipython{}.{} = ptpython.entry_points.run_ptipython:run".format( + *sys.version_info[:2] + ), + ] + }, + extras_require={ + "ptipython": ["ipython"], # For ptipython, we need to have IPython + "all": ["black"], # Black not always possible on PyPy + }, +) diff --git a/tests/run_tests.py b/tests/run_tests.py new file mode 100755 index 0000000..0de3743 --- /dev/null +++ b/tests/run_tests.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +from __future__ import annotations + +import unittest + +import ptpython.completer +import ptpython.eventloop +import ptpython.filters +import ptpython.history_browser +import ptpython.key_bindings +import ptpython.layout +import ptpython.python_input +import ptpython.repl +import ptpython.style +import ptpython.utils +import ptpython.validator + +# For now there are no tests here. +# However this is sufficient for Travis to do at least a syntax check. +# That way we are at least sure to restrict to the Python 2.6 syntax. + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_dummy.py b/tests/test_dummy.py deleted file mode 100755 index 922c6a3..0000000 --- a/tests/test_dummy.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -from __future__ import annotations - -import ptpython.completer -import ptpython.eventloop -import ptpython.filters -import ptpython.history_browser -import ptpython.key_bindings -import ptpython.layout -import ptpython.python_input -import ptpython.repl -import ptpython.style -import ptpython.utils -import ptpython.validator - -# For now there are no tests here. -# However this is sufficient to do at least a syntax check. - - -def test_dummy() -> None: - assert ptpython.completer - assert ptpython.eventloop - assert ptpython.filters - assert ptpython.history_browser - assert ptpython.key_bindings - assert ptpython.layout - assert ptpython.python_input - assert ptpython.repl - assert ptpython.style - assert ptpython.utils - assert ptpython.validator