esuls 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
esuls/db_cli.py CHANGED
@@ -178,6 +178,8 @@ class AsyncDB(Generic[SchemaType]):
178
178
  """Fast value serialization with type-based optimization."""
179
179
  if value is None or isinstance(value, (int, float, bool, str)):
180
180
  return value
181
+ if isinstance(value, bytes):
182
+ return value
181
183
  if isinstance(value, datetime):
182
184
  return value.isoformat()
183
185
  if isinstance(value, enum.Enum):
@@ -193,6 +195,18 @@ class AsyncDB(Generic[SchemaType]):
193
195
 
194
196
  field_type = self._type_hints.get(field_name)
195
197
 
198
+ # Handle bytes fields - keep as bytes
199
+ if field_type == bytes:
200
+ if isinstance(value, bytes):
201
+ return value
202
+ # If somehow stored as string, convert back
203
+ if isinstance(value, str):
204
+ import ast
205
+ try:
206
+ return ast.literal_eval(value)
207
+ except:
208
+ return value.encode('utf-8')
209
+
196
210
  # Handle string fields - ensure phone numbers are strings
197
211
  if field_type is str or (hasattr(field_type, '__origin__') and field_type.__origin__ is Union and str in getattr(field_type, '__args__', ())):
198
212
  return str(value)
esuls/request_cli.py CHANGED
@@ -178,7 +178,7 @@ class AsyncRequest(AsyncContextManager['AsyncRequest']):
178
178
  if response.status_code not in range(200, 300):
179
179
  logger.warning(
180
180
  f"Request: {response.status_code}\n"
181
- f"Attempt {attempt}/{max_attempt}\n"
181
+ f"Attempt {attempt + 1}/{max_attempt}\n"
182
182
  f"Url: {url}\n"
183
183
  f"Params: {params}\n"
184
184
  f"Response: {response.text[:1000]}\n"
@@ -194,7 +194,13 @@ class AsyncRequest(AsyncContextManager['AsyncRequest']):
194
194
  if attempt + 1 == max_attempt:
195
195
  return response if force_response else None
196
196
 
197
- await asyncio.sleep(exception_sleep)
197
+ # Exponential backoff for 429 (rate limit)
198
+ if response.status_code == 429:
199
+ backoff = min(120, exception_sleep * (2 ** attempt))
200
+ logger.info(f"Rate limited (429), backing off for {backoff:.1f}s")
201
+ await asyncio.sleep(backoff)
202
+ else:
203
+ await asyncio.sleep(exception_sleep)
198
204
  continue
199
205
 
200
206
  # Validate JSON response
@@ -297,7 +303,7 @@ async def make_request(
297
303
  if response.status_code not in range(200, 300):
298
304
  logger.warning(
299
305
  f"Request: {response.status_code}\n"
300
- f"Attempt {attempt}/{max_attempt}\n"
306
+ f"Attempt {attempt + 1}/{max_attempt}\n"
301
307
  f"Url: {url}\n"
302
308
  f"Params: {params}\n"
303
309
  f"Response: {response.text[:1000]}\n"
@@ -312,7 +318,13 @@ async def make_request(
312
318
  if attempt + 1 == max_attempt:
313
319
  return response if force_response else None
314
320
 
315
- await asyncio.sleep(exception_sleep)
321
+ # Exponential backoff for 429 (rate limit)
322
+ if response.status_code == 429:
323
+ backoff = min(120, exception_sleep * (2 ** attempt))
324
+ logger.info(f"Rate limited (429), backing off for {backoff:.1f}s")
325
+ await asyncio.sleep(backoff)
326
+ else:
327
+ await asyncio.sleep(exception_sleep)
316
328
  continue
317
329
 
318
330
  # Validate JSON response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esuls
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: Utility library for async database operations, HTTP requests, and parallel execution
5
5
  Author-email: IperGiove <ipergiove@gmail.com>
6
6
  License: MIT
@@ -0,0 +1,10 @@
1
+ esuls/__init__.py,sha256=dtZtmjZZ8jNspOd17BWsE9D9ofeg3vZF0vIpSgKaZqk,529
2
+ esuls/db_cli.py,sha256=F1XwkuzCc69ldnDv0-X4kl4VZ9zI6oJnqmQAOe2d8jE,17931
3
+ esuls/download_icon.py,sha256=w-bWbyPSbWvonzq43aDDtdxIvdKSa7OSyZ7LaN0uudg,3623
4
+ esuls/request_cli.py,sha256=wcHC7dMRyyRrLjl2EqKaGcgE_jD1tdBEqk2OhEmZWNc,14993
5
+ esuls/utils.py,sha256=R0peIanodvDrKYFWWdLZ9weIPAUZX787XIjZH40qNo0,677
6
+ esuls-0.1.7.dist-info/licenses/LICENSE,sha256=AY0N01ARt0kbKB7CkByYLqqNQU-yalb-rpv-eXITEWA,1066
7
+ esuls-0.1.7.dist-info/METADATA,sha256=p6p01nDh8vYdXCqwGdbvDRkNyI2YR-__iKiECOjjtq4,6994
8
+ esuls-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ esuls-0.1.7.dist-info/top_level.txt,sha256=WWBDHRhQ0DQLBZKD7Un8uFN93GvVQnP4WvJKkvbACVA,6
10
+ esuls-0.1.7.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- esuls/__init__.py,sha256=dtZtmjZZ8jNspOd17BWsE9D9ofeg3vZF0vIpSgKaZqk,529
2
- esuls/db_cli.py,sha256=-iKaSknraP9EDQHms-Jg8W9SfVof1_M5ycdKdkChD5Q,17452
3
- esuls/download_icon.py,sha256=w-bWbyPSbWvonzq43aDDtdxIvdKSa7OSyZ7LaN0uudg,3623
4
- esuls/request_cli.py,sha256=8wt2MQ4Y3J-vEVacizbbuHLSrENm41UhnnGGzi-DfDE,14277
5
- esuls/utils.py,sha256=R0peIanodvDrKYFWWdLZ9weIPAUZX787XIjZH40qNo0,677
6
- esuls-0.1.5.dist-info/licenses/LICENSE,sha256=AY0N01ARt0kbKB7CkByYLqqNQU-yalb-rpv-eXITEWA,1066
7
- esuls-0.1.5.dist-info/METADATA,sha256=XjKuMRd9BAeaXtIKB8K4HWV_7k-ijMgEAjImnZm3Qoc,6994
8
- esuls-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- esuls-0.1.5.dist-info/top_level.txt,sha256=WWBDHRhQ0DQLBZKD7Un8uFN93GvVQnP4WvJKkvbACVA,6
10
- esuls-0.1.5.dist-info/RECORD,,
File without changes