Skip to content

Commit 2d9197f

Browse files
committed
Add ruff (lint+format) and pyright (type check) tooling
- Add ruff and pyright as dev dependencies in pyproject.toml - Configure ruff: target py310, line-length 120, select E/F/I/UP, ignore E501 - Configure ruff format: skip-magic-trailing-comma (match project style) - Configure pyright: pythonVersion 3.10, exclude gui_streamlit - Auto-fix lint issues (import sorting, Optional->union syntax, f-string cleanup) - Fix all pyright type errors across the codebase - Document code quality checks in README Development Guide - Exclude uv.lock from version control
1 parent 7fec8f9 commit 2d9197f

36 files changed

Lines changed: 2172 additions & 1563 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ run.py
66
/dist/
77
/openfaker.egg-info/
88
__pycache__/
9+
uv.lock

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,23 @@ uv venv
306306
uv sync
307307
```
308308

309+
### Code quality checks
310+
311+
Before committing, please make sure the following checks pass locally:
312+
313+
```shell
314+
# Lint
315+
uv run ruff check openlrc/ tests/
316+
317+
# Format
318+
uv run ruff format --check openlrc/ tests/
319+
# To auto-fix formatting:
320+
# uv run ruff format openlrc/ tests/
321+
322+
# Type check
323+
uv run pyright openlrc/
324+
```
325+
309326
For live translation testing as a developer (and for CI usage), set:
310327

311328
```shell

openlrc/__init__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# Copyright (C) 2024. Hao Zheng
22
# All rights reserved.
33

4-
from openlrc.models import list_chatbot_models, ModelConfig, ModelProvider
4+
from openlrc.models import ModelConfig, ModelProvider, list_chatbot_models
55
from openlrc.openlrc import LRCer, TranscriptionConfig, TranslationConfig
66

7-
__all__ = ('LRCer', 'TranscriptionConfig', 'TranslationConfig',
8-
'ModelConfig', 'list_chatbot_models', 'ModelProvider')
9-
__version__ = '1.5.2'
10-
__author__ = 'zh-plus'
7+
__all__ = ("LRCer", "TranscriptionConfig", "TranslationConfig", "ModelConfig", "list_chatbot_models", "ModelProvider")
8+
__version__ = "1.5.2"
9+
__author__ = "zh-plus"

openlrc/agents.py

Lines changed: 160 additions & 93 deletions
Large diffs are not rendered by default.

openlrc/chatbot.py

Lines changed: 196 additions & 135 deletions
Large diffs are not rendered by default.

openlrc/context.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# Copyright (C) 2025. Hao Zheng
22
# All rights reserved.
33
import re
4-
from typing import Optional, Union, List
54

65
from pydantic import BaseModel
76

87
from openlrc import ModelConfig
98

109

1110
class TranslationContext(BaseModel):
12-
previous_summaries: Optional[List[str]] = None
13-
summary: Optional[str] = ''
14-
scene: Optional[str] = ''
15-
model: Optional[Union[str, ModelConfig]] = None
16-
guideline: Optional[str] = None
11+
previous_summaries: list[str] | None = None
12+
summary: str | None = ""
13+
scene: str | None = ""
14+
model: str | ModelConfig | None = None
15+
guideline: str | None = None
1716

1817
def update(self, **args):
1918
for key, value in args.items():
@@ -22,12 +21,14 @@ def update(self, **args):
2221

2322
@property
2423
def non_glossary_guideline(self) -> str:
25-
cleaned_text = re.sub(r'### Glossary.*?### Characters', '### Characters', self.guideline, flags=re.DOTALL)
24+
if not self.guideline:
25+
return ""
26+
cleaned_text = re.sub(r"### Glossary.*?### Characters", "### Characters", self.guideline, flags=re.DOTALL)
2627
return cleaned_text
2728

2829

