Skip to content

Commit b7fef4a

Browse files
committed
Refactor: Extract and exclude common content from README
This commit refactors the code that handles common content in README files for assignments. It introduces two functions: - `assignment_instruction()`: This function takes a README file path and returns the assignment-specific instructions, excluding any common content. It uses configurable markers to identify the common content. - `exclude_common_contents()`: This function takes a string containing README content and returns a new string with the common content removed. This refactoring improves code organization, readability, and maintainability. It also makes the code more flexible by allowing the common content markers to be configured. Additionally, this commit adds comprehensive docstrings to both functions, enhancing the documentation and making the code easier to understand.
1 parent 99bd6e8 commit b7fef4a

2 files changed

Lines changed: 99 additions & 3 deletions

File tree

ai_tutor.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import json
33
import logging
44
import pathlib
5+
import re
56
import time
6-
77
from typing import Dict, List, Tuple
88

99
import requests
@@ -238,8 +238,65 @@ def assignment_code(student_files:Tuple[pathlib.Path]) -> str:
238238

239239

240240
@functools.lru_cache
241-
def assignment_instruction(readme_file:pathlib.Path) -> str:
242-
return readme_file.read_text()
241+
def assignment_instruction(
242+
readme_file: pathlib.Path,
243+
common_content_start_marker: str = r"``From here is common to all assignments\.``",
244+
common_content_end_marker: str = r"``Until here is common to all assignments\.``",
245+
) -> str:
246+
"""Extracts assignment-specific instructions from a README.md file.
247+
248+
This function reads a README.md file and removes content marked as common
249+
to all assignments, returning only the assignment-specific instructions.
250+
251+
Args:
252+
readme_file: Path to the README.md file.
253+
common_content_start_marker: The marker indicating the start of common content.
254+
common_content_end_marker: The marker indicating the end of common content.
255+
256+
Returns:
257+
A string containing the assignment-specific instructions.
258+
"""
259+
260+
return exclude_common_contents(
261+
readme_file.read_text(),
262+
common_content_start_marker,
263+
common_content_end_marker,
264+
) # Single exit point
265+
266+
267+
def exclude_common_contents(
268+
readme_content:str,
269+
common_content_start_marker: str = r"``From here is common to all assignments\.``",
270+
common_content_end_marker: str = r"``Until here is common to all assignments\.``",
271+
) -> str:
272+
"""Removes common content from a string.
273+
274+
This function takes a string and removes the content between the specified
275+
start and end markers.
276+
277+
Args:
278+
readme_content: The input string containing the README content.
279+
common_content_start_marker: The marker indicating the start of common content.
280+
common_content_end_marker: The marker indicating the end of common content.
281+
282+
Returns:
283+
A string with the common content removed.
284+
"""
285+
# Include the markers in the pattern itself
286+
pattern = rf"(.*?){common_content_start_marker}\s*(.*?)\s*{common_content_end_marker}(.*?)"
287+
match = re.search(pattern, readme_content, re.DOTALL | re.IGNORECASE)
288+
289+
if match:
290+
# Extract the parts before and after the common content
291+
before_common = match.group(1).strip()
292+
after_common = match.group(3).strip()
293+
# Combine them to get the final instructions
294+
instruction = (before_common + after_common).strip()
295+
else:
296+
logging.warning(f"Common content markers '{common_content_start_marker}' and '{common_content_end_marker}' not found in README.md. Returning entire file.")
297+
instruction = readme_content.strip() # Single exit point
298+
299+
return instruction
243300

244301

245302
@functools.lru_cache(maxsize=None)

tests/test_ai_tutor.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,5 +280,44 @@ def test_load_locale(explanation_in:str, homework:Tuple[str]):
280280
)
281281

282282

283+
def test__exclude_common_contents__single():
284+
start_marker = '``From here is common to all assignments.``'
285+
end_marker = '``Until here is common to all assignments.``'
286+
287+
common_line_0 = "def subtract(a, b):"
288+
common_line_1 = "return a - b"
289+
290+
common_content = start_marker + (
291+
'``\n'
292+
"\n"
293+
f"{common_line_0}\n"
294+
f" {common_line_1}\n"
295+
) + end_marker + '\n'
296+
297+
specific_line_0 = "def add(a, b):"
298+
specific_line_1 = "return a + b"
299+
300+
content = (
301+
"Write a function that returns the sum of two numbers.\n"
302+
"\n"
303+
f"{specific_line_0}\n"
304+
f" {specific_line_1}\n"
305+
) + common_content
306+
307+
result = ai_tutor.exclude_common_contents(
308+
readme_content=content,
309+
common_content_start_marker=start_marker,
310+
common_content_end_marker=end_marker,
311+
)
312+
313+
assert specific_line_0 in result
314+
assert specific_line_1 in result
315+
316+
assert common_line_0 not in result
317+
assert common_line_1 not in result
318+
assert start_marker not in result
319+
assert end_marker not in result
320+
321+
283322
if '__main__' == __name__:
284323
pytest.main([__file__])

0 commit comments

Comments
 (0)