Skip to content

Commit a9e425c

Browse files
committed
Refactor VkRequestsPool:
- Make VkRequestsPool.method_one_param separated function: vk_request_one_param_pool - Use actual error dict for RequestResult, instead of bool
1 parent e165e5f commit a9e425c

4 files changed

Lines changed: 120 additions & 119 deletions

File tree

examples/requests_pool.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def main():
1313
vk_session = vk_api.VkApi(login, password)
1414

1515
try:
16-
vk_session.auth()
16+
vk_session.auth(token_only=True)
1717
except vk_api.AuthError as error_msg:
1818
print(error_msg)
1919
return
@@ -35,6 +35,17 @@ def main():
3535
# False - поэтому нельзя обратиться к результату
3636
print(request_with_error.ok)
3737

38+
# Получить ошибку
39+
print(request_with_error.error)
40+
41+
try:
42+
""" Если запрос был завершен с ошибкой, то при обращении к результату
43+
будет выбрасываться исключение
44+
"""
45+
_ = request_with_error.result
46+
except vk_api.VkRequestsPoolException as e:
47+
print('Error:', e)
48+
3849
""" Пример получения друзей у нескольких пользователей за один запрос
3950
"""
4051

@@ -52,25 +63,28 @@ def main():
5263

5364
print(friends)
5465

55-
""" Следующий пример - оптимизированная версия предыдущего
66+
""" Следующий пример - более простая версия предыдущего
5667
5768
В friends будет записан тот же самый результат, что и в прошлом примере.
58-
method_one_param можно использовать, когда запрос идет к одному методу,
59-
и когда изменяется только один параметр. В данном случае это 'user_id'
69+
vk_request_one_param_pool можно использовать, когда запрос идет к
70+
одному методу и когда изменяется только один параметр. В данном случае
71+
это 'user_id'.
6072
61-
Плюс не нужно вызывать .result для каждого ключа
73+
Кроме того не нужно получать .result для каждого ключа.
6274
"""
63-
with vk_api.VkRequestsPool(vk_session) as pool:
64-
friends = pool.method_one_param(
65-
'friends.get', # Метод
66-
key='user_id', # Изменяющийся параметр
67-
values=[1, 183433824],
75+
friends, errors = vk_api.vk_request_one_param_pool(
76+
vk_session,
77+
'friends.get', # Метод
78+
key='user_id', # Изменяющийся параметр
79+
values=[1, 3, 183433824],
6880

69-
# Параметры, которые будут в каждом запросе
70-
default_values={'fields': 'photo'}
71-
)
81+
# Параметры, которые будут в каждом запросе
82+
default_values={'fields': 'photo'}
83+
)
84+
85+
print(friends)
86+
print(errors)
7287

73-
print(friends.result)
7488

7589
if __name__ == '__main__':
7690
main()

vk_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from .enums import *
33
from .exceptions import *
4-
from .requests_pool import VkRequestsPool
4+
from .requests_pool import VkRequestsPool, vk_request_one_param_pool
55
from .tools import VkTools
66
from .upload import VkUpload
77
from .vk_api import VkApi

vk_api/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,9 @@ class VkAudioUrlDecodeError(VkAudioException):
159159

160160
class VkToolsException(VkApiError):
161161
pass
162+
163+
164+
class VkRequestsPoolException(Exception):
165+
def __init__(self, error, *args, **kwargs):
166+
self.error = error
167+
super(VkRequestsPoolException, self).__init__(*args, **kwargs)

vk_api/requests_pool.py

Lines changed: 85 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,14 @@
1010
import sys
1111
from collections import namedtuple
1212

13-
from .utils import sjson_dumps
13+
from .exceptions import VkRequestsPoolException
1414
from .execute import VkFunction
15+
from .utils import sjson_dumps
1516

1617
if sys.version_info.major == 2:
1718
range = xrange
1819

1920

20-
class VkRequestsPoolException(Exception):
21-
pass
22-
23-
2421
PoolRequest = namedtuple('PoolRequest', ['method', 'values', 'result'])
2522

2623

@@ -51,7 +48,13 @@ def result(self):
5148
raise RuntimeError('Result is not available in `with` context')
5249

5350
if self._error:
54-
raise VkRequestsPoolException('Got error while executing request')
51+
raise VkRequestsPoolException(
52+
self._error,
53+
'Got error while executing request: [{}] {}'.format(
54+
self.error['error_code'],
55+
self.error['error_msg']
56+
)
57+
)
5558

5659
return self._result
5760

@@ -74,28 +77,20 @@ class VkRequestsPool(object):
7477
Служит как менеджер контекста: запросы к API добавляются в
7578
открытый пул, и выполняются при его закрытии.
7679
77-
:param vk: Объект :class:`VkApi`
80+
:param vk_session: Объект :class:`VkApi`
7881
"""
7982

80-
__slots__ = ('vk', 'pool', 'one_param', 'execute_errors')
83+
__slots__ = ('vk_session', 'pool')
8184

82-
def __init__(self, vk):
83-
self.vk = vk
85+
def __init__(self, vk_session):
86+
self.vk_session = vk_session
8487
self.pool = []
85-
self.one_param = {}
86-
self.execute_errors = []
8788

8889
def __enter__(self):
8990
return self
9091

9192
def __exit__(self, *args, **kwargs):
92-
if self.one_param:
93-
self.execute_one_param()
94-
else:
95-
self.execute()
96-
97-
def get_execute_errors(self):
98-
return self.execute_errors
93+
self.execute()
9994

10095
def method(self, method, values=None):
10196
"""
@@ -111,9 +106,6 @@ def method(self, method, values=None):
111106
:rtype: RequestResult
112107
"""
113108

114-
if self.one_param:
115-
raise RuntimeError('One param mode does not work with self.method')
116-
117109
if values is None:
118110
values = {}
119111