2930
class TranslateInfo(BaseModel):
30-
title: Optional[str] = ''
31-
audio_type: str = 'Movie'
32-
glossary: Optional[dict] = None
31+
title: str | None = ""
32+
audio_type: str = "Movie"
33+
glossary: dict | None = None
3334
forced_glossary: bool = False

openlrc/defaults.py

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,23 @@
1212
"repetition_penalty": 1.0,
1313
"no_repeat_ngram_size": 0,
1414
"temperature": 0.0,
15-
1615
# We assume the voice is valid after VAD, log_prob_threshold is not reliable, set these 3 to None to prevent
1716
# miss-transcription, see https://github.com/openai/whisper/discussions/29#discussioncomment-3726710 for details
1817
"compression_ratio_threshold": None,
1918
"log_prob_threshold": None,
2019
"no_speech_threshold": None,
2120
"condition_on_previous_text": True,
22-
2321
"initial_prompt": None,
2422
"prefix": None,
2523
"suppress_blank": True,
2624
"suppress_tokens": [-1],
2725
"without_timestamps": False,
28-
2926
"word_timestamps": True,
3027
"prepend_punctuations": "\"'“¿([{-",
3128
"append_punctuations": "\"'.。,,!!??::”)]}、",
3229
# "hallucination_silence_threshold": 2,
3330
"hotwords": None,
34-
35-
"chunk_length": None
31+
"chunk_length": None,
3632
}
3733

3834
# Check https://github.com/SYSTRAN/faster-whisper/blob/master/faster_whisper/transcribe.py#L123 for details
@@ -42,22 +38,62 @@
4238
"min_speech_duration_ms": 0,
4339
"max_speech_duration_s": float("inf"),
4440
"min_silence_duration_ms": 2000,
45-
"speech_pad_ms": 400
41+
"speech_pad_ms": 400,
4642
}
4743

48-
default_preprocess_options = {
49-
'atten_lim_db': 15
50-
}
44+
default_preprocess_options = {"atten_lim_db": 15}
5145

5246
# Currently bottleneck-ed by Spacy
5347
supported_languages = {
54-
'ca', 'zh', 'hr', 'da', 'nl', 'en', 'fi', 'fr', 'de', 'el', 'it', 'ja', 'ko', 'lt', 'mk', 'nb', 'pl', 'pt', 'ro',
55-
'ru', 'sl', 'es', 'sv', 'uk'
48+
"ca",
49+
"zh",
50+
"hr",
51+
"da",
52+
"nl",
53+
"en",
54+
"fi",
55+
"fr",
56+
"de",
57+
"el",
58+
"it",
59+
"ja",
60+
"ko",
61+
"lt",
62+
"mk",
63+
"nb",
64+
"pl",
65+
"pt",
66+
"ro",
67+
"ru",
68+
"sl",
69+
"es",
70+
"sv",
71+
"uk",
5672
}
5773

5874
supported_languages_lingua = {
59-
Language.CATALAN, Language.CHINESE, Language.CROATIAN, Language.DANISH, Language.DUTCH, Language.ENGLISH,
60-
Language.FINNISH, Language.FRENCH, Language.GERMAN, Language.GREEK, Language.ITALIAN, Language.JAPANESE,
61-
Language.KOREAN, Language.LITHUANIAN, Language.MACEDONIAN, Language.BOKMAL, Language.POLISH, Language.PORTUGUESE,
62-
Language.ROMANIAN, Language.RUSSIAN, Language.SLOVENE, Language.SPANISH, Language.SWEDISH, Language.UKRAINIAN
75+
Language.CATALAN,
76+
Language.CHINESE,
77+
Language.CROATIAN,
78+
Language.DANISH,
79+
Language.DUTCH,
80+
Language.ENGLISH,
81+
Language.FINNISH,
82+
Language.FRENCH,
83+
Language.GERMAN,
84+
Language.GREEK,
85+
Language.ITALIAN,
86+
Language.JAPANESE,
87+
Language.KOREAN,
88+
Language.LITHUANIAN,
89+
Language.MACEDONIAN,
90+
Language.BOKMAL,
91+
Language.POLISH,
92+
Language.PORTUGUESE,
93+
Language.ROMANIAN,
94+
Language.RUSSIAN,
95+
Language.SLOVENE,
96+
Language.SPANISH,
97+
Language.SWEDISH,
98+
Language.UKRAINIAN,
6399
}

