amochka 0.1.2.1__tar.gz → 0.1.4__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.1
2
2
  Name: amochka
3
- Version: 0.1.2.1
3
+ Version: 0.1.4
4
4
  Summary: Библиотека для работы с API amoCRM
5
5
  Home-page: UNKNOWN
6
6
  Author: Timurka
@@ -22,7 +22,7 @@ class Deal(dict):
22
22
 
23
23
  Обеспечивает два способа доступа к кастомным полям:
24
24
  1. get(key): при обращении по названию (строкой) или по ID поля (integer)
25
- возвращает текстовое значение поля (например, «Гурина Юлия»).
25
+ возвращает текстовое значение поля (например, «Дурина Юлия»).
26
26
  2. get_id(key): возвращает идентификатор выбранного варианта (enum_id) для полей типа select.
27
27
  Если в данных enum_id отсутствует, производится поиск в переданной конфигурации полей,
28
28
  сравнение выполняется без учёта регистра и лишних пробелов.
@@ -41,9 +41,11 @@ class Deal(dict):
41
41
  values = field.get("values")
42
42
  if field_name and values and isinstance(values, list) and len(values) > 0:
43
43
  key_name = field_name.lower().strip()
44
- # Сохраняем текстовое значение для доступа по названию
45
- self._custom[key_name] = values[0].get("value")
46
- logger.debug(f"Set custom field '{key_name}' = {self._custom[key_name]}")
44
+ stored_value = values[0].get("value")
45
+ stored_enum_id = values[0].get("enum_id") # может быть None для некоторых полей
46
+ # Сохраняем полную информацию (и для get() и для get_id())
47
+ self._custom[key_name] = {"value": stored_value, "enum_id": stored_enum_id}
48
+ logger.debug(f"Set custom field '{key_name}' = {{'value': {stored_value}, 'enum_id': {stored_enum_id}}}")
47
49
  field_id = field.get("field_id")
48
50
  if field_id is not None and values and isinstance(values, list) and len(values) > 0:
49
51
  stored_value = values[0].get("value")
@@ -80,7 +82,7 @@ class Deal(dict):
80
82
  def get_id(self, key, default=None):
81
83
  """
82
84
  Возвращает идентификатор выбранного варианта (enum_id) для кастомного поля.
83
- Если значение enum_id отсутствует в данных, производится поиск в конфигурации полей,
85
+ Если значение enum_id отсутствует в данных, производится поиск в конфигурации кастомных полей,
84
86
  сравнение значения выполняется без учёта регистра и пробелов.
85
87
 
86
88
  :param key: Название поля (строка) или ID поля (integer).
@@ -99,7 +101,6 @@ class Deal(dict):
99
101
  enum_id = stored.get("enum_id")
100
102
  if enum_id is not None:
101
103
  return enum_id
102
- # Если enum_id отсутствует, пробуем найти его в конфигурации кастомных полей
103
104
  if self._custom_config:
104
105
  field_def = None
105
106
  if isinstance(key, int):
@@ -112,7 +113,6 @@ class Deal(dict):
112
113
  if field_def:
113
114
  enums = field_def.get("enums") or []
114
115
  for enum in enums:
115
- # Сравниваем текстовое значение без учёта регистра и лишних пробелов
116
116
  if enum.get("value", "").lower().strip() == stored.get("value", "").lower().strip():
117
117
  return enum.get("id", default)
118
118
  return default
@@ -132,23 +132,45 @@ class AmoCRMClient:
132
132
  Дополнительно можно задать уровень логирования через параметр log_level,
133
133
  либо полностью отключить логирование, установив disable_logging=True.
134
134
  """
