mirror of
https://github.com/Xevion/leetcode.git
synced 2025-12-06 05:15:30 -06:00
Add debug flag, add difficulty to question data, more log statements
This commit is contained in:
@@ -36,6 +36,7 @@ class Question(BaseModel):
|
|||||||
id: int
|
id: int
|
||||||
slug: str
|
slug: str
|
||||||
title: str
|
title: str
|
||||||
|
difficulty: str
|
||||||
tags: List[Tag]
|
tags: List[Tag]
|
||||||
|
|
||||||
|
|
||||||
@@ -44,12 +45,13 @@ class QuestionDatabase(object):
|
|||||||
A class for managing the question database.
|
A class for managing the question database.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cache_path: Path, cache_time: int) -> None:
|
def __init__(self, cache_path: Path, cache_time: int, debug: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
Initializes the question database.
|
Initializes the question database.
|
||||||
|
|
||||||
:param cache_time: The amount of time to cache all questions for, in seconds.
|
:param cache_time: The amount of time to cache all questions for, in seconds.
|
||||||
"""
|
"""
|
||||||
|
self.debug = debug
|
||||||
self.client = Session()
|
self.client = Session()
|
||||||
self.client.headers["Content-Type"] = "application/json"
|
self.client.headers["Content-Type"] = "application/json"
|
||||||
self.client.headers["Referer"] = "https://leetcode.com/problemset/all/"
|
self.client.headers["Referer"] = "https://leetcode.com/problemset/all/"
|
||||||
@@ -71,9 +73,12 @@ class QuestionDatabase(object):
|
|||||||
Question(**question) for question in raw_cache["questions"]
|
Question(**question) for question in raw_cache["questions"]
|
||||||
]
|
]
|
||||||
logger.info(f"Loaded {len(self.questions)} questions from cache.")
|
logger.info(f"Loaded {len(self.questions)} questions from cache.")
|
||||||
|
else:
|
||||||
|
logger.info(f"Cache file {cache_path} does not exist.")
|
||||||
|
|
||||||
# Question data wasn't loaded from the cache, so we fetch it (and store it in the cache) now
|
# Question data wasn't loaded from the cache, so we fetch it (and store it in the cache) now
|
||||||
if self.questions is None:
|
if self.questions is None:
|
||||||
|
|
||||||
# Make sure the directory holding it does exist (this shouldn't ever be raised, so this is just a sanity check)
|
# Make sure the directory holding it does exist (this shouldn't ever be raised, so this is just a sanity check)
|
||||||
if not cache_path.parent.exists():
|
if not cache_path.parent.exists():
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
@@ -81,7 +86,7 @@ class QuestionDatabase(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
logger.info("Fetching questions from LeetCode...")
|
logger.info("Fetching questions from LeetCode...")
|
||||||
fetch_time = time.time()
|
fetch_time = int(time.time())
|
||||||
self.questions = self.fetch()
|
self.questions = self.fetch()
|
||||||
|
|
||||||
logger.info(f"Writing {len(self.questions)} questions to cache...")
|
logger.info(f"Writing {len(self.questions)} questions to cache...")
|
||||||
@@ -160,22 +165,26 @@ class QuestionDatabase(object):
|
|||||||
"variables": {
|
"variables": {
|
||||||
"categorySlug": "",
|
"categorySlug": "",
|
||||||
"filters": {},
|
"filters": {},
|
||||||
"limit": 50,
|
"limit": 50 if self.debug else total,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger.debug("{:,} bytes received.".format(len(questions_response.content)))
|
||||||
|
|
||||||
if not questions_response.ok:
|
if not questions_response.ok:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Failed to fetch questions: {questions_response.status_code} {questions_response.reason}"
|
f"Failed to fetch questions: {questions_response.status_code} {questions_response.reason}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Parse & extract question data into Pydantic models
|
||||||
questions = questions_response.json()["data"]["questionsList"]["questions"]
|
questions = questions_response.json()["data"]["questionsList"]["questions"]
|
||||||
return [
|
return [
|
||||||
Question(
|
Question(
|
||||||
id=question["id"],
|
id=question["id"],
|
||||||
slug=question["titleSlug"],
|
slug=question["titleSlug"],
|
||||||
title=question["title"],
|
title=question["title"],
|
||||||
|
difficulty=question["difficulty"],
|
||||||
tags=[
|
tags=[
|
||||||
Tag(name=tag["name"], slug=tag["slug"])
|
Tag(name=tag["name"], slug=tag["slug"])
|
||||||
for tag in question["topicTags"]
|
for tag in question["topicTags"]
|
||||||
@@ -184,14 +193,14 @@ class QuestionDatabase(object):
|
|||||||
for question in questions
|
for question in questions
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_by_id(self, question_id: int) -> Question:
|
def get_by_id(self, question_id: int) -> Question | None:
|
||||||
"""
|
"""
|
||||||
Gets a question by its ID.
|
Gets a question by its ID.
|
||||||
"""
|
"""
|
||||||
return self.by_id[question_id]
|
return self.by_id.get(question_id)
|
||||||
|
|
||||||
def get_by_slug(self, slug: str) -> Question:
|
def get_by_slug(self, slug: str) -> Question | None:
|
||||||
"""
|
"""
|
||||||
Gets a question by its slug.
|
Gets a question by its slug.
|
||||||
"""
|
"""
|
||||||
return self.by_slug[slug]
|
return self.by_slug.get(slug)
|
||||||
|
|||||||
Reference in New Issue
Block a user