@@ -122,44 +114,6 @@ def method(self, method, values=None):
122114

123115
return result
124116

125-
def method_one_param(self, method, key, values, default_values=None):
126-
"""
127-
Использовать, если изменяется значение только одного параметра.
128-
Невозможно использовать вместе с :func:`method`.
129-
Возвращаемое значение будет содержать результат после закрытия пула.
130-
131-
:param method: метод
132-
:type method: str
133-
134-
:param default_values: одинаковые значения для запросов
135-
:type default_values: dict
136-
137-
:param key: ключ изменяющегося параметра
138-
:type key: str
139-
140-
:param values: список значений изменяющегося параметра (max: 25)
141-
:type values: list
142-
143-
:rtype: RequestResult
144-
"""
145-
146-
if not self.one_param and self.pool:
147-
raise RuntimeError('One param mode does not work with self.method')
148-
149-
if default_values is None:
150-
default_values = {}
151-
152-
self.one_param = {
153-
'method': method,
154-
'default': default_values,
155-
'key': key,
156-
'return': RequestResult()
157-
}
158-
159-
self.pool = values
160-
161-
return self.one_param['return']
162-
163117
def execute(self):
164118
for i in range(0, len(self.pool), 25):
165119
cur_pool = self.pool[i:i + 25]
@@ -169,45 +123,24 @@ def execute(self):
169123
if one_method:
170124
value_list = [i.values for i in cur_pool]
171125

172-
response_raw = vk_one_method(self.vk, one_method, value_list)
126+
response_raw = vk_one_method(
127+
self.vk_session, one_method, value_list
128+
)
173129
else:
174-
response_raw = vk_many_methods(self.vk, cur_pool)
175-
176-
response = response_raw['response']
177-
response_errors = response_raw.get('execute_errors')
178-
179-
if response_errors:
180-
self.execute_errors += response_errors[:-1]
181-
182-
for x, response in enumerate(response):
183-
if response is not False:
184-
cur_pool[x].result.result = response
185-
else:
186-
cur_pool[x].result.error = True
187-
188-
def execute_one_param(self):
189-
result = {}
190-
191-
method = self.one_param['method']
192-
default = self.one_param['default']
193-
key = self.one_param['key']
194-
195-
for i in range(0, len(self.pool), 25):
196-
cur_pool = self.pool[i:i + 25]
197-
198-
response_raw = vk_one_param(self.vk, method, cur_pool, default, key)
130+
response_raw = vk_many_methods(self.vk_session, cur_pool)
199131

200132
response = response_raw['response']
201-
response_errors = response_raw.get('execute_errors')
133+
response_errors = response_raw.get('execute_errors', [])
202134

203-
if response_errors:
204-
self.execute_errors += response_errors[:-1]
135+
response_errors_iter = iter(response_errors)
205136

206-
for x, r in enumerate(response):
207-
if r is not False:
208-
result[cur_pool[x]] = r
137+
for x, current_response in enumerate(response):
138+
current_result = cur_pool[x].result
209139

210-
self.one_param['return'].result = result
140+
if current_response is not False:
141+
current_result.result = current_response
142+
else:
143+
current_result.error = next(response_errors_iter)
211144

212145

213146
def check_one_method(pool):
@@ -242,6 +175,65 @@ def check_one_method(pool):
242175
''')
243176

244177

178+
def vk_many_methods(vk_session, pool):
179+
requests = ','.join(
180+
'API.{}({})'.format(i.method, sjson_dumps(i.values))
181+
for i in pool
182+
)
183+
184+
code = 'return [{}];'.format(requests)
185+
186+
return vk_session.method('execute', {'code': code}, raw=True)
187+
188+
189+
def vk_request_one_param_pool(vk_session, method, key, values,
190+
default_values=None):
191+
"""
192+
Использовать, если изменяется значение только одного параметра.
193+
Невозможно использовать вместе с :func:`method`.
194+
Возвращаемое значение будет содержать результат после закрытия пула.
195+
196+
:param vk_session: метод
197+
:type vk_session: vk_api.VkAPi
198+
199+
:param method: метод
200+
:type method: str
201+
202+
:param default_values: одинаковые значения для запросов
203+
:type default_values: dict
204+
205+
:param key: ключ изменяющегося параметра
206+
:type key: str
207+
208+
:param values: список значений изменяющегося параметра (max: 25)
209+
:type values: list
210+
211+
:rtype: (dict, dict)
212+
"""
213+
214+
result = {}
215+
errors = {}
216+
217+
for i in range(0, len(values), 25):
218+
current_values = values[i:i + 25]
219+
220+
response_raw = vk_one_param(
221+
vk_session, method, current_values, default_values, key
222+
)
223+
224+
response = response_raw['response']
225+
response_errors = response_raw.get('execute_errors', [])
226+
response_errors_iter = iter(response_errors)
227+
228+
for x, r in enumerate(response):
229+
if r is not False:
230+
result[current_values[x]] = r
231+
else:
232+
errors[current_values[x]] = next(response_errors_iter)
233+
234+
return result, errors
235+
236+
245237
vk_one_param = VkFunction(
246238
args=('method', 'values', 'default_values', 'key'),
247239
clean_args=('method', 'key'),
@@ -262,14 +254,3 @@ def check_one_method(pool):
262254
263255
return result;
264256
''')
265-
266-
267-
def vk_many_methods(vk_session, pool):
268-
requests = ','.join(
269-
'API.{}({})'.format(i.method, sjson_dumps(i.values))
270-
for i in pool
271-
)
272-
273-
code = 'return [{}];'.format(requests)
274-
275-
return vk_session.method('execute', {'code': code}, raw=True)

0 commit comments

Comments
 (0)