Skip to content

Commit ac0eb49

Browse files
committed
feat: Add requestslimit_timeout class init variable
1 parent 6154556 commit ac0eb49

File tree

3 files changed

+41
-66
lines changed

3 files changed

+41
-66
lines changed

readme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ wallhaven_api = wallhavenapi.WallhavenApiV1(api_key="some_api_key")
4040

4141
## Methods
4242

43+
### WallhavenApiV1
44+
45+
* api_key {String} - your **[Wallhaven](https://wallhaven.cc)** [api key](https://wallhaven.cc/settings/account)
46+
* verify_connection {Bool} - check ssl cert
47+
* base_url {String} - **[Wallhaven](https://wallhaven.cc)** base api url
48+
* timeout {Tuple(Int, Int)} - http request timeout
49+
* requestslimit_timeout {Tuple(Int, Int)} - try to handle 429 http error. The first Int - how many times to do request, the second - delay (in seconds) between requests.
50+
4351
### WallhavenApiV1.search - Accessing Wallpaper information
4452

4553
* q {String} - query (used to filter by user, tags, ids and [so on...](https://wallhaven.cc/help/api#search))

tests.py

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,50 +5,33 @@
55
import time
66

77

8-
def request_limit_decorator(test_method):
9-
def wrapper(self, *args, **kwargs):
10-
for _ in range(20):
11-
try:
12-
result = test_method(self, *args, **kwargs)
13-
break
14-
except RequestsLimitError:
15-
time.sleep(5)
16-
else:
17-
raise RequestsLimitError()
18-
19-
return result
20-
return wrapper
21-
22-
238
class TestWallhavenApiV1(unittest.TestCase):
249
@classmethod
2510
def setUpClass(self):
2611
self.wallhaven_api = WallhavenApiV1(api_key=os.getenv('APIKEY', None), verify_connection=False,
27-
base_url="http://wallhaven.cc/api/v1")
12+
base_url="http://wallhaven.cc/api/v1",
13+
requestslimit_timeout=(15, 5))
2814

2915
def test_search(self):
3016
search_data = self.wallhaven_api.search()
3117

3218
self.assertIn("data", search_data)
3319
self.assertIn("meta", search_data)
3420

35-
@request_limit_decorator
3621
def test_search_categories(self):
3722
for category in list(Category):
3823
search_data = self.wallhaven_api.search(categories=category)
3924

4025
for wallpaper_data in search_data["data"]:
4126
self.assertEqual(category.value, wallpaper_data["category"])
4227

43-
@request_limit_decorator
4428
def test_search_purities(self):
4529
for purity in list(Purity):
4630
search_data = self.wallhaven_api.search(purities=purity)
4731

4832
for wallpaper_data in search_data["data"]:
4933
self.assertEqual(purity.value, wallpaper_data["purity"])
5034

51-
@request_limit_decorator
5235
def test_search_sorting(self):
5336
for sorting_method in list(Sorting):
5437
search_data = self.wallhaven_api.search(sorting=sorting_method)
@@ -66,15 +49,12 @@ def parse_datetime(datetime_string):
6649
self.assertGreaterEqual(datetime_1, datetime_2) \
6750
if order == Order.desc else self.assertLessEqual(datetime_1, datetime_2)
6851

69-
@request_limit_decorator
7052
def test_search_sorting_dated_added_asc(self):
7153
self.search_sorting_dated_added(Order.asc)
7254

73-
@request_limit_decorator
7455
def test_search_sorting_dated_added_desc(self):
7556
self.search_sorting_dated_added(Order.desc)
7657

77-
@request_limit_decorator
7858
def search_sorting_views(self, order):
7959
search_data = self.wallhaven_api.search(sorting=Sorting.views, order=order)
8060
for i in range(len(search_data["data"]) - 1):
@@ -83,12 +63,10 @@ def search_sorting_views(self, order):
8363
self.assertGreaterEqual(views_1, views_2) \
8464
if order == Order.desc else self.assertLessEqual(views_1, views_2)
8565

86-
@request_limit_decorator
8766
@unittest.skip("May content unsorted results. Need help")
8867
def test_search_sorting_views_asc(self):
8968
self.search_sorting_views(Order.asc)
9069

91-
@request_limit_decorator
9270
@unittest.skip("May content unsorted results. Need help")
9371
def test_search_sorting_views_desc(self):
9472
self.search_sorting_views(Order.desc)
@@ -101,17 +79,14 @@ def search_sorting_favorites(self, order):
10179
self.assertGreaterEqual(favorites_1, favorites_2) \
10280
if order == Order.desc else self.assertLessEqual(favorites_1, favorites_2)
10381

104-
@request_limit_decorator
10582
@unittest.skip("May content unsorted results. Need help")
10683
def test_search_sorting_favorites_asc(self):
10784
self.search_sorting_favorites(Order.asc)
10885

109-
@request_limit_decorator
11086
@unittest.skip("May content unsorted results. Need help")
11187
def test_search_sorting_favorites_desc(self):
11288
self.search_sorting_favorites(Order.desc)
11389

114-
@request_limit_decorator
11590
@unittest.skip("May content unsorted results. Need help")
11691
def test_search_top_range(self):
11792
for top_range in list(TopRange):
@@ -132,35 +107,30 @@ def test_search_top_range(self):
132107

133108
self.assertGreaterEqual(created_at, datetime.datetime.now() - timedelta)
134109

135-
@request_limit_decorator
136110
def test_search_atleast(self):
137111
search_data = self.wallhaven_api.search(atleast=(1920, 1080))
138112
for wallpaper in search_data["data"]:
139113
self.assertGreaterEqual(int(wallpaper["dimension_x"]), 1920)
140114
self.assertGreaterEqual(int(wallpaper["dimension_y"]), 1080)
141115

142-
@request_limit_decorator
143116
def test_search_resolutions(self):
144117
search_data = self.wallhaven_api.search(resolutions=(1920, 1080))
145118
for wallpaper in search_data["data"]:
146119
self.assertEqual(int(wallpaper["dimension_x"]), 1920)
147120
self.assertEqual(int(wallpaper["dimension_y"]), 1080)
148121

149-
@request_limit_decorator
150122
def test_search_ratios(self):
151123
search_data = self.wallhaven_api.search(ratios=(16, 10))
152124
for wallpaper in search_data["data"]:
153125
self.assertEqual(float(wallpaper["ratio"]), 1.6)
154126

155-
@request_limit_decorator
156127
def test_search_colors(self):
157128
for color in list(Color):
158129
search_data = self.wallhaven_api.search(colors=color)
159130
for wallpaper in search_data["data"]:
160131
self.assertIn("colors", wallpaper)
161132
self.assertIn("#{}".format(color.value), wallpaper["colors"])
162133

163-
@request_limit_decorator
164134
def test_search_page(self):
165135
search_data = self.wallhaven_api.search()
166136

@@ -174,7 +144,6 @@ def test_search_page(self):
174144
self.assertIn("current_page", search_data["meta"])
175145
self.assertEqual(2, int(search_data["meta"]["current_page"]))
176146

177-
@request_limit_decorator
178147
def test_wallpaper(self):
179148
search_data = self.wallhaven_api.search()
180149

@@ -187,7 +156,6 @@ def test_wallpaper(self):
187156
wallpaper = self.wallhaven_api.wallpaper(search_data["data"][0]["id"])
188157
self.assertIn("data", wallpaper)
189158

190-
@request_limit_decorator
191159
def test_tag(self):
192160
search_data = self.wallhaven_api.search()
193161

@@ -209,7 +177,6 @@ def test_tag(self):
209177

210178
break
211179

212-
@request_limit_decorator
213180
def test_search_query_uploader(self):
214181
search_data = self.wallhaven_api.search()
215182

@@ -230,7 +197,6 @@ def test_search_query_uploader(self):
230197

231198
self.assertGreater(len(search_data["data"]), 0)
232199

233-
@request_limit_decorator
234200
def test_search_query_id(self):
235201
search_data = self.wallhaven_api.search()
236202

@@ -252,7 +218,6 @@ def test_search_query_id(self):
252218
self.assertGreater(len(search_data["data"]), 0)
253219
break
254220

255-
@request_limit_decorator
256221
def test_search_query_like(self):
257222
search_data = self.wallhaven_api.search()
258223

@@ -264,7 +229,6 @@ def test_search_query_like(self):
264229
self.assertIn("data", search_data)
265230
self.assertIn("meta", search_data)
266231

267-
@request_limit_decorator
268232
def test_search_query_type(self):
269233
for image_type in Type:
270234
search_data = self.wallhaven_api.search(q="type:{}".format(image_type.value))
@@ -280,13 +244,11 @@ def test_search_query_type(self):
280244
else:
281245
self.assertTrue(str(wallpaper["file_type"]).endswith(image_type.value))
282246

283-
@request_limit_decorator
284247
def test_settings(self):
285248
result = self.wallhaven_api.settings()
286249

287250
assert result is None if self.wallhaven_api.api_key is None else result is not None
288251

289-
@request_limit_decorator
290252
def test_collections(self):
291253
# Just a random user, who has a collection with wallpapers
292254
result = self.wallhaven_api.collections("ThorRagnarok")
@@ -297,7 +259,6 @@ def test_collections(self):
297259

298260
return result
299261

300-
@request_limit_decorator
301262
def test_collection_wallpapers(self, page=None):
302263
collections = self.test_collections()
303264

@@ -308,11 +269,9 @@ def test_collection_wallpapers(self, page=None):
308269
assert "meta" in collections_wallpapers
309270
assert len(collections_wallpapers["data"])
310271

311-
@request_limit_decorator
312272
def test_collection_wallpapers_page(self):
313273
self.test_collection_wallpapers(2)
314274

315-
@request_limit_decorator
316275
def test_my_collections(self):
317276
result = self.wallhaven_api.my_collections()
318277

wallhavenapi.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from enum import Enum
55
import random
66
import string
7+
import time
78

89

910
class Purity(Enum):
@@ -112,43 +113,50 @@ def __init__(self, wallpaper_id):
112113

113114
class WallhavenApiV1:
114115
def __init__(self, api_key=None, verify_connection=True, base_url="https://wallhaven.cc/api/v1",
115-
timeout=(2,5)):
116+
timeout=(2,5), requestslimit_timeout=None):
116117
self.verify_connection = verify_connection
117118
self.api_key = api_key
118119
self.base_url = base_url
119120
self.timeout = timeout
121+
self.requestslimit_timeout = requestslimit_timeout
120122

121123
def _request(self, to_json, **kwargs):
122-
if self.api_key is not None:
123-
if "params" in kwargs:
124-
kwargs["params"]["apikey"] = self.api_key
125-
else:
126-
kwargs["params"] = {"apikey": self.api_key}
124+
for i in range(self.requestslimit_timeout[0] if self.requestslimit_timeout is not None else 1):
125+
if self.api_key is not None:
126+
if "params" in kwargs:
127+
kwargs["params"]["apikey"] = self.api_key
128+
else:
129+
kwargs["params"] = {"apikey": self.api_key}
127130

128-
if "timeout" not in kwargs:
129-
kwargs["timeout"] = self.timeout
131+
if "timeout" not in kwargs:
132+
kwargs["timeout"] = self.timeout
130133

131-
if "verify" not in kwargs:
132-
kwargs["verify"] = self.verify_connection
134+
if "verify" not in kwargs:
135+
kwargs["verify"] = self.verify_connection
133136

134-
response = requests.request(**kwargs)
137+
response = requests.request(**kwargs)
135138

136-
if response.status_code == 429:
137-
raise RequestsLimitError
139+
if response.status_code == 429:
140+
if self.requestslimit_timeout is None\
141+
or i == (self.requestslimit_timeout[0] - 1) if self.requestslimit_timeout is not None else 0:
142+
raise RequestsLimitError
143+
144+
time.sleep(self.requestslimit_timeout[1])
145+
continue
138146

139-
if response.status_code == 401:
140-
raise ApiKeyError
147+
if response.status_code == 401:
148+
raise ApiKeyError
141149

142-
if response.status_code != 200:
143-
raise UnhandledException
144-
145-
if to_json:
146-
try:
147-
return response.json()
148-
except:
150+
if response.status_code != 200:
149151
raise UnhandledException
150152

151-
return response
153+
if to_json:
154+
try:
155+
return response.json()
156+
except:
157+
raise UnhandledException
158+
159+
return response
152160

153161
def _url_format(self, *args):
154162
url = self.base_url

0 commit comments

Comments
 (0)