Skip to content

Commit 28f8db1

Browse files
committed
class restructurization
1 parent 65e18dc commit 28f8db1

File tree

7 files changed

+152
-87
lines changed

7 files changed

+152
-87
lines changed

leetcode/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# TODO: add a command to show the solution in the browser
1717
# TODO: problem with import in synced code or code to submit
1818
# TODO: random problem selector (from not accepted problems)
19+
# TODO: check the changes in question_content and apply them to the code in other files
1920

2021
def positive_integer(value):
2122
try:

leetcode/models/graphql_problemset_question_list.py

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from leetcode.models import *
22

3+
""" This module contains the QueryTemplate class for the problemsetQuestionList query.
4+
The class is used to fetch a list of LeetCode problems by the 'list' command.
5+
"""
6+
37
@dataclass
48
class QueryResult(JSONWizard):
59
@dataclass
@@ -53,44 +57,53 @@ class ProblemsetQuestionList(QueryTemplate):
5357
- 'difficulty' (str, optional): Difficulty level. Valid values: 'EASY', 'MEDIUM', 'HARD'.
5458
- 'status' (str, optional): Status of the problem. Valid values: 'NOT_STARTED', 'TRIED', 'AC'.
5559
limit (int, optional): Maximum number of problems to retrieve. Defaults to None.
60+
If not provided, the value is taken from the user config file.
5661
skip (int, optional): Number of problems to skip. Defaults to 0.
5762
"""
5863

5964
def __init__(self, filters={}, limit=None, skip=0):
6065
super().__init__()
61-
6266
# Instance specific variables
6367
self.page : int = 1
6468
self.max_page : int = 0
6569
self.filters = filters
6670
self.limit = limit or self.config.user_config.get('question_list_limit')
6771
self.skip = skip
72+
self._data_fetched: bool = False
6873

69-
self.params = {'categorySlug': "",
74+
self._params = {'categorySlug': "",
7075
'skip':self.skip,
7176
'limit': self.limit,
7277
'filters': self.filters}
73-
74-
self.graphql_query = None
75-
self.result = None
78+
79+
self.data = None
7680

7781
def fetch_data(self, parameters: Dict = None) -> QueryResult:
78-
""" Fetches the data from the LeetCode API.
82+
""" Fetches the data from the LeetCode API.
83+
Updates the state of the object.
7984
8085
Args:
8186
parameters (dict, optional): Parameters to pass to the query. Defaults to None.
8287
8388
Returns:
8489
QueryResult: The result of the query.
8590
"""
86-
87-
if parameters is None:
88-
parameters = self.params
89-
with Loader('Fetching problems...', ''):
90-
self.graphql_query = GraphQLQuery(self.query, parameters)
91-
self.result = self.leet_API.post_query(self.graphql_query) # Take the response from the API
92-
self.result = QueryResult.from_dict(self.result['data'])
93-
return self.result
91+
try:
92+
with Loader('Fetching problems...', ''):
93+
if parameters is not None and parameters != self.params:
94+
self.params = parameters
95+
96+
if self.data_fetched:
97+
return self.data
98+
99+
self.graphql_query = GraphQLQuery(self.query, parameters)
100+
self.data = self.leet_API.post_query(self.graphql_query) # Take the response from the API
101+
self.data = QueryResult.from_dict(self.data['data'])
102+
self.data_fetched = True
103+
return self.data
104+
except Exception as e:
105+
console.print(f"{e.__class__.__name__}: {e}", style=ALERT)
106+
sys.exit(1)
94107

95108
def _execute(self, args):
96109
""" Executes the query with the given arguments and displays the result.
@@ -100,32 +113,31 @@ def _execute(self, args):
100113
"""
101114

102115
self.__parse_args(args)
103-
self.result = self.fetch_data()
104-
self.show(self.result)
116+
self.data = self.fetch_data()
117+
self.show(self.data)
105118

