amochka 0.4.5__tar.gz → 0.4.6__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.
Files changed (27) hide show
  1. {amochka-0.4.5 → amochka-0.4.6}/PKG-INFO +1 -1
  2. {amochka-0.4.5 → amochka-0.4.6}/amochka/__init__.py +1 -1
  3. {amochka-0.4.5 → amochka-0.4.6}/amochka/client.py +25 -4
  4. {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/PKG-INFO +1 -1
  5. {amochka-0.4.5 → amochka-0.4.6}/pyproject.toml +1 -1
  6. {amochka-0.4.5 → amochka-0.4.6}/tests/test_client.py +39 -0
  7. {amochka-0.4.5 → amochka-0.4.6}/README.md +0 -0
  8. {amochka-0.4.5 → amochka-0.4.6}/amochka/errors.py +0 -0
  9. {amochka-0.4.5 → amochka-0.4.6}/amochka/etl.py +0 -0
  10. {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/SOURCES.txt +0 -0
  11. {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/dependency_links.txt +0 -0
  12. {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/requires.txt +0 -0
  13. {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/top_level.txt +0 -0
  14. {amochka-0.4.5 → amochka-0.4.6}/etl/__init__.py +0 -0
  15. {amochka-0.4.5 → amochka-0.4.6}/etl/config.py +0 -0
  16. {amochka-0.4.5 → amochka-0.4.6}/etl/extractors.py +0 -0
  17. {amochka-0.4.5 → amochka-0.4.6}/etl/loaders.py +0 -0
  18. {amochka-0.4.5 → amochka-0.4.6}/etl/migrations/001_create_tables.sql +0 -0
  19. {amochka-0.4.5 → amochka-0.4.6}/etl/run_etl.py +0 -0
  20. {amochka-0.4.5 → amochka-0.4.6}/etl/transformers.py +0 -0
  21. {amochka-0.4.5 → amochka-0.4.6}/setup.cfg +0 -0
  22. {amochka-0.4.5 → amochka-0.4.6}/tests/test_cache.py +0 -0
  23. {amochka-0.4.5 → amochka-0.4.6}/tests/test_etl.py +0 -0
  24. {amochka-0.4.5 → amochka-0.4.6}/tests/test_http.py +0 -0
  25. {amochka-0.4.5 → amochka-0.4.6}/tests/test_notes_events.py +0 -0
  26. {amochka-0.4.5 → amochka-0.4.6}/tests/test_security.py +0 -0
  27. {amochka-0.4.5 → amochka-0.4.6}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amochka
3
- Version: 0.4.5
3
+ Version: 0.4.6
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
@@ -2,7 +2,7 @@
2
2
  amochka: Библиотека для работы с API amoCRM.
3
3
  """
4
4
 
5
- __version__ = "0.4.5"
5
+ __version__ = "0.4.6"
6
6
 
7
7
  from .client import AmoCRMClient, CacheConfig
8
8
  from .errors import (
@@ -1098,12 +1098,17 @@ class AmoCRMClient:
1098
1098
  limit: int = 250,
1099
1099
  extra_params: Optional[dict] = None,
1100
1100
  max_pages: Optional[int] = None,
1101
+ query_mode: str = "auto",
1102
+ min_phone_length: Optional[int] = None,
1101
1103
  ) -> Iterator[dict]:
1102
1104
  """
1103
1105
  Итератор контактов с фильтрацией по диапазону обновления, списку ID или query.
1104
1106
 
1105
1107
  :param query: Строка поиска (например, телефон). Перед отправкой очищается до цифр.
1106
1108
  :param min_query_length: Минимальная длина query (по числу цифр). Если не достигнута, query не отправляется.
1109
+ Deprecated: используйте min_phone_length.
1110
+ :param query_mode: Режим обработки query: auto | phone | raw.
1111
+ :param min_phone_length: Минимальная длина номера (по числу цифр). Применяется в phone/auto режимах.
1107
1112
 
1108
1113
  :param max_pages: Максимальное количество страниц для итерации (None = без ограничений)
1109
1114
  :raises ValidationError: Если параметры имеют некорректный тип или значение.
@@ -1130,6 +1135,15 @@ class AmoCRMClient:
1130
1135
  elif not isinstance(contact_ids, str):
1131
1136
  raise ValidationError(f"contact_ids must be int, str or sequence, got {type(contact_ids).__name__}")
1132
1137
 
1138
+ if min_query_length is not None and (not isinstance(min_query_length, int) or min_query_length < 1):
1139
+ raise ValidationError("min_query_length must be a positive int")
1140
+ if min_phone_length is not None and (not isinstance(min_phone_length, int) or min_phone_length < 1):
1141
+ raise ValidationError("min_phone_length must be a positive int")
1142
+
1143
+ mode = (query_mode or "auto").lower()
1144
+ if mode not in {"auto", "phone", "raw"}:
1145
+ raise ValidationError(f"query_mode must be one of: auto, phone, raw (got {query_mode})")
1146
+
1133
1147
  params = {"limit": limit, "page": 1}
1134
1148
  start_ts = self._to_timestamp(updated_from)
1135
1149
  end_ts = self._to_timestamp(updated_to)
@@ -1141,10 +1155,17 @@ class AmoCRMClient:
1141
1155
  if contact_param:
1142
1156
  params["filter[id][]"] = contact_param
1143
1157
  if query is not None:
1144
- query_digits = "".join(ch for ch in query.strip() if ch.isdigit())
1145
- if query_digits:
1146
- if min_query_length is None or len(query_digits) >= min_query_length:
1147
- params["query"] = query_digits
1158
+ query_str = str(query).strip()
1159
+ if query_str:
1160
+ effective_min_len = min_phone_length if min_phone_length is not None else min_query_length
1161
+ is_raw = mode == "raw" or (mode == "auto" and any(ch.isalpha() or ch == "@" for ch in query_str))
1162
+ if is_raw:
1163
+ params["query"] = query_str
1164
+ else:
1165
+ query_digits = "".join(ch for ch in query_str if ch.isdigit())
1166
+ if query_digits:
1167
+ if effective_min_len is None or len(query_digits) >= effective_min_len:
1168
+ params["query"] = query_digits
1148
1169
  if extra_params:
1149
1170
  params.update(extra_params)
1150
1171
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amochka
3
- Version: 0.4.5
3
+ Version: 0.4.6
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "amochka"
7
- version = "0.4.5"
7
+ version = "0.4.6"
8
8
  description = "Python library for working with amoCRM API with ETL capabilities"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -297,3 +297,42 @@ def test_iter_contacts_query_min_length(monkeypatch):
297
297
  monkeypatch.setattr(client, "_make_request", fake_request)
298
298
  list(client.iter_contacts(query="7925", min_query_length=8, max_pages=1))
299
299
  assert "query" not in captured["params"]
300
+
301
+
302
+ def test_iter_contacts_query_auto_raw_for_name(monkeypatch):
303
+ client = make_client()
304
+ captured = {}
305
+
306
+ def fake_request(method, endpoint, params=None, **kwargs):
307
+ captured["params"] = params
308
+ return {"_embedded": {"contacts": []}, "_page_count": 1}
309
+
310
+ monkeypatch.setattr(client, "_make_request", fake_request)
311
+ list(client.iter_contacts(query="ivan", max_pages=1))
312
+ assert captured["params"]["query"] == "ivan"
313
+
314
+
315
+ def test_iter_contacts_query_phone_mode_forces_digits(monkeypatch):
316
+ client = make_client()
317
+ captured = {}
318
+
319
+ def fake_request(method, endpoint, params=None, **kwargs):
320
+ captured["params"] = params
321
+ return {"_embedded": {"contacts": []}, "_page_count": 1}
322
+
323
+ monkeypatch.setattr(client, "_make_request", fake_request)
324
+ list(client.iter_contacts(query="ivan 7925", query_mode="phone", max_pages=1))
325
+ assert captured["params"]["query"] == "7925"
326
+
327
+
328
+ def test_iter_contacts_query_min_phone_length(monkeypatch):
329
+ client = make_client()
330
+ captured = {}
331
+
332
+ def fake_request(method, endpoint, params=None, **kwargs):
333
+ captured["params"] = params
334
+ return {"_embedded": {"contacts": []}, "_page_count": 1}
335
+
336
+ monkeypatch.setattr(client, "_make_request", fake_request)
337
+ list(client.iter_contacts(query="7925", min_phone_length=8, max_pages=1))
338
+ assert "query" not in captured["params"]
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes