Skip to content

Commit 75ca883

Browse files
committed
fix: pyright issues
Signed-off-by: Anupam Kumar <kyteinsky@gmail.com>
1 parent ca45abe commit 75ca883

3 files changed

Lines changed: 49 additions & 66 deletions

File tree

.pre-commit-config.yaml

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,29 @@
11
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
2-
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# SPDX-License-Identifier: MIT
33
ci:
4-
skip: [pylint]
4+
skip: [pyright]
55

66
repos:
7-
- repo: https://github.com/pre-commit/pre-commit-hooks
8-
rev: v4.6.0
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v5.0.0
99
hooks:
10-
- id: check-yaml
11-
- id: end-of-file-fixer
12-
- id: trailing-whitespace
13-
- id: mixed-line-ending
10+
- id: check-yaml
11+
- id: check-toml
12+
- id: mixed-line-ending
13+
- id: trailing-whitespace
14+
files: lib
15+
- id: end-of-file-fixer
1416

15-
- repo: https://github.com/PyCQA/isort
16-
rev: 5.13.2
17+
- repo: https://github.com/astral-sh/ruff-pre-commit
18+
rev: v0.9.9
1719
hooks:
18-
- id: isort
19-
files: lib/
20+
- id: ruff
2021

21-
- repo: https://github.com/psf/black
22-
rev: 24.4.2
22+
- repo: local
2323
hooks:
24-
- id: black
25-
files: lib/
26-
27-
- repo: https://github.com/astral-sh/ruff-pre-commit
28-
rev: v0.4.3
29-
hooks:
30-
- id: ruff
31-
32-
- repo: local
33-
hooks:
34-
- id: pylint
35-
name: pylint
36-
entry: pylint "lib/"
24+
- id: pyright
25+
name: pyright
26+
entry: pyright
3727
language: system
38-
types: [ python ]
28+
types: [python]
3929
pass_filenames: false
40-
args:
41-
[
42-
"-rn", # Only display messages
43-
"-sn", # Don't display the score
44-
]

lib/main.py

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@
1616
from datetime import datetime, timedelta
1717
from typing import Annotated
1818

19-
2019
import tzlocal
20+
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
2121
from apscheduler.schedulers.background import BackgroundScheduler
22-
from apecheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
2322
from apscheduler.triggers.cron import CronTrigger
2423
from apscheduler.triggers.cron.fields import BaseField
2524
from fastapi import Depends, FastAPI, Response
@@ -37,13 +36,12 @@
3736
# os.environ["NEXTCLOUD_URL"] = "http://nextcloud.local"
3837
# os.environ["APP_PERSISTENT_STORAGE"] = "/tmp/"
3938

39+
# isort: off
4040
# Imported here to register environment variables before importing store (only for local dev purposes)
4141
import store
4242
from store import database_path
4343

44-
sqlite_url = f"sqlite:///{database_path}"
45-
46-
44+
SQLITE_URI = f"sqlite:///{database_path}"
4745

4846

4947
class LLMException(Exception):
@@ -59,10 +57,11 @@ class LLMException(Exception):
5957
logger.setLevel(logging.DEBUG)
6058
setup_nextcloud_logging(os.environ["APP_ID"], logging.WARNING)
6159

60+
6261
# The same stuff as for usual External Applications
6362
@asynccontextmanager
6463
async def lifespan(app: FastAPI):
65-
set_handlers(app, enabled_handler)
64+
set_handlers(app, enabled_handler) # pyright: ignore[reportArgumentType]
6665
yield
6766

6867

@@ -92,7 +91,7 @@ async def lifespan(app: FastAPI):
9291
9392
Now, please provide an insighful summary of the provided chat log and use human-readable time references for time related information.
9493
Use bullet points to list the most important facts and keep the summary concise and readable in roughly 30 seconds.
95-
""" # noqa: E501
94+
""" # noqa: E501
9695

9796
PROMPT_WINDOW = 16_000 - 4_000
9897
"""Most models (proprietory and local) have an effective context length of 16000 tokens. We leave 4000 tokens for the
@@ -104,10 +103,7 @@ async def lifespan(app: FastAPI):
104103
MAX_CHARACTERS = MAX_WORDS * 5
105104

106105

107-
108-
jobstores= {
109-
'default':SQLAlchemyJobStore(url=sqlite_url)
110-
}
106+
jobstores = {"default": SQLAlchemyJobStore(url=SQLITE_URI)}
111107

112108
scheduler = BackgroundScheduler(jobstores=jobstores)
113109
scheduler.start()
@@ -223,17 +219,17 @@ def sched_process_request(message: talk_bot.TalkBotMessage, job_hash: str):
223219

224220
def get_ctx_limited_messages(chat_messages: list[store.ChatMessages]) -> tuple[str, str | None]:
225221
"""Get the last messages that fit into the context window of the model.
226-
The second return is the cut-off datetime of the messages.
227-
"""
228222
223+
The second return is the cut-off datetime of the messages.
224+
"""
229225
msgs = ""
230226
length = 0
231227
cutoff = None
232228

233229
for i in range(len(chat_messages) - 1, -1, -1):
234230
msg = format_message(chat_messages[i])
235231
if (length := length + len(msg)) > MAX_CHARACTERS:
236-
cutoff = str(chat_messages[max(0, i-1)].timestamp)
232+
cutoff = str(chat_messages[max(0, i - 1)].timestamp)
237233
break
238234

239235
msgs = msg + "\n" + msgs
@@ -258,17 +254,18 @@ def last_x_duration_process(message: talk_bot.TalkBotMessage, hduration: str = "
258254
)
259255
return
260256

261-
duration = timedelta(seconds=timelength_res.to_seconds(max_precision=0))
257+
duration = timedelta(seconds=timelength_res.to_milliseconds(max_precision=0) * 0.001)
262258
current_time = datetime.now()
263259
start_time = current_time - duration
264260
start_time_str = start_time.strftime("%Y-%m-%d %H:%M:%S")
265261

266262
try:
267263
# Get the chat messages from the database
268-
chat_messages = store.ChatMessages \
269-
.select() \
270-
.where(store.ChatMessages.room_id == message.conversation_token) \
271-
.where(store.ChatMessages.timestamp >= start_time_str)
264+
chat_messages = (
265+
store.ChatMessages.select()
266+
.where(store.ChatMessages.room_id == message.conversation_token)
267+
.where(store.ChatMessages.timestamp >= start_time_str) # pyright: ignore[reportOperatorIssue]
268+
)
272269

273270
if chat_messages.count() == 0:
274271
BOT.send_message(f"```There was no conversation since i joined '{message.conversation_name}'```", message)
@@ -286,7 +283,9 @@ def last_x_duration_process(message: talk_bot.TalkBotMessage, hduration: str = "
286283
f" (All times are in {tz} timezone)*\n"
287284
)
288285
if cutoff:
289-
ai_info += f"\n\n*Note: Messages before \"{cutoff}\" were not included in the summary due to the length limit.*"
286+
ai_info += (
287+
f'\n\n*Note: Messages before "{cutoff}" were not included in the summary due to the length limit.*'
288+
)
290289
BOT.send_message(f"""**Summary:**\n{summary}\n\n{ai_info}""", message)
291290
except LLMException:
292291
error_handler("Could not get a summary from any large language model", message)
@@ -297,7 +296,8 @@ def is_numbers_and_colon(s: str):
297296

298297