106-
def show(self, query_result: Optional[QueryResult] = None) -> None:
119+
def show(self) -> None:
107120
""" Displays the query result in a table.
108121
109122
Args:
110123
query_result (QueryResult, optional): The result of the query. Defaults to None.
111124
If the result is None, the method will try to fetch the data with defauly parameters and than display it.
112125
"""
113-
114-
if query_result is None:
115-
query_result = self.fetch_data()
116-
117-
displayed : int = self.limit * self.page if self.limit * self.page < query_result.total else self.result.total
118-
119-
table = LeetTable(title=f'Total number of problems retrieved: {query_result.total}\n',
120-
caption=f"Page #{self.page} / ({displayed}/{self.result.total})")
121-
122-
table.add_column('ID')
123-
table.add_column('Title')
124-
table.add_column('Status')
125-
table.add_column('Difficulty')
126-
for item in query_result.questions:
127-
table.add_row(item.questionId, item.title, item.status, item.difficulty)
128-
console.print(table)
126+
if self.data_fetched:
127+
displayed : int = self.limit * self.page if self.limit * self.page < self.data.total else self.data.total
128+
129+
table = LeetTable(title=f'Total number of problems retrieved: {self.data.total}\n',
130+
caption=f"Page #{self.page} / ({displayed}/{self.data.total})")
131+
132+
table.add_column('ID')
133+
table.add_column('Title')
134+
table.add_column('Status')
135+
table.add_column('Difficulty')
136+
for item in self.data.questions:
137+
table.add_row(item.questionId, item.title, item.status, item.difficulty)
138+
console.print(table)
139+
else:
140+
raise Exception("Data is not fetched yet.")
129141

130142
def __validate_page(self):
131143
""" Validates the current page number.
@@ -160,4 +172,21 @@ def __parse_args(self, args):
160172
self.page = getattr(args, 'page')
161173
self.params['skip'] = self.limit * self.page - self.limit
162174

163-
self.__validate_page()
175+
self.__validate_page()
176+
177+
@property
178+
def data_fetched(self):
179+
return self._data_fetched
180+
181+
@data_fetched.setter
182+
def data_fetched(self, data_fetched: bool):
183+
self._data_fetched = data_fetched
184+
185+
@property
186+
def params(self):
187+
return self._params
188+
189+
@params.setter
190+
def params(self, params: dict):
191+
self._params = params
192+
self.data_fetched = False

leetcode/models/graphql_question_content.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ class QuestionContent(QueryTemplate):
44
""" A class to represent a LeetCode problem content.
55
66
Args:
7-
title_slug (str): The title slug of the problem. """
7+
title_slug (str, optional): The title slug of the problem. If provided the data is fetched when the object is created. Defaults to None."""
88

9-
def __init__(self, title_slug):
9+
def __init__(self, title_slug: str = None):
1010
super().__init__()
1111
# Instance-specific variables
1212
self._title_slug = title_slug
@@ -15,36 +15,36 @@ def __init__(self, title_slug):
1515
self._data_fetched: bool = False
1616

1717
self.question_panels: List[rich.panel.Panel] = []
18-
self.fetch_data(self.title_slug)
18+
19+
if title_slug is not None:
20+
self.fetch_data(self.title_slug)
1921

2022
def fetch_data(self, title_slug: str = None) -> Dict:
2123
""" Fetches the content data for the problem.
2224
2325
Args:
24-
parameters (dict, optional): Parameters to pass to the query. Defaults to None.
26+
title_slug (str, optional): The title slug of the problem. Defaults to None.
2527
2628
Returns:
2729
Dict: The content data for the problem.
2830
"""
2931
try:
3032
with Loader('Fetching question details...', ''):
31-
parameters = self.params
32-
if title_slug is None:
33-
parameters = self.params
34-
elif title_slug != self.title_slug:
33+
# If provided title slug does not change anything, return the data
34+
if title_slug is not None and title_slug != self.title_slug:
3535
self.title_slug = title_slug
36-
self.params = {'titleSlug': title_slug}
37-
parameters = self.params
36+
3837
if self.data_fetched:
39-
return self._data
38+
return self.data
4039

41-
graphql_query = GraphQLQuery(self.query, parameters)
40+
graphql_query = GraphQLQuery(self.query, self.params)
4241
response = self.leet_API.post_query(graphql_query)
42+
4343
if response['data']['question'] is None:
4444
raise Exception('There is no question with title slug: ' + title_slug)
45+
4546
self.data = response['data']['question']['content']
4647
self.data_fetched = True
47-
self.params = parameters
4848
return self.data
4949
except Exception as e:
5050
console.print(f"{e.__class__.__name__}: {e}", style=ALERT)
@@ -121,7 +121,7 @@ def data_fetched(self, data_fetched: bool):
121121

122122

123123
if __name__ == '__main__':
124-
content = QuestionContent('two-sumfsdf')
124+
content = QuestionContent('two-sum')
125125
print(content)
126126
content.fetch_data('add-two-integers')
127127
print(content)

