amochka 0.3.1__tar.gz → 0.3.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amochka
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Python library for working with amoCRM API with ETL capabilities
5
5
  Author-email: Timur <timurdt@gmail.com>
6
6
  License: MIT
@@ -26,7 +26,6 @@ Classifier: Topic :: Internet :: WWW/HTTP
26
26
  Requires-Python: >=3.6
27
27
  Description-Content-Type: text/markdown
28
28
  Requires-Dist: requests>=2.25.0
29
- Requires-Dist: ratelimit>=2.2.0
30
29
  Requires-Dist: psycopg2-binary>=2.9.0
31
30
  Requires-Dist: python-dotenv>=1.0.0
32
31
 
@@ -5,7 +5,7 @@ import requests
5
5
  import logging
6
6
  from datetime import datetime
7
7
  from typing import Iterator, List, Optional, Sequence, Union
8
- from ratelimit import limits, sleep_and_retry
8
+ # ratelimit больше не используется - rate limiting реализован вручную через self.rate_limit
9
9
 
10
10
  # Создаём базовый логгер
11
11
  logger = logging.getLogger(__name__)
@@ -15,7 +15,7 @@ if not logger.handlers:
15
15
  ch.setFormatter(formatter)
16
16
  logger.addHandler(ch)
17
17
 
18
- RATE_LIMIT = 7 # Максимум 7 запросов в секунду
18
+ DEFAULT_RATE_LIMIT = 7 # Максимум запросов в секунду по умолчанию
19
19
 
20
20
  class Deal(dict):
21
21
  """
@@ -262,12 +262,13 @@ class AmoCRMClient:
262
262
  либо полностью отключить логирование, установив disable_logging=True.
263
263
  """
264
264
  def __init__(
265
- self,
266
- base_url,
267
- token_file=None,
268
- cache_config=None,
269
- log_level=logging.INFO,
265
+ self,
266
+ base_url,
267
+ token_file=None,
268
+ cache_config=None,
269
+ log_level=logging.INFO,
270
270
  disable_logging=False,
271
+ rate_limit: Optional[int] = None,
271
272
  *,
272
273
  client_id: Optional[str] = None,
273
274
  client_secret: Optional[str] = None,
@@ -275,14 +276,17 @@ class AmoCRMClient:
275
276
  ):
276
277
  """
277
278
  Инициализирует клиента, задавая базовый URL, токен авторизации и настройки кэша для кастомных полей.
278
-
279
+
279
280
  :param base_url: Базовый URL API amoCRM.
280
281
  :param token_file: Файл, содержащий токен авторизации.
281
282
  :param cache_config: Конфигурация кэширования (объект CacheConfig или None для значений по умолчанию)
282
283
  :param log_level: Уровень логирования (например, logging.DEBUG, logging.INFO).
283
284
  :param disable_logging: Если True, логирование будет отключено.
285
+ :param rate_limit: Максимальное количество запросов в секунду (по умолчанию 7).
284
286
  """
285
287
  self.base_url = base_url.rstrip('/')
288
+ self.rate_limit = rate_limit if rate_limit is not None else DEFAULT_RATE_LIMIT
289
+ self._request_times: List[float] = [] # Для отслеживания времени запросов
286
290
  domain = self.base_url.split("//")[-1].split(".")[0]
287
291
  self.domain = domain
288
292
  self.token_file = token_file or os.path.join(os.path.expanduser('~'), '.amocrm_token.json')
@@ -378,8 +382,24 @@ class AmoCRMClient:
378
382
 
379
383
  raise Exception("Токен истёк или некорректен, и нет данных для refresh_token. Обновите токен.")
380
384
 
381
- @sleep_and_retry
382
- @limits(calls=RATE_LIMIT, period=1)
385
+ def _wait_for_rate_limit(self):
386
+ """Ожидает, если превышен лимит запросов в секунду."""
387
+ now = time.time()
388
+ # Удаляем запросы старше 1 секунды
389
+ self._request_times = [t for t in self._request_times if now - t < 1.0]
390
+
391
+ if len(self._request_times) >= self.rate_limit:
392
+ # Ждём до освобождения слота
393
+ sleep_time = 1.0 - (now - self._request_times[0])
394
+ if sleep_time > 0:
395
+ self.logger.debug(f"Rate limit: ожидание {sleep_time:.3f}с (лимит {self.rate_limit} req/s)")
396
+ time.sleep(sleep_time)
397
+ # Очищаем старые записи после ожидания
398
+ now = time.time()
399
+ self._request_times = [t for t in self._request_times if now - t < 1.0]
400
+
401
+ self._request_times.append(time.time())
402
+
383
403
  def _make_request(self, method, endpoint, params=None, data=None, timeout=10):
384
404
  """
385
405
  Выполняет HTTP-запрос к API amoCRM с учетом ограничения по скорости (rate limit).
@@ -392,6 +412,9 @@ class AmoCRMClient:
392
412
  :return: Ответ в формате JSON или None (если статус 204).
393
413
  :raises Exception: При получении кода ошибки, отличного от 200/204.
394
414
  """
415
+ # Ручной rate limiting
416
+ self._wait_for_rate_limit()
417
+
395
418
  url = f"{self.base_url}{endpoint}"
396
419
  headers = {
397
420
  "Authorization": f"Bearer {self.token}",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amochka
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Python library for working with amoCRM API with ETL capabilities
5
5
  Author-email: Timur <timurdt@gmail.com>
6
6
  License: MIT
@@ -26,7 +26,6 @@ Classifier: Topic :: Internet :: WWW/HTTP
26
26
  Requires-Python: >=3.6
27
27
  Description-Content-Type: text/markdown
28
28
  Requires-Dist: requests>=2.25.0
29
- Requires-Dist: ratelimit>=2.2.0
30
29
  Requires-Dist: psycopg2-binary>=2.9.0
31
30
  Requires-Dist: python-dotenv>=1.0.0
32
31
 
@@ -1,4 +1,3 @@
1
1
  requests>=2.25.0
2
- ratelimit>=2.2.0
3
2
  psycopg2-binary>=2.9.0
4
3
  python-dotenv>=1.0.0
@@ -107,6 +107,7 @@ class AmoCRMAccount:
107
107
  mybi_account_id: int # Внутренний account_id как в mybi.ru (для совместимости)
108
108
  pipeline_ids: Optional[List[int]] = None # None = все воронки
109
109
  cache_dir: Optional[Path] = None
110
+ rate_limit: int = 7 # Максимум запросов в секунду (по умолчанию 7)
110
111
 
111
112
  def __post_init__(self):
112
113
  if isinstance(self.token_path, str):
@@ -125,6 +126,7 @@ class AmoCRMAccount:
125
126
  mybi_account_id=int(d.get("mybi_account_id", 0)),
126
127
  pipeline_ids=d.get("pipeline_ids"),
127
128
  cache_dir=Path(d.get("cache_dir", ".cache")) if d.get("cache_dir") else None,
129
+ rate_limit=int(d.get("rate_limit", 7)),
128
130
  )
129
131
 
130
132
 
@@ -48,6 +48,7 @@ class AmoCRMExtractor:
48
48
  base_url=self.account.base_url,
49
49
  token_file=str(self.account.token_path),
50
50
  cache_config=cache_config,
51
+ rate_limit=self.account.rate_limit,
51
52
  )
52
53
 
53
54
  @property
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "amochka"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Python library for working with amoCRM API with ETL capabilities"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -31,7 +31,6 @@ keywords = ["amocrm", "crm", "api", "client", "automation", "etl"]
31
31
  requires-python = ">=3.6"
32
32
  dependencies = [
33
33
  "requests>=2.25.0",
34
- "ratelimit>=2.2.0",
35
34
  "psycopg2-binary>=2.9.0",
36
35
  "python-dotenv>=1.0.0"
37
36
  ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes