feat: use IPython shell if available

This commit is contained in:
2024-12-13 15:15:53 +02:00
parent 56114ecc1e
commit 4880ca4fee
9 changed files with 103 additions and 12 deletions

View File

@ -18,12 +18,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import argparse
import code
import sys
from pathlib import Path
from ahriman.application.handlers.handler import Handler, SubParserAction
from ahriman.application.interactive_shell import InteractiveShell
from ahriman.core.configuration import Configuration
from ahriman.core.formatters import StringPrinter
from ahriman.models.repository_id import RepositoryId
@ -58,11 +58,13 @@ class Shell(Handler):
"configuration": configuration,
"repository_id": repository_id,
}
console = InteractiveShell(locals=local_variables)
if args.code is None:
code.interact(local=local_variables)
else:
code.InteractiveConsole(locals=local_variables).runcode(args.code)
match args.code:
case None:
console.interact()
case snippet:
console.runcode(snippet)
@staticmethod
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
@ -79,6 +81,7 @@ class Shell(Handler):
description="drop into python shell")
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
parser.add_argument("-o", "--output", help="output commands and result to the file", type=Path)
parser.set_defaults(lock=None, report=False)
return parser

View File

@ -0,0 +1,46 @@
#
# Copyright (c) 2021-2024 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from code import InteractiveConsole
from typing import Any
class InteractiveShell(InteractiveConsole):
"""
wrapper around :class:`code.InteractiveConsole` to pass :func:`interact()` to IPython shell
"""
def interact(self, *args: Any, **kwargs: Any) -> None:
"""
pass controller to IPython shell
Args:
*args(Any): positional arguments
**kwargs(Any): keyword arguments
"""
try:
from IPython.terminal.embed import InteractiveShellEmbed
shell = InteractiveShellEmbed(user_ns=self.locals) # type: ignore[no-untyped-call]
shell.show_banner() # type: ignore[no-untyped-call]
shell.interact() # type: ignore[no-untyped-call]
except ImportError:
# fallback to default
import readline # pylint: disable=unused-import
InteractiveConsole.interact(self, *args, **kwargs)