leetcode/models/graphql_question_info_table.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,38 +33,37 @@ class QuestionInfoTable(QueryTemplate):
3333
3434
Args:
3535
titleSlug (str): The title slug of the question to fetch data for.
36+
If provided the data is fetched when the object is created. Defaults to None.
3637
"""
3738

38-
def __init__(self, titleSlug):
39+
def __init__(self, title_slug: str = None):
3940
super().__init__()
4041
# Instance-specific variables
41-
self._title_slug = titleSlug
42+
self._title_slug = title_slug
4243
self._data = None
43-
self._params = {'titleSlug': titleSlug}
44+
self._params = {'titleSlug': title_slug}
4445
self._data_fetched: bool = False
4546

46-
self.fetch_data(self.title_slug)
47+
if title_slug is not None:
48+
self.fetch_data(self.title_slug)
4749

48-
def fetch_data(self, titleSlug: str = None) -> Dict:
50+
def fetch_data(self, title_slug: str = None) -> Dict:
4951
try:
5052
with Loader('Fetching question details...', ''):
51-
parameters = self.params
52-
if titleSlug is None:
53-
parameters = self.params
54-
elif titleSlug != self.title_slug:
55-
self.title_slug = titleSlug
56-
self.params = {'titleSlug': titleSlug}
57-
parameters = self.params
53+
if title_slug is not None and title_slug != self.title_slug:
54+
self.title_slug = title_slug
55+
5856
if self.data_fetched:
59-
return self._data
57+
return self.data
6058

61-
graphql_query = GraphQLQuery(self.query, parameters)
59+
graphql_query = GraphQLQuery(self.query, self.params)
6260
response = self.leet_API.post_query(graphql_query)
61+
6362
if response['data']['question'] is None:
64-
raise Exception('There is no question with title slug: ' + titleSlug)
63+
raise Exception('There is no question with title slug: ' + title_slug)
64+
6565
self.data = Question.from_dict(response['data'])
6666
self.data_fetched = True
67-
self.params = parameters
6867
return self.data
6968
except Exception as e:
7069
console.print(f"{e.__class__.__name__}: {e}", style=ALERT)

leetcode/models/graphql_question_of_today.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,23 @@ def __init__(self):
4343
self.title_slug: str = None
4444

4545
self.data = None
46+
47+
def fetch_data(self) -> Dict:
48+
""" Fetches the question of the day data.
49+
50+
Returns:
51+
Dict: The question of the day data.
52+
"""
53+
try:
54+
with Loader('Fetching question of the day...', ''):
55+
graphql_query = GraphQLQuery(self.query, {})
56+
response = self.leet_API.post_query(graphql_query)
57+
return response['data']
58+
except Exception as e:
59+
console.print(f"{e.__class__.__name__}: {e}", style=ALERT)
60+
sys.exit(1)
4661

47-
def _execute(self, args):
62+
def _execute(self, args) -> None:
4863
""" Executes the query with the given arguments and displays the result.
4964
5065
Args:
@@ -59,7 +74,7 @@ def _execute(self, args):
5974
self.title_slug = self.data.question.titleSlug
6075
self.show()
6176

62-
def show(self):
77+
def show(self) -> None:
6378
""" Shows the question information and content or opens the question in a browser.
6479
The displayed information depends on the flags passed to the command line.
6580
"""
@@ -77,7 +92,7 @@ def show(self):
7792
else:
7893
print(question_info_table)
7994

80-
def __parse_args(self, args):
95+
def __parse_args(self, args) -> None:
8196
""" Parses the command line arguments.
8297
8398
Args:

leetcode/models/graphql_submission_list.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,33 @@ def __init__(self):
3636
super().__init__()
3737
# Instance specific variables
3838
self.question_id: int = None
39-
self.show_terminal = False
40-
self.submission_download = False
39+
self.show_terminal: bool = False
40+
self.submission_download: bool = False
4141

42-
self.graphql_query = None
4342
self.data = None
4443
self.params = {'offset': 0, 'limit': 20, 'lastKey': None, 'questionSlug': None}
44+
45+
def fetch_data(self, question_id: int = None) -> Dict:
46+
""" Fetches the submission list data for the problem.
47+
48+
Args:
49+
question_id (int, optional): The question id of the problem. Defaults to None.
50+
51+
Returns:
52+
Dict: The submission list data for the problem.
53+
"""
54+
try:
55+
with Loader('Fetching submission list...', ''):
56+
if question_id is not None and question_id != self.question_id:
57+
self.question_id = question_id
58+
self.params['questionSlug'] = ProblemInfo.get_title_slug(self.question_id)
59+
60+
graphql_query = GraphQLQuery(self.query, self.params)
61+
response = self.leet_API.post_query(graphql_query)
62+
return response['data']
63+
except Exception as e:
64+
console.print(f"{e.__class__.__name__}: {e}", style=ALERT)
65+
sys.exit(1)
4566

4667
def _execute(self, args):
4768
""" Executes the query with the given arguments and displays the result.

0 commit comments

Comments
 (0)