135
- def __init__(self, base_url, token_file=None, cache_file=None, log_level=logging.INFO, disable_logging=False):
135
+ def __init__(
136
+ self,
137
+ base_url,
138
+ token_file=None,
139
+ cache_file=None,
140
+ log_level=logging.INFO,
141
+ disable_logging=False,
142
+ cache_enabled=True,
143
+ cache_storage='file', # 'file' или 'memory'
144
+ cache_hours=24 # время жизни кэша в часах, или None для бесконечного кэша
145
+ ):
136
146
  """
137
- Инициализирует клиента, задавая базовый URL, токен авторизации и файл кэша для кастомных полей.
138
-
147
+ Инициализирует клиента, задавая базовый URL, токен авторизации и настройки кэша для кастомных полей.
148
+
139
149
  :param base_url: Базовый URL API amoCRM.
140
150
  :param token_file: Файл, содержащий токен авторизации.
141
151
  :param cache_file: Файл для кэширования данных кастомных полей.
142
152
  :param log_level: Уровень логирования (например, logging.DEBUG, logging.INFO).
143
153
  :param disable_logging: Если True, логирование будет отключено.
154
+ :param cache_enabled: Если False, кэширование отключается (остальные параметры игнорируются).
155
+ :param cache_storage: 'file' для файлового кэша, 'memory' для кэша только в оперативной памяти.
156
+ :param cache_hours: Время жизни кэша в часах. Если None – кэш считается бесконечным.
144
157
  """
145
158
  self.base_url = base_url.rstrip('/')
146
159
  domain = self.base_url.split("//")[-1].split(".")[0]
147
160
  self.domain = domain
148
161
  self.token_file = token_file or os.path.join(os.path.expanduser('~'), '.amocrm_token.json')
149
- if not cache_file:
150
- cache_file = f"custom_fields_cache_{self.domain}.json"
151
- self.cache_file = cache_file
162
+
163
+ # Если выбран файловый кэш, определяем имя файла, иначе он не используется
164
+ if cache_storage.lower() == 'file':
165
+ if not cache_file:
166
+ cache_file = f"custom_fields_cache_{self.domain}.json"
167
+ self.cache_file = cache_file
168
+ else:
169
+ self.cache_file = None
170
+ self.cache_enabled = cache_enabled
171
+ self.cache_storage = cache_storage.lower() # 'file' или 'memory'
172
+ self.cache_hours = cache_hours
173
+
152
174
  self.token = self.load_token()
153
175
  self._custom_fields_mapping = None
154
176
 
@@ -233,10 +255,15 @@ class AmoCRMClient:
233
255
 
234
256
  def _save_custom_fields_cache(self, mapping):
235
257
  """
236
- Сохраняет кэшированное отображение кастомных полей в файл.
237
-
238
- :param mapping: Словарь с отображением кастомных полей.
258
+ Сохраняет кэш кастомных полей в файл, если используется файловый кэш.
259
+ Если кэширование отключено или выбран кэш в памяти, операция пропускается.
239
260
  """
261
+ if not self.cache_enabled:
262
+ logger.debug("Caching disabled; cache not saved.")
263
+ return
264
+ if self.cache_storage != 'file':
265
+ logger.debug("Using memory caching; no file cache saved.")
266
+ return
240
267
  cache_data = {"last_updated": time.time(), "mapping": mapping}
241
268
  with open(self.cache_file, "w") as f:
242
269
  json.dump(cache_data, f)
@@ -244,10 +271,15 @@ class AmoCRMClient:
244
271
 
245
272
  def _load_custom_fields_cache(self):
246
273
  """
247
- Загружает кэш кастомных полей из файла.
248
-
249
- :return: Кэшированные данные или None, если не удалось загрузить.
274
+ Загружает кэш кастомных полей из файла, если используется файловый кэш.
275
+ Если кэширование отключено или выбран кэш в памяти, возвращает None.
250
276
  """
277
+ if not self.cache_enabled:
278
+ logger.debug("Caching disabled; no cache loaded.")
279
+ return None
280
+ if self.cache_storage != 'file':
281
+ logger.debug("Using memory caching; cache will be kept in memory only.")
282
+ return None
251
283
  if os.path.exists(self.cache_file):
