tracktolib 0.50.0__tar.gz → 0.51.1__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: tracktolib
3
- Version: 0.50.0
3
+ Version: 0.51.1
4
4
  Summary: Utility library for python
5
5
  Home-page: https://github.com/tracktor/tracktolib
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tracktolib"
3
- version = "0.50.0"
3
+ version = "0.51.1"
4
4
  description = "Utility library for python"
5
5
  authors = ["Julien Brayere <julien.brayere@tracktor.fr>"]
6
6
  license = "MIT"
@@ -81,7 +81,7 @@ pythonPlatform = "Linux"
81
81
 
82
82
  [tool.commitizen]
83
83
  name = "cz_conventional_commits"
84
- version = "0.50.0"
84
+ version = "0.51.1"
85
85
  tag_format = "$version"
86
86
  version_files = [
87
87
  "pyproject.toml:version"
@@ -75,6 +75,7 @@ class PGConflictQuery(Generic[K]):
75
75
  query: str | None = None
76
76
  constraint: str | None = None
77
77
  where: str | None = None
78
+ """JSONB keys to merge (like jsonb1 || newjsonb2)"""
78
79
  merge_keys: Iterable[K] | None = None
79
80
 
80
81
  def __post_init__(self):
@@ -198,17 +199,26 @@ def get_update_fields(
198
199
  start_from: int = 0,
199
200
  ignore_keys: list[str] | None = None,
200
201
  quote_columns: bool = False,
202
+ merge_keys: list[str] | None = None,
201
203
  ) -> tuple[str, list]:
202
204
  values, fields, where_values = [], [], []
203
205
  counter = 0
206
+ _merge_keys = set(merge_keys or [])
207
+ _ignore_keys = ignore_keys or []
208
+
204
209
  for k in keys:
205
210
  v = item[k]
206
- if ignore_keys and k in ignore_keys:
211
+ if k in _ignore_keys:
207
212
  where_values.append(v)
208
213
  continue
209
214
  values.append(v)
210
215
  _col = f'"{k}"' if quote_columns else k
211
- fields.append(f"{_col} = ${counter + start_from + 1}")
216
+ _counter = counter + start_from + 1
217
+ fields.append(
218
+ f"{_col} = ${_counter}"
219
+ if k not in _merge_keys
220
+ else f"{_col} = COALESCE(t.{_col}, jsonb_build_object()) || " f"${_counter}"
221
+ )
212
222
  counter += 1
213
223
  return ",\n".join(fields), values + where_values
214
224
 
@@ -227,6 +237,8 @@ class PGUpdateQuery(PGQuery):
227
237
  returning: str | list[str] | None = None
228
238
  """If True, the query will return all the updated fields"""
229
239
  return_keys: bool = False
240
+ """Values to update using merge (like {}::jsonb || {}::jsonb)"""
241
+ merge_keys: list[str] | None = None
230
242
 
231
243
  _update_fields: str | None = field(init=False, default=None)
232
244
  _values: list | None = field(init=False, default=None)
@@ -243,6 +255,7 @@ class PGUpdateQuery(PGQuery):
243
255
  start_from=self.start_from or 0,
244
256
  ignore_keys=self.where_keys,
245
257
  quote_columns=self.quote_columns,
258
+ merge_keys=self.merge_keys,
246
259
  )
247
260
  if self.returning and self.return_keys:
248
261
  raise ValueError("Please choose either returning or return_keys")
@@ -268,7 +281,7 @@ class PGUpdateQuery(PGQuery):
268
281
  raise ValueError("No update fields found")
269
282
 
270
283
  query = f"""
271
- UPDATE {self.table}
284
+ UPDATE {self.table} t
272
285
  SET {self._update_fields}
273
286
  {self._get_where_query()}
274
287
  """
@@ -375,8 +388,11 @@ async def update_one(
375
388
  keys: list[str] | None = None,
376
389
  start_from: int | None = None,
377
390
  where: str | None = None,
391
+ merge_keys: list[str] | None = None,
378
392
  ):
379
- query = PGUpdateQuery(table=table, items=[item], start_from=start_from, where_keys=keys, where=where)
393
+ query = PGUpdateQuery(
394
+ table=table, items=[item], start_from=start_from, where_keys=keys, where=where, merge_keys=merge_keys
395
+ )
380
396
  await conn.execute(query.query, *args, *query.values)
381
397
 
382
398
 
@@ -391,6 +407,7 @@ async def update_returning(
391
407
  where: str | None = None,
392
408
  keys: list[str] | None = None,
393
409
  start_from: int | None = None,
410
+ merge_keys: list[str] | None = None,
394
411
  ) -> Any | None: ...
395
412
 
396
413
 
@@ -405,6 +422,7 @@ async def update_returning(
405
422
  where: str | None = None,
406
423
  keys: list[str] | None = None,
407
424
  start_from: int | None = None,
425
+ merge_keys: list[str] | None = None,
408
426
  ) -> asyncpg.Record | None: ...
409
427
 
410
428
 
@@ -419,6 +437,7 @@ async def update_returning(
419
437
  where: str | None = None,
420
438
  keys: list[str] | None = None,
421
439
  start_from: int | None = None,
440
+ merge_keys: list[str] | None = None,
422
441
  ) -> asyncpg.Record | None: ...
423
442
 
424
443
 
@@ -432,6 +451,7 @@ async def update_returning(
432
451
  where: str | None = None,
433
452
  keys: list[str] | None = None,
434
453
  start_from: int | None = None,
454
+ merge_keys: list[str] | None = None,
435
455
  ) -> Any | asyncpg.Record | None:
436
456
  if returning is not None:
437
457
  returning_values = [returning] if isinstance(returning, str) else returning
@@ -445,6 +465,7 @@ async def update_returning(
445
465
  where_keys=keys,
446
466
  return_keys=return_keys,
447
467
  returning=returning_values,
468
+ merge_keys=merge_keys,
448
469
  )
449
470
  fn = conn.fetchval if len(returning_values or []) == 1 else conn.fetchrow
450
471
  return await fn(query.query, *args, *query.values)
@@ -69,6 +69,7 @@ def get_conflict_query(
69
69
  _ignore_columns = [*_update_columns, *_ignore_columns, *_merge_columns]
70
70
  fields = ", ".join(f"{x} = COALESCE(EXCLUDED.{x}, t.{x})" for x in columns if x not in _ignore_columns)
71
71
  if merge_columns:
72
+ fields = fields + ", " if fields else fields
72
73
  fields += ", ".join(f"{x} = COALESCE(t.{x}, jsonb_build_object()) || EXCLUDED.{x}" for x in merge_columns)
73
74
  if not fields:
74
75
  raise ValueError("No fields set")
File without changes
File without changes