Skip to content

Commit 2f4fadf

Browse files
committed
mypy
1 parent eb3e1fa commit 2f4fadf

7 files changed

Lines changed: 49 additions & 42 deletions

funpayparsers/parsers/categories_parser.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
__all__ = ('CategoriesParser', 'CategoriesParsingOptions')
55

6+
from typing import cast
67
from dataclasses import dataclass
78

89
from selectolax.lexbor import LexborNode
@@ -38,13 +39,13 @@ def _parse(self) -> list[Category]:
3839
# FunPay treats them as different categories,
3940
# but on main page they are in the same div.
4041
for cat in categories:
41-
id_ = int(cat.attributes['data-id'])
42-
location = global_cat.css(f'button[data-id="{id_}"]')
43-
location = location[0].text(strip=True) if location else None
42+
id_ = int(cast(str, cat.attributes['data-id']))
43+
locations = global_cat.css(f'button[data-id="{id_}"]')
44+
location = locations[0].text(strip=True) if locations else None
4445

4546
result.append(
4647
Category(
47-
raw_source=global_cat.html,
48+
raw_source=global_cat.html or '',
4849
id=id_,
4950
name=cat.css('a')[0].text(strip=True),
5051
location=location,
@@ -59,12 +60,13 @@ def _parse_subcategories(
5960
result = []
6061
div = global_cat.css(f'ul.list-inline[data-id="{data_id}"]')[0]
6162
for link in div.css('a'):
63+
url: str = link.attributes['href'] # type: ignore[assignment] # always has href
6264
result.append(
6365
Subcategory(
64-
raw_source=link.html,
65-
id=int(link.attributes['href'].split('/')[-2]),
66+
raw_source=link.html or '',
67+
id=int(url.split('/')[-2]),
6668
name=link.text(strip=True),
67-
type=SubcategoryType.get_by_url(link.attributes['href']),
69+
type=SubcategoryType.get_by_url(url),
6870
offers_amount=None,
6971
)
7072
)

funpayparsers/parsers/chat_parser.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,22 @@ def _parse(self) -> Chat:
5858
interlocutor, notifications, banned = self._parse_chat_header(chat_div)
5959

6060
chat_id = (
61-
int(chat_div.attributes['data-id']) if chat_div.attributes.get('data-id') else None
61+
int(cast(str, chat_div.attributes['data-id']))
62+
if chat_div.attributes.get('data-id')
63+
else None
6264
)
63-
chat_name = chat_div.attributes.get('data-name')
65+
66+
chat_name: str = cast(str, chat_div.attributes.get('data-name'))
6467

6568
messages_div = chat_div.css('div.chat-message-list')[0]
6669
history = MessagesParser(
67-
raw_source=messages_div.html,
70+
raw_source=messages_div.html or '',
6871
options=self.options.messages_parsing_options,
6972
context={'chat_id': chat_id, 'chat_name': chat_name},
7073
).parse()
7174

7275
return Chat(
73-
raw_source=chat_div.html,
76+
raw_source=chat_div.html or '',
7477
id=chat_id,
7578
name=chat_name,
7679
interlocutor=interlocutor,
@@ -100,9 +103,9 @@ def _parse_chat_header(
100103
btn_div = btn_divs[0]
101104

102105
notifications, banned = False, False
103-
if 'btn-success' in btn_div.attributes['class']: # type: ignore
106+
if 'btn-success' in btn_div.attributes['class']: # type: ignore[operator]
104107
notifications, banned = True, False
105-
elif 'btn-danger' in btn_div.attributes['class']: # type: ignore
108+
elif 'btn-danger' in btn_div.attributes['class']: # type: ignore[operator]
106109
notifications, banned = False, True
107110

108111
return interlocutor, notifications, banned

funpayparsers/parsers/money_value_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def _parse_order_preview_type(self) -> MoneyValue:
8181
val = self.tree.css_first('div.tc-price')
8282
return parse_money_value_string(
8383
val.text().strip(),
84-
raw_source=val.html,
84+
raw_source=val.html or '',
8585
raise_on_error=True,
8686
)
8787

funpayparsers/parsers/offer_previews_parser.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from selectolax.lexbor import LexborNode
1111

1212
from funpayparsers.parsers.base import ParsingOptions, FunPayHTMLObjectParser
13+
from funpayparsers.types.common import UserPreview
1314
from funpayparsers.types.offers import OfferSeller, OfferPreview
1415
from funpayparsers.parsers.utils import extract_css_url
1516
from funpayparsers.parsers.money_value_parser import (
@@ -57,13 +58,13 @@ def _parse(self) -> list[OfferPreview]:
5758
# cz there are specific fields in OfferPreview class for them.
5859
skip_match_data = ['user', 'online', 'auto']
5960

60-
processed_users = {}
61+
processed_users: dict[int, UserPreview] = {}
6162

6263
for offer_div in self.tree.css('a.tc-item'):
6364
offer_id_str = offer_div.attributes['href'].split('id=')[1]
64-
desc = offer_div.css('div.tc-desc-text')
65+
desc_divs = offer_div.css('div.tc-desc-text')
6566
# currency offers don't have description.
66-
desc = desc[0].text(strip=True) if desc else None
67+
desc = desc_divs[0].text(strip=True) if desc_divs else None
6768

6869
# Currency offers have 'data-s' attribute in tc-amount div,
6970
# where amount is stored.
@@ -83,7 +84,7 @@ def _parse(self) -> list[OfferPreview]:
8384

8485
price_div = offer_div.css('div.tc-price')[0]
8586
price = MoneyValueParser(
86-
price_div.html,
87+
price_div.html or '',
8788
options=self.options.money_value_parsing_options,
8889
parsing_mode=MoneyValueParsingMode.FROM_OFFER_PREVIEW,
8990
parse_value_from_attribute=(
@@ -111,7 +112,7 @@ def _parse(self) -> list[OfferPreview]:
111112

112113
result.append(
113114
OfferPreview(
114-
raw_source=offer_div.html,
115+
raw_source=offer_div.html or '',
115116
id=int(offer_id_str) if offer_id_str.isnumeric() else offer_id_str,
116117
auto_delivery=bool(offer_div.attributes.get('data-auto')),
117118
is_pinned=bool(offer_div.attributes.get('data-user')),

funpayparsers/parsers/private_chat_info_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def _parse(self) -> PrivateChatInfo:
4343
blocks = info_div.css('div.param-item:not(.hidden)')
4444

4545
result = PrivateChatInfo(
46-
raw_source=info_div.html,
46+
raw_source=info_div.html or '',
4747
registration_date_text=(
4848
blocks[0].text(separator='\n', strip=True).strip().split('\n')[-2]
4949
),
@@ -55,7 +55,7 @@ def _parse(self) -> PrivateChatInfo:
5555
for div in blocks:
5656
if div.attributes.get('data-type') == 'c-p-u':
5757
cpu = CurrentlyViewingOfferInfoParser(
58-
raw_source=div.html,
58+
raw_source=div.html or '',
5959
options=self.options.cpu_parsing_options,
6060
).parse()
6161
result.currently_viewing_offer = cpu

funpayparsers/parsers/transaction_previews_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def _parse(self) -> TransactionPreviewsBatch:
4747
result = []
4848
for i in self.tree.css('div.tc-item'):
4949
value = MoneyValueParser(
50-
raw_source=i.css('div.tc-price')[0].html,
50+
raw_source=i.css('div.tc-price')[0].html or '',
5151
options=self.options.money_value_parsing_options,
5252
parsing_mode=MoneyValueParsingMode.FROM_TRANSACTION_PREVIEW,
5353
).parse()

funpayparsers/parsers/updates_parser.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
__all__ = ('UpdatesParser', 'UpdatesParsingOptions')
55

6+
import json
7+
from typing import Any, cast
68
from dataclasses import dataclass
79

810
from funpayparsers.types.enums import UpdateType
911
from funpayparsers.parsers.base import ParsingOptions, FunPayJSONObjectParser
12+
from funpayparsers.types.common import CurrentlyViewingOfferInfo
1013
from funpayparsers.types.updates import (
1114
ChatNode,
1215
NodeInfo,
@@ -16,7 +19,6 @@
1619
ChatBookmarks,
1720
ActionResponse,
1821
OrdersCounters,
19-
CurrentlyViewingOfferInfo,
2022
)
2123
from funpayparsers.parsers.cpu_parser import (
2224
CurrentlyViewingOfferInfoParser,
@@ -82,44 +84,43 @@ def _parse(self) -> UpdatesPack:
8284
response=None,
8385
)
8486

85-
action_response = self.data.get('response')
87+
action_response = self.data.get('response') # type: ignore[union-attr] # raise if not dict
8688
if action_response:
8789
updates_obj.response = self._parse_action_response(action_response)
8890

89-
objects = self.data.get('objects')
91+
objects = self.data.get('objects') # type: ignore[union-attr] # raise if not dict
9092
if not objects:
9193
return updates_obj
9294

93-
unknown_objects = []
94-
nodes = {}
9595
for obj in objects:
9696
result = self._parse_update(obj)
9797
if result is None:
98-
unknown_objects.append(obj)
98+
updates_obj.unknown_objects.append(obj) # type: ignore[union-attr]
9999
elif result.type is UpdateType.CHAT_NODE:
100-
updates_obj.nodes.append(result)
100+
updates_obj.nodes.append(result) # type: ignore[union-attr]
101101
else:
102102
setattr(updates_obj, self.__update_fields__[result.type], result)
103103

104-
updates_obj.unknown_objects = unknown_objects or updates_obj.unknown_objects
105-
updates_obj.nodes = nodes or updates_obj.nodes
104+
updates_obj.nodes = updates_obj.nodes or None
105+
updates_obj.unknown_objects = updates_obj.unknown_objects or None
106+
106107
return updates_obj
107108

108-
def _parse_orders_counters(self, obj: dict) -> OrdersCounters:
109+
def _parse_orders_counters(self, obj: dict[str, Any]) -> OrdersCounters:
109110
return OrdersCounters(
110-
raw_source=str(obj),
111-
purchases=int(obj.get('buyer')) if obj.get('seller') else 0,
112-
sales=int(obj.get('seller')) if obj.get('seller') else 0,
111+
raw_source=json.dumps(obj, ensure_ascii=False),
112+
purchases=int(cast(str, obj.get('buyer'))) if obj.get('seller') else 0,
113+
sales=int(cast(str, obj.get('seller'))) if obj.get('seller') else 0,
113114
)
114115

115-
def _parse_chat_counter(self, obj: dict) -> ChatCounter:
116+
def _parse_chat_counter(self, obj: dict[str, Any]) -> ChatCounter:
116117
return ChatCounter(
117118
raw_source=str(obj),
118119
counter=int(obj['counter']),
119120
message=int(obj['message']),
120121
)
121122

122-
def _parse_chat_bookmarks(self, obj: dict) -> ChatBookmarks:
123+
def _parse_chat_bookmarks(self, obj: dict[str, Any]) -> ChatBookmarks:
123124
return ChatBookmarks(
124125
raw_source=str(obj),
125126
counter=int(obj['counter']),
@@ -131,14 +132,14 @@ def _parse_chat_bookmarks(self, obj: dict) -> ChatBookmarks:
131132
).parse(),
132133
)
133134

134-
def _parse_cpu(self, obj: dict) -> CurrentlyViewingOfferInfo:
135+
def _parse_cpu(self, obj: dict[str, Any]) -> CurrentlyViewingOfferInfo:
135136
html_ = obj['html']['desktop']
136137
return CurrentlyViewingOfferInfoParser(
137138
html_,
138139
options=self.options.cpu_parsing_options,
139140
).parse()
140141

141-
def _parse_node(self, obj: dict) -> ChatNode:
142+
def _parse_node(self, obj: dict[str, Any]) -> ChatNode:
142143
node_obj = obj['node']
143144
node_info = NodeInfo(
144145
raw_source=str(node_obj),
@@ -160,14 +161,14 @@ def _parse_node(self, obj: dict) -> ChatNode:
160161
has_history=obj['hasHistory'],
161162
)
162163

163-
def _parse_action_response(self, obj: dict) -> ActionResponse:
164+
def _parse_action_response(self, obj: dict[str, Any]) -> ActionResponse:
164165
return ActionResponse(
165166
raw_source=str(obj),
166167
error=obj.get('error'),
167168
)
168169

169-
def _parse_update(self, update_dict: dict) -> UpdateObject | None:
170-
update_type = UpdateType.get_by_type_str(update_dict.get('type'))
170+
def _parse_update(self, update_dict: dict[str, Any]) -> UpdateObject[Any] | None:
171+
update_type = UpdateType.get_by_type_str(cast(str, update_dict.get('type')))
171172
if update_type not in self.__parsing_methods__:
172173
return None
173174

0 commit comments

Comments
 (0)