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.
- {amochka-0.4.5 → amochka-0.4.6}/PKG-INFO +1 -1
- {amochka-0.4.5 → amochka-0.4.6}/amochka/__init__.py +1 -1
- {amochka-0.4.5 → amochka-0.4.6}/amochka/client.py +25 -4
- {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/PKG-INFO +1 -1
- {amochka-0.4.5 → amochka-0.4.6}/pyproject.toml +1 -1
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_client.py +39 -0
- {amochka-0.4.5 → amochka-0.4.6}/README.md +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka/errors.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka/etl.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/SOURCES.txt +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/dependency_links.txt +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/requires.txt +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/amochka.egg-info/top_level.txt +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/__init__.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/config.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/extractors.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/loaders.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/migrations/001_create_tables.sql +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/run_etl.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/etl/transformers.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/setup.cfg +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_cache.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_etl.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_http.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_notes_events.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_security.py +0 -0
- {amochka-0.4.5 → amochka-0.4.6}/tests/test_utils.py +0 -0
|
@@ -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
|
-
|
|
1145
|
-
if
|
|
1146
|
-
if
|
|
1147
|
-
|
|
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
|
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|