1
1
from dataclasses import dataclass
2
2
from datetime import datetime , timezone
3
3
from unittest .mock import MagicMock , patch
4
+ import json
4
5
5
6
import pytest
6
7
@@ -225,14 +226,14 @@ def test_insert_with_unique_opts_by_state(client, mock_exec, simple_args):
225
226
insert_opts = InsertOpts (
226
227
unique_opts = UniqueOpts (
227
228
by_state = [
228
- "available" ,
229
- "cancelled" ,
230
- "completed" ,
231
- "discarded" ,
232
- "pending" ,
233
- "retryable" ,
234
- "running" ,
235
- "scheduled" ,
229
+ JobState . AVAILABLE ,
230
+ JobState . CANCELLED ,
231
+ JobState . COMPLETED ,
232
+ JobState . DISCARDED ,
233
+ JobState . PENDING ,
234
+ JobState . RETRYABLE ,
235
+ JobState . RUNNING ,
236
+ JobState . SCHEDULED ,
236
237
]
237
238
)
238
239
)
@@ -251,6 +252,143 @@ def test_insert_with_unique_opts_by_state(client, mock_exec, simple_args):
251
252
assert insert_params .unique_states == bytes ([0b11111111 ])
252
253
253
254
255
+ def test_insert_with_unique_opts_by_args_true (client , mock_exec , simple_args ):
256
+ """Test that by_args=True uses full args with sorted keys"""
257
+ mock_exec .job_insert_many .return_value = [("job_row" , False )]
258
+
259
+ # Call with by_args=True
260
+ insert_opts = InsertOpts (unique_opts = UniqueOpts (by_args = True ))
261
+
262
+ insert_res = client .insert (simple_args , insert_opts = insert_opts )
263
+
264
+ mock_exec .job_insert_many .assert_called_once ()
265
+ assert insert_res .job == "job_row"
266
+
267
+ # Verify the by_args=True was properly handled
268
+ call_args = mock_exec .job_insert_many .call_args [0 ][0 ]
269
+ assert len (call_args ) == 1
270
+ insert_params = call_args [0 ]
271
+ assert insert_params .unique_key is not None
272
+
273
+
274
+ def test_insert_with_unique_opts_by_args_sorting (
275
+ client : Client , mock_exec : MagicMock
276
+ ) -> None :
277
+ """Test that different key order in args produces the same unique key"""
278
+ mock_exec .job_insert_many .side_effect = [
279
+ [("job_row1" , False )],
280
+ [("job_row2" , False )],
281
+ ]
282
+
283
+ @dataclass
284
+ class JsonArgs :
285
+ kind : str = "ordered"
286
+ json_str : str = ""
287
+
288
+ def to_json (self ) -> str :
289
+ return self .json_str
290
+
291
+ # Insert with different key orders
292
+ insert_opts = InsertOpts (unique_opts = UniqueOpts (by_args = True ))
293
+
294
+ # Same data with different key orders
295
+ ordered_json = '{"a": 1, "b": 2, "c": 3}'
296
+ reverse_ordered_json = '{"c": 3, "b": 2, "a": 1}'
297
+
298
+ insert_res1 = client .insert (
299
+ JsonArgs (json_str = ordered_json ), insert_opts = insert_opts
300
+ )
301
+ insert_res2 = client .insert (
302
+ JsonArgs (json_str = reverse_ordered_json ), insert_opts = insert_opts
303
+ )
304
+
305
+ # Get the unique keys that were generated
306
+ call_args1 = mock_exec .job_insert_many .call_args_list [0 ][0 ][0 ] # type: ignore[index]
307
+ call_args2 = mock_exec .job_insert_many .call_args_list [1 ][0 ][0 ] # type: ignore[index]
308
+
309
+ # The unique keys should be identical despite different order in original JSON
310
+ assert call_args1 [0 ].unique_key == call_args2 [0 ].unique_key
311
+
312
+
313
+ def test_insert_with_unique_opts_by_args_partial_keys (
314
+ client : Client , mock_exec : MagicMock
315
+ ) -> None :
316
+ """Test that by_args with keys extracts only specified keys, even from nested objects"""
317
+ mock_exec .job_insert_many .return_value = [("job_row" , False )]
318
+
319
+ @dataclass
320
+ class JsonArgs :
321
+ kind : str = "partial"
322
+ json_str : str = ""
323
+
324
+ def to_json (self ) -> str :
325
+ return self .json_str
326
+
327
+ args1 = json .dumps (
328
+ {
329
+ "a" : "value" ,
330
+ "b" : "foo" ,
331
+ "c" : {
332
+ "d" : "bar" ,
333
+ },
334
+ "e" : "ignore_this" ,
335
+ }
336
+ )
337
+
338
+ # Same data as args1 except for omitted `e`, and reordered keys. It's a duplicate:
339
+ args2 = json .dumps (
340
+ {
341
+ "c" : {
342
+ "d" : "bar" ,
343
+ },
344
+ "b" : "foo" ,
345
+ "a" : "value" ,
346
+ }
347
+ )
348
+
349
+ # Missing `c`, so it's not a duplicate:
350
+ args3 = json .dumps (
351
+ {
352
+ "a" : "value" ,
353
+ "b" : "foo" ,
354
+ "d" : "something else" , # Omitted
355
+ }
356
+ )
357
+
358
+ args4 = json .dumps (
359
+ {
360
+ "b" : "foo" ,
361
+ "a" : "value" ,
362
+ "e" : "bar" , # Omitted
363
+ }
364
+ )
365
+
366
+ # Filter by a, b, and c:
367
+ insert_opts = InsertOpts (unique_opts = UniqueOpts (by_args = ["a" , "b" , "c" ]))
368
+
369
+ client .insert (JsonArgs (json_str = args1 ), insert_opts = insert_opts )
370
+ client .insert (JsonArgs (json_str = args2 ), insert_opts = insert_opts )
371
+ client .insert (JsonArgs (json_str = args3 ), insert_opts = insert_opts )
372
+ client .insert (JsonArgs (json_str = args4 ), insert_opts = insert_opts )
373
+
374
+ # Parse args to verify filtering
375
+ call_args_1 = mock_exec .job_insert_many .call_args_list [0 ][0 ][0 ] # type: ignore[index]
376
+ insert_params_1 = call_args_1 [0 ]
377
+ call_args_2 = mock_exec .job_insert_many .call_args_list [1 ][0 ][0 ] # type: ignore[index]
378
+ insert_params_2 = call_args_2 [0 ]
379
+ call_args_3 = mock_exec .job_insert_many .call_args_list [2 ][0 ][0 ] # type: ignore[index]
380
+ insert_params_3 = call_args_3 [0 ]
381
+ call_args_4 = mock_exec .job_insert_many .call_args_list [3 ][0 ][0 ] # type: ignore[index]
382
+ insert_params_4 = call_args_4 [0 ]
383
+
384
+ # Check that the keys were filtered correctly
385
+ assert insert_params_1 .unique_key == insert_params_2 .unique_key
386
+ # args3 is missing `c`, so it's not a duplicate:
387
+ assert insert_params_1 .unique_key != insert_params_3 .unique_key
388
+ # args3 and args4 are both the same when only looking at the filtered keys:
389
+ assert insert_params_3 .unique_key == insert_params_4 .unique_key
390
+
391
+
254
392
def test_insert_kind_error (client ):
255
393
@dataclass
256
394
class MyArgs :
0 commit comments