Make it work on 3.9 again
turns out I have some systems where I care about that :)
This commit is contained in:
parent
14f284defc
commit
5daf7e7d2a
5 changed files with 22 additions and 19 deletions
|
|
@ -20,13 +20,14 @@ name="chap"
|
|||
authors = [{name = "Jeff Epler", email = "jepler@gmail.com"}]
|
||||
description = "Interact with the OpenAI ChatGPT API (and other text generators)"
|
||||
dynamic = ["readme","version","dependencies"]
|
||||
requires-python = ">=3.10"
|
||||
requires-python = ">=3.9"
|
||||
keywords = ["llm", "tui", "chatgpt"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import asyncio
|
||||
import sys
|
||||
from typing import Iterable, Protocol
|
||||
from typing import Iterable, Optional, Protocol
|
||||
|
||||
import click
|
||||
import rich
|
||||
|
|
@ -40,7 +40,7 @@ class DumbPrinter:
|
|||
|
||||
|
||||
class WrappingPrinter:
|
||||
def __init__(self, width: int | None = None) -> None:
|
||||
def __init__(self, width: Optional[int] = None) -> None:
|
||||
self._width = width or rich.get_console().width
|
||||
self._column = 0
|
||||
self._line = ""
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import asyncio
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Any, cast
|
||||
from typing import Any, Optional, cast
|
||||
|
||||
from markdown_it import MarkdownIt
|
||||
from textual import work
|
||||
|
|
@ -63,7 +63,7 @@ class Tui(App[None]):
|
|||
]
|
||||
|
||||
def __init__(
|
||||
self, api: Backend | None = None, session: Session | None = None
|
||||
self, api: Optional[Backend] = None, session: Optional[Session] = None
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.api = api or get_api("lorem")
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ import pathlib
|
|||
import pkgutil
|
||||
import subprocess
|
||||
from dataclasses import MISSING, dataclass, fields
|
||||
from types import UnionType
|
||||
from typing import Any, AsyncGenerator, Callable, cast
|
||||
from typing import Any, AsyncGenerator, Callable, Optional, Union, cast
|
||||
|
||||
import click
|
||||
import platformdirs
|
||||
|
|
@ -22,6 +21,9 @@ from typing_extensions import Protocol
|
|||
from . import backends, commands # pylint: disable=no-name-in-module
|
||||
from .session import Message, Session, System, session_from_file
|
||||
|
||||
# 3.9 compatible version of `from types import UnionType`
|
||||
UnionType = type(Union[int, list])
|
||||
|
||||
conversations_path = platformdirs.user_state_path("chap") / "conversations"
|
||||
conversations_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
|
@ -54,14 +56,14 @@ class AutoAskMixin: # pylint: disable=too-few-public-methods
|
|||
return "".join(tokens)
|
||||
|
||||
|
||||
def last_session_path() -> pathlib.Path | None:
|
||||
def last_session_path() -> Optional[pathlib.Path]:
|
||||
result = max(
|
||||
conversations_path.glob("*.json"), key=lambda p: p.stat().st_mtime, default=None
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def new_session_path(opt_path: pathlib.Path | None = None) -> pathlib.Path:
|
||||
def new_session_path(opt_path: Optional[pathlib.Path] = None) -> pathlib.Path:
|
||||
return opt_path or conversations_path / (
|
||||
datetime.datetime.now().isoformat().replace(":", "_") + ".json"
|
||||
)
|
||||
|
|
@ -95,7 +97,7 @@ def get_api(name: str = "openai_chatgpt") -> Backend:
|
|||
|
||||
|
||||
def do_session_continue(
|
||||
ctx: click.Context, param: click.Parameter, value: pathlib.Path | None
|
||||
ctx: click.Context, param: click.Parameter, value: Optional[pathlib.Path]
|
||||
) -> None:
|
||||
if value is None:
|
||||
return
|
||||
|
|
@ -293,18 +295,18 @@ def version_callback( # pylint: disable=unused-argument
|
|||
|
||||
@dataclass
|
||||
class Obj:
|
||||
api: Backend | None = None
|
||||
system_message: str | None = None
|
||||
session: list[Message] | None = None
|
||||
session_filename: pathlib.Path | None = None
|
||||
api: Optional[Backend] = None
|
||||
system_message: Optional[str] = None
|
||||
session: Optional[list[Message]] = None
|
||||
session_filename: Optional[pathlib.Path] = None
|
||||
|
||||
|
||||
class MyCLI(click.MultiCommand):
|
||||
def make_context(
|
||||
self,
|
||||
info_name: str | None,
|
||||
info_name: Optional[str],
|
||||
args: list[str],
|
||||
parent: click.Context | None = None,
|
||||
parent: Optional[click.Context] = None,
|
||||
**extra: Any,
|
||||
) -> click.Context:
|
||||
result = super().make_context(info_name, args, parent, obj=Obj(), **extra)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from __future__ import annotations
|
|||
import json
|
||||
import pathlib
|
||||
from dataclasses import asdict, dataclass
|
||||
from typing import cast
|
||||
from typing import Union, cast
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
|
@ -65,11 +65,11 @@ def session_from_json(data: str) -> Session:
|
|||
return [Message(**mapping) for mapping in j]
|
||||
|
||||
|
||||
def session_from_file(path: pathlib.Path | str) -> Session:
|
||||
def session_from_file(path: Union[pathlib.Path, str]) -> Session:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return session_from_json(f.read())
|
||||
|
||||
|
||||
def session_to_file(session: Session, path: pathlib.Path | str) -> None:
|
||||
def session_to_file(session: Session, path: Union[pathlib.Path, str]) -> None:
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write(session_to_json(session))
|
||||
|
|
|
|||
Loading…
Reference in a new issue