openlrc/evaluate.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright (C) 2025. Hao Zheng
22
# All rights reserved.
33
import abc
4-
from typing import Union
54

65
from openlrc.agents import TranslationEvaluatorAgent
76
from openlrc.models import ModelConfig
@@ -26,7 +25,7 @@ class LLMTranslationEvaluator(TranslationEvaluator):
2625
Evaluate the translated texts using large language models.
2726
"""
2827

29-
def __init__(self, chatbot_model: Union[str, ModelConfig] = 'gpt-4.1-nano'):
28+
def __init__(self, chatbot_model: str | ModelConfig = "gpt-4.1-nano"):
3029
self.agenet = TranslationEvaluatorAgent(chatbot_model=chatbot_model)
3130

3231
def evaluate(self, src_texts, target_texts, src_lang=None, target_lang=None):

openlrc/exceptions.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Copyright (C) 2024. Hao Zheng
22
# All rights reserved.
3-
from typing import Union
43

54
from anthropic.types import Message
65
from openai.types.chat import ChatCompletion
@@ -13,8 +12,8 @@ class SameLanguageException(Exception):
1312

1413
def __init__(self):
1514
super().__init__(
16-
'Source language and target language are the same, no need to translate. '
17-
'If you want to translate, set force_translate=True.'
15+
"Source language and target language are the same, no need to translate. "
16+
"If you want to translate, set force_translate=True."
1817
)
1918

2019

@@ -32,8 +31,9 @@ class LengthExceedException(ChatBotException):
3231
Raised when the length of generated response exceeds the limit.
3332
"""
3433

35-
def __init__(self, response: Union[ChatCompletion, Message]):
34+
def __init__(self, response: ChatCompletion | Message):
3635
if isinstance(response, ChatCompletion):
36+
assert response.usage is not None, "ChatCompletion.usage is None"
3737
prompt_tokens = response.usage.prompt_tokens
3838
completion_tokens = response.usage.completion_tokens
3939
total_tokens = response.usage.total_tokens
@@ -42,14 +42,14 @@ def __init__(self, response: Union[ChatCompletion, Message]):
4242
completion_tokens = response.usage.output_tokens
4343
total_tokens = prompt_tokens + completion_tokens
4444
else:
45-
raise ValueError(f'Invalid response type: {type(response)}')
45+
raise ValueError(f"Invalid response type: {type(response)}")
4646

4747
super().__init__(
48-
f'Failed to get completion. Exceed max token length. '
49-
f'Prompt tokens: {prompt_tokens}, '
50-
f'Completion tokens: {completion_tokens}, '
51-
f'Total tokens: {total_tokens} '
52-
f'Reduce chunk_size may help.'
48+
f"Failed to get completion. Exceed max token length. "
49+
f"Prompt tokens: {prompt_tokens}, "
50+
f"Completion tokens: {completion_tokens}, "
51+
f"Total tokens: {total_tokens} "
52+
f"Reduce chunk_size may help."
5353
)
5454

5555

@@ -59,7 +59,7 @@ class OpenaiFailureException(Exception):
5959
"""
6060

6161
def __init__(self):
62-
super().__init__('OpenAI API failed to generate response.')
62+
super().__init__("OpenAI API failed to generate response.")
6363

6464

6565
class FfmpegException(Exception):
@@ -74,4 +74,4 @@ def __init__(self, message):
7474

7575
class DependencyException(Exception):
7676
def __init__(self, message):
77-
super().__init__(f'Dependency not correctly installed: {message}')
77+
super().__init__(f"Dependency not correctly installed: {message}")

0 commit comments

Comments
 (0)