Skip to content

Commit e790519

Browse files
More ruff stuff
1 parent da9d731 commit e790519

8 files changed

Lines changed: 33 additions & 99 deletions

backend/fastapi_generate_quiz.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,9 @@
7575

7676
@app.get("/GenerateQuiz")
7777
async def generate_quiz_endpoint(
78-
topic: str = Query(
79-
..., description="The subject for the quiz (e.g., 'UK History')"
80-
),
81-
difficulty: str = Query(
82-
..., description="The desired difficulty (e.g., 'easy', 'medium', 'hard')"
83-
),
84-
n_questions: int = Query(
85-
10, description="Number of questions to generate (defaults to 10)"
86-
),
78+
topic: str = Query(..., description="The subject for the quiz (e.g., 'UK History')"),
79+
difficulty: str = Query(..., description="The desired difficulty (e.g., 'easy', 'medium', 'hard')"),
80+
n_questions: int = Query(10, description="Number of questions to generate (defaults to 10)"),
8781
model: Optional[str] = Query(
8882
None,
8983
description="The model to use. If not provided, the default from QuizGenerator is used",
@@ -101,14 +95,9 @@ async def generate_quiz_endpoint(
10195
Returns:
10296
- StreamingResponse: Streams quiz questions in SSE format.
10397
"""
104-
logger.info(
105-
f"Quiz request: topic={topic}, difficulty={difficulty}, "
106-
f"n_questions={n_questions}, model={model}"
107-
)
108-
109-
logging.info(
110-
f"Generating quiz with: {topic=}, {difficulty=}, {n_questions=}, {model=}."
111-
)
98+
logger.info(f"Quiz request: topic={topic}, difficulty={difficulty}, n_questions={n_questions}, model={model}")
99+
100+
logging.info(f"Generating quiz with: {topic=}, {difficulty=}, {n_questions=}, {model=}.")
112101

113102
# Create a QuizGenerator instance.
114103
# TODO: rename to quiz creator ?

backend/generate_image.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
from openai import OpenAI
66

77
logger = logging.getLogger(__name__)
8-
logging.basicConfig(
9-
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
10-
)
8+
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
119

1210

1311
class ImageGenerator:
@@ -23,10 +21,7 @@ def get_api_key_from_env(cls) -> str:
2321
"""
2422
api_key = os.getenv("OPENAI_API_KEY")
2523
if not api_key:
26-
raise ValueError(
27-
"Environment variable OPENAI_API_KEY is not set. "
28-
"Please ensure it's set and try again."
29-
)
24+
raise ValueError("Environment variable OPENAI_API_KEY is not set. Please ensure it's set and try again.")
3025
return api_key
3126

3227
def __init__(self, api_key: Optional[str] = None):
@@ -43,9 +38,7 @@ def __init__(self, api_key: Optional[str] = None):
4338

4439
self.client = OpenAI(api_key=api_key)
4540

46-
def generate_image(
47-
self, prompt: str, n: int = 1, size: str = "256x256"
48-
) -> Optional[str]:
41+
def generate_image(self, prompt: str, n: int = 1, size: str = "256x256") -> Optional[str]:
4942
"""Generates an image based on the provided prompt.
5043
5144
Args:
@@ -84,10 +77,6 @@ def _get_image_url(self, prompt: str, n: int, size: str) -> Optional[str]:
8477

8578
if __name__ == "__main__":
8679
# Example usage:
87-
image_generator = (
88-
ImageGenerator()
89-
) # Uses environment variable if no API key is provided
90-
prompt_text = (
91-
"Crested Gecko showcasing its distinct crests and colouration. Pixel Art"
92-
)
80+
image_generator = ImageGenerator() # Uses environment variable if no API key is provided
81+
prompt_text = "Crested Gecko showcasing its distinct crests and colouration. Pixel Art"
9382
image_url = image_generator.generate_image(prompt_text)

backend/generate_quiz.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,7 @@ def check_model_is_supported(model: str) -> str:
100100
str: A supported model name.
101101
"""
102102
if model not in QuizGenerator.SUPPORTED_MODELS:
103-
logger.warning(
104-
f"Model '{model}' is not supported. Defaulting to 'gpt-4-turbo'."
105-
)
103+
logger.warning(f"Model '{model}' is not supported. Defaulting to 'gpt-4-turbo'.")
106104
return "gpt-4-turbo"
107105
return model
108106

@@ -129,9 +127,7 @@ def __init__(
129127
# Use the separate parser class to handle the stream.
130128
self.parser = ResponseStreamParser()
131129

132-
def generate_quiz(
133-
self, topic: str, difficulty: str, n_questions: int = 10
134-
) -> Generator[str, None, None]:
130+
def generate_quiz(self, topic: str, difficulty: str, n_questions: int = 10) -> Generator[str, None, None]:
135131
"""
136132
Generate a quiz based on the provided topic and difficulty using litellm.
137133

backend/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ dev = [
2525
dev = "uvicorn fastapi_generate_quiz:app --reload --host 0.0.0.0 --port 8000"
2626

2727
[tool.ruff]
28-
line-length = 88
28+
line-length = 120
2929
target-version = "py310"
3030

3131
[tool.ruff.lint]

backend/tests/conftest.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33

44
# Add backend directory explicitly
55
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) # Add tests directory
6-
sys.path.insert(
7-
0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
8-
) # Add backend directory
6+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) # Add backend directory

backend/tests/test_generate_image.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,22 @@ def test_generate_image_success(self, mocker, image_generator):
3131
"""Test generate_image with a successful API response."""
3232
# Create a mock response simulating the structure returned by OpenAI.
3333
mock_response = mocker.Mock()
34-
mock_response.data = [
35-
SimpleNamespace(url="https://example.com/generated_image.png")
36-
]
34+
mock_response.data = [SimpleNamespace(url="https://example.com/generated_image.png")]
3735

3836
# Patch the generate method of the images client.
39-
mocker.patch.object(
40-
image_generator.client.images, "generate", return_value=mock_response
41-
)
37+
mocker.patch.object(image_generator.client.images, "generate", return_value=mock_response)
4238

4339
url = image_generator.generate_image("A test prompt")
4440
assert url == "https://example.com/generated_image.png"
4541

4642
def test_generate_image_custom_size(self, mocker, image_generator):
4743
"""Test generate_image with a custom image size."""
4844
mock_response = mocker.Mock()
49-
mock_response.data = [
50-
SimpleNamespace(url="https://example.com/custom_size_image.png")
51-
]
45+
mock_response.data = [SimpleNamespace(url="https://example.com/custom_size_image.png")]
5246

53-
mocker.patch.object(
54-
image_generator.client.images, "generate", return_value=mock_response
55-
)
47+
mocker.patch.object(image_generator.client.images, "generate", return_value=mock_response)
5648

57-
url = image_generator.generate_image(
58-
"A dragon flying over mountains", size="512x512"
59-
)
49+
url = image_generator.generate_image("A dragon flying over mountains", size="512x512")
6050
assert url == "https://example.com/custom_size_image.png"
6151

6252
def test_generate_image_api_failure(self, mocker, image_generator):
@@ -85,9 +75,7 @@ def test_openai_api_key_not_set(self, mocker):
8575
# Clear environment variables to simulate missing API key.
8676
mocker.patch.dict(os.environ, {}, clear=True)
8777

88-
with pytest.raises(
89-
ValueError, match="Environment variable OPENAI_API_KEY is not set"
90-
):
78+
with pytest.raises(ValueError, match="Environment variable OPENAI_API_KEY is not set"):
9179
ImageGenerator()
9280

9381
def test_logging_when_api_fails(self, mocker, image_generator):

backend/tests/test_generate_quiz.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ class TestQuizGenerator:
3636

3737
def test_check_model_is_supported(self):
3838
"""Test that unsupported models default to 'gpt-4-turbo'."""
39-
assert (
40-
QuizGenerator.check_model_is_supported("unsupported-model") == "gpt-4-turbo"
41-
)
42-
assert (
43-
QuizGenerator.check_model_is_supported("gpt-3.5-turbo") == "gpt-3.5-turbo"
44-
)
39+
assert QuizGenerator.check_model_is_supported("unsupported-model") == "gpt-4-turbo"
40+
assert QuizGenerator.check_model_is_supported("gpt-3.5-turbo") == "gpt-3.5-turbo"
4541

4642
def test_environment_variable_not_set(self, monkeypatch):
4743
"""
@@ -79,9 +75,7 @@ def test_generate_quiz(self, mock_completion, quiz_generator):
7975
mock_completion.return_value = mock_stream
8076

8177
parser_mock = MagicMock()
82-
parser_mock.parse_stream.return_value = iter(
83-
['data: {"question": "What is 2+2?", "answer": "4"}\n\n']
84-
)
78+
parser_mock.parse_stream.return_value = iter(['data: {"question": "What is 2+2?", "answer": "4"}\n\n'])
8579

8680
with patch.object(quiz_generator, "parser", parser_mock):
8781
generator = quiz_generator.generate_quiz("Math", "Easy", n_questions=1)
@@ -116,9 +110,7 @@ def test_model(self, model):
116110
pytest.skip("GEMINI_API_KEY not set")
117111
elif provider == "deepseek" and not os.getenv("DEEPSEEK_API_KEY"):
118112
pytest.skip("DEEPSEEK_API_KEY not set")
119-
elif provider == "azure_ai" and (
120-
not os.getenv("AZURE_AI_API_KEY") or not os.getenv("AZURE_AI_API_BASE")
121-
):
113+
elif provider == "azure_ai" and (not os.getenv("AZURE_AI_API_KEY") or not os.getenv("AZURE_AI_API_BASE")):
122114
pytest.skip("Azure AI credentials not set")
123115

124116
# Test the model

backend/tests/test_response_stream_parser.py

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ def test_extract_chunk_content_valid(self, response_parser):
3030
"""
3131
Test extracting content from a valid chunk.
3232
"""
33-
chunk = SimpleNamespace(
34-
choices=[SimpleNamespace(delta=SimpleNamespace(content="test content"))]
35-
)
33+
chunk = SimpleNamespace(choices=[SimpleNamespace(delta=SimpleNamespace(content="test content"))])
3634
content = response_parser._extract_chunk_content(chunk)
3735
assert content == "test content"
3836

@@ -48,9 +46,7 @@ def test_split_buffer(self, response_parser):
4846
"""
4947
Test splitting the buffer into complete lines and a remainder.
5048
"""
51-
response_parser.buffer = (
52-
'{"question": "Who was ..."}\n{"question": "What is ..."}\nincomplete'
53-
)
49+
response_parser.buffer = '{"question": "Who was ..."}\n{"question": "What is ..."}\nincomplete'
5450

5551
expected_complete_lines = [
5652
'{"question": "Who was ..."}',
@@ -63,13 +59,11 @@ def test_split_buffer(self, response_parser):
6359
print("Complete Lines:", complete_lines)
6460
print("Remainder:", remainder)
6561

66-
assert (
67-
complete_lines == expected_complete_lines
68-
), f"Expected complete lines '{expected_complete_lines}', but got {complete_lines}"
62+
assert complete_lines == expected_complete_lines, (
63+
f"Expected complete lines '{expected_complete_lines}', but got {complete_lines}"
64+
)
6965

70-
assert (
71-
remainder == expected_remainder
72-
), f"Expected remainder '{expected_remainder}', but got {remainder}"
66+
assert remainder == expected_remainder, f"Expected remainder '{expected_remainder}', but got {remainder}"
7367

7468
def test_process_line_valid_json(self, response_parser):
7569
"""
@@ -93,20 +87,8 @@ def test_parse_stream(self, response_parser):
9387
"""
9488
fake_stream = iter(
9589
[
96-
SimpleNamespace(
97-
choices=[
98-
SimpleNamespace(
99-
delta=SimpleNamespace(content='{"question": "First"}\n')
100-
)
101-
]
102-
),
103-
SimpleNamespace(
104-
choices=[
105-
SimpleNamespace(
106-
delta=SimpleNamespace(content='{"question": "Second"}\n')
107-
)
108-
]
109-
),
90+
SimpleNamespace(choices=[SimpleNamespace(delta=SimpleNamespace(content='{"question": "First"}\n'))]),
91+
SimpleNamespace(choices=[SimpleNamespace(delta=SimpleNamespace(content='{"question": "Second"}\n'))]),
11092
]
11193
)
11294
results = list(response_parser.parse_stream(fake_stream))

0 commit comments

Comments
 (0)