252
284
  with open(self.cache_file, "r") as f:
253
285
  try:
@@ -259,26 +291,27 @@ class AmoCRMClient:
259
291
  return None
260
292
  return None
261
293
 
262
- def get_custom_fields_mapping(self, force_update=False, cache_duration_hours=24):
294
+ def get_custom_fields_mapping(self, force_update=False):
263
295
  """
264
296
  Возвращает словарь отображения кастомных полей для сделок.
265
- Если данные кэшированы и не устарели, возвращает кэш; иначе выполняет серию запросов,
266
- чтобы получить все страницы (с лимитом 250 полей на запрос).
267
-
268
- :param force_update: Принудительное обновление кэша.
269
- :param cache_duration_hours: Время жизни кэша в часах.
270
- :return: Словарь mapping, где ключи – ID полей, а значения – их модели.
297
+ Если данные кэшированы и не устарели, возвращает кэш; иначе выполняет запросы для получения данных.
271
298
  """
272
- if not force_update:
273
- if self._custom_fields_mapping:
274
- return self._custom_fields_mapping
275
- cache_data = self._load_custom_fields_cache()
276
- if cache_data:
277
- last_updated = cache_data.get("last_updated", 0)
278
- if time.time() - last_updated < cache_duration_hours * 3600:
299
+ if not force_update and self._custom_fields_mapping is not None:
300
+ return self._custom_fields_mapping
301
+
302
+ cache_data = self._load_custom_fields_cache() if self.cache_enabled else None
303
+ if cache_data:
304
+ last_updated = cache_data.get("last_updated", 0)
305
+ if self.cache_hours is not None:
306
+ if time.time() - last_updated < self.cache_hours * 3600:
279
307
  self._custom_fields_mapping = cache_data.get("mapping")
280
308
  logger.debug("Using cached custom fields mapping.")
281
309
  return self._custom_fields_mapping
310
+ else:
311
+ # Бесконечный кэш – не проверяем срок
312
+ self._custom_fields_mapping = cache_data.get("mapping")
313
+ logger.debug("Using cached custom fields mapping (infinite cache).")
314
+ return self._custom_fields_mapping
282
315
 
283
316
  mapping = {}
284
317
  page = 1
@@ -297,7 +330,8 @@ class AmoCRMClient:
297
330
 
298
331
  logger.debug("Custom fields mapping fetched (содержимое маппинга не выводится полностью).")
299
332
  self._custom_fields_mapping = mapping
300
- self._save_custom_fields_cache(mapping)
333
+ if self.cache_enabled:
334
+ self._save_custom_fields_cache(mapping)
301
335
  return mapping
302
336
 
303
337
  def find_custom_field_id(self, search_term):
@@ -347,14 +381,11 @@ class AmoCRMClient:
347
381
  payload[key] = value
348
382
  logger.debug(f"Standard field {key} set to {value}")
349
383
  else:
350
- # Если значение integer, интерпретируем как enum_id для полей типа select,
351
- # иначе как текстовое значение.
352
384
  if isinstance(value, int):
353
385
  field_value_dict = {"enum_id": value}
354
386
  else:
355
387
  field_value_dict = {"value": value}
356
388
  try:
357
- # Если ключ уже число, считаем его field_id
358
389
  field_id = int(key)
359
390
  custom_fields.append({"field_id": field_id, "values": [field_value_dict]})
360
391
  logger.debug(f"Custom field by id {field_id} set to {value}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: amochka
3
- Version: 0.1.2.1
3
+ Version: 0.1.4
4
4
  Summary: Библиотека для работы с API amoCRM
5
5
  Home-page: UNKNOWN
6
6
  Author: Timurka
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='amochka',
5
- version='0.1.2.1',
5
+ version='0.1.4',
6
6
  packages=find_packages(),
7
7
  install_requires=[
8
8
  'requests',
File without changes
File without changes
File without changes