299298
def help_message(message, text):
300-
BOT.send_message(f"""
299+
BOT.send_message(
300+
f"""
301301
**{os.environ["APP_DISPLAY_NAME"]}**:
302302
*{text}*
303303
@@ -321,7 +321,7 @@ def help_message(message, text):
321321
Prints a help message:
322322
@summary help
323323
```
324-
""", # noqa: E501
324+
""", # noqa: E501
325325
message,
326326
)
327327

@@ -418,7 +418,7 @@ def handle_command(message: talk_bot.TalkBotMessage):
418418
message,
419419
"Invalid time string provided, please use '30m' for 30 minutes, '3h40m' for 3 hours and 40 minutes,"
420420
" '1d' for 1 day",
421-
) # noqa: E501
421+
) # noqa: E501
422422
return
423423

424424
#########
@@ -454,7 +454,7 @@ def handle_command(message: talk_bot.TalkBotMessage):
454454
# Parameters for the new job
455455
new_job_hour = int(hour)
456456
new_job_minute = int(minute)
457-
new_job_hash = f"{conversation_token}_{hashlib.md5(f'{conversation_token}_{conversation_name}_{new_job_hour}_{new_job_minute}'.encode()).hexdigest()}" # noqa: E501, S324
457+
new_job_hash = f"{conversation_token}_{hashlib.md5(f'{conversation_token}_{conversation_name}_{new_job_hour}_{new_job_minute}'.encode()).hexdigest()}" # noqa: E501, S324
458458

459459
# Check if a similar job already exists
460460
job_exists = False
@@ -472,7 +472,7 @@ def handle_command(message: talk_bot.TalkBotMessage):
472472
job_minute = trigger.fields[trigger.FIELD_NAMES.index("minute")]
473473
job_day_of_week = trigger.fields[trigger.FIELD_NAMES.index("day_of_week")]
474474

475-
old_job_hash = f"{old_conversation_token}_{hashlib.md5(f'{old_conversation_token}_{conversation_name}_{job_hour}_{job_minute}'.encode()).hexdigest()}" # noqa: E501, S324
475+
old_job_hash = f"{old_conversation_token}_{hashlib.md5(f'{old_conversation_token}_{conversation_name}_{job_hour}_{job_minute}'.encode()).hexdigest()}" # noqa: E501, S324
476476

477477
if isinstance(job_hour, BaseField):
478478
job_hour = job_hour.expressions[0]
@@ -500,8 +500,8 @@ def handle_command(message: talk_bot.TalkBotMessage):
500500
return
501501

502502
BOT.send_message(
503-
f"```Skip - A {os.environ['APP_DISPLAY_NAME']} job already exists at {job_hour}:{job_minute}:00 for"
504-
f" '{conversation_name}'```",
503+
f"```Skip - A {os.environ['APP_DISPLAY_NAME']} job already exists at {job_hour}:{job_minute}:00"
504+
f" for '{conversation_name}'```",
505505
message,
506506
)
507507
return
@@ -525,8 +525,8 @@ def handle_command(message: talk_bot.TalkBotMessage):
525525
if minute <= 9:
526526
minute = f"0{minute}"
527527
BOT.send_message(
528-
f"```New: Added a daily {os.environ['APP_DISPLAY_NAME']} task at {hour}:{minute}:00 for '{conversation_name}' with the"
529-
f" id: {job_hash}```",
528+
f"```New: Added a daily {os.environ['APP_DISPLAY_NAME']} task at {hour}:{minute}:00"
529+
f" for '{conversation_name}' with the id: {job_hash}```",
530530
message,
531531
)
532532
except Exception:
@@ -570,8 +570,7 @@ def handle_command(message: talk_bot.TalkBotMessage):
570570

571571
if not job_id_to_delete:
572572
BOT.send_message(
573-
"```No Job ID to delete given - use '@summary list' to get a list of scheduled"
574-
" job ids```",
573+
"```No Job ID to delete given - use '@summary list' to get a list of scheduled" " job ids```",
575574
message,
576575
)
577576
return

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
# SPDX-License-Identifier: AGPL-3.0-or-later
33
[tool.black]
44
line-length = 120
5-
target-versions = ["py310"]
65
preview = true
76

87
[tool.ruff]
98
line-length = 120
109
target-version = "py310"
1110
select = ["A", "B", "C", "D", "E", "F", "G", "I", "S", "SIM", "PIE", "Q", "RET", "RUF", "UP" , "W"]
12-
extend-ignore = ["D101", "D102", "D103", "D105", "D107", "D203", "D213", "D401", "I001", "RUF100", "D400", "D415", "G004"]
11+
extend-ignore = ["C901", "D101", "D102", "D103", "D105", "D107", "D203", "D213", "D401", "I001", "RUF100", "D400", "D415", "G004"]
1312

1413
[tool.isort]
1514
profile = "black"

0 commit comments

Comments
 (0)