@@ -302,12 +302,130 @@ def test_whichdb_sqlite3_existing_db(self):
302
302
cx .close ()
303
303
self .assertEqual (self .dbm .whichdb (_fname ), "dbm.sqlite3" )
304
304
305
+ def setUp (self ):
306
+ self .addCleanup (cleaunup_test_dir )
307
+ setup_test_dir ()
308
+ self .dbm = import_helper .import_fresh_module ('dbm' )
309
+
305
310
311
+ class DBMBackendTestCase (unittest .TestCase ):
306
312
def setUp (self ):
307
313
self .addCleanup (cleaunup_test_dir )
308
314
setup_test_dir ()
309
315
self .dbm = import_helper .import_fresh_module ('dbm' )
310
316
317
+ @staticmethod
318
+ def get_available_backends ():
319
+ available_backends = []
320
+ for backend_name in ['dbm.dumb' , 'dbm.gnu' , 'dbm.ndbm' , 'dbm.sqlite3' ]:
321
+ try :
322
+ __import__ (backend_name , fromlist = ['open' ])
323
+ available_backends .append (backend_name )
324
+ except ImportError :
325
+ pass
326
+ return available_backends
327
+
328
+ def test_backend_parameter_validation (self ):
329
+ invalid_types = [123 , [], {}, object (), dbm ]
330
+ for invalid_backend in invalid_types :
331
+ with self .subTest (invalid_backend = invalid_backend ):
332
+ with self .assertRaises (TypeError ) as cm :
333
+ dbm .open (_fname , backend = invalid_backend )
334
+ self .assertIn ("backend must be a string" , str (cm .exception ))
335
+
336
+ invalid_names = ['invalid' , 'postgres' , 'gnu' , 'dumb' , 'sqlite3' ]
337
+ for invalid_name in invalid_names :
338
+ with self .subTest (invalid_name = invalid_name ):
339
+ with self .assertRaises (ValueError ) as cm :
340
+ dbm .open (_fname , backend = invalid_name )
341
+ self .assertIn ("Unknown backend" , str (cm .exception ))
342
+
343
+ def test_backend_parameter_functionality (self ):
344
+ valid_backends = self .get_available_backends ()
345
+ if len (valid_backends ) < 1 :
346
+ self .skipTest ("Need at least 1 backends for this test" )
347
+
348
+ for backend in valid_backends :
349
+ with self .subTest (backend = backend ):
350
+ unique_fn = f"{ _fname } _{ backend } "
351
+ with dbm .open (unique_fn , 'c' , backend = backend ) as db :
352
+ db [b'test_key' ] = b'test_value'
353
+ db [b'backend' ] = backend .encode ('ascii' )
354
+
355
+ self .assertEqual (dbm .whichdb (unique_fn ), backend )
356
+
357
+ with dbm .open (unique_fn , 'r' , backend = backend ) as db :
358
+ self .assertEqual (db [b'test_key' ], b'test_value' )
359
+ self .assertEqual (db [b'backend' ], backend .encode ('ascii' ))
360
+
361
+ def test_backend_none_preserves_auto_selection (self ):
362
+ with dbm .open (_fname , 'c' ) as db1 :
363
+ db1 [b'test' ] = b'auto_selection'
364
+ backend1 = dbm .whichdb (_fname )
365
+
366
+ with dbm .open (_fname , 'c' , backend = None ) as db2 :
367
+ db2 [b'test' ] = b'explicit_none'
368
+ backend2 = dbm .whichdb (_fname )
369
+
370
+ self .assertEqual (backend1 , backend2 )
371
+
372
+ def test_backend_with_different_flags (self ):
373
+ valid_backends = self .get_available_backends ()
374
+ if len (valid_backends ) < 1 :
375
+ self .skipTest ("Need at least 1 backends for this test" )
376
+
377
+ for backend in valid_backends :
378
+ with self .subTest (backend = backend ):
379
+ unique_fn = f"{ _fname } _{ backend } "
380
+ with dbm .open (unique_fn , 'c' , backend = backend ) as db :
381
+ db [b'flag_test' ] = b'create'
382
+ self .assertEqual (dbm .whichdb (unique_fn ), backend )
383
+
384
+ # Test 'w' flag (write existing)
385
+ with dbm .open (unique_fn , 'w' , backend = backend ) as db :
386
+ self .assertEqual (db [b'flag_test' ], b'create' )
387
+ db [b'flag_test' ] = b'write'
388
+
389
+ # Test 'r' flag (read-only)
390
+ with dbm .open (unique_fn , 'r' , backend = backend ) as db :
391
+ self .assertEqual (db [b'flag_test' ], b'write' )
392
+ with self .assertRaises (dbm .error ):
393
+ db [b'readonly_test' ] = b'should_fail'
394
+
395
+ # Test 'n' flag (new database)
396
+ new_file = f"{ unique_fn } _new"
397
+ with dbm .open (new_file , 'n' , backend = backend ) as db :
398
+ db [b'new_test' ] = b'new_data'
399
+
400
+ self .assertEqual (dbm .whichdb (new_file ), backend )
401
+
402
+ def test_backend_parameter_positioning (self ):
403
+ valid_backends = self .get_available_backends ()
404
+ if len (valid_backends ) < 1 :
405
+ self .skipTest ("Need at least 1 backends for this test" )
406
+
407
+ for backend in valid_backends :
408
+ with self .subTest (backend = backend ):
409
+ unique_fn = f"{ _fname } _{ backend } "
410
+
411
+ # Test as keyword argument
412
+ file_1 = f"{ unique_fn } _keyword"
413
+ with dbm .open (file_1 , 'c' , backend = backend ) as db :
414
+ db [b'test' ] = b'keyword'
415
+
416
+ # Test as positional argument
417
+ file_2 = f"{ unique_fn } _positional"
418
+ with dbm .open (file_2 , 'c' , 0o666 , backend ) as db :
419
+ db [b'test' ] = b'positional'
420
+
421
+ self .assertEqual (dbm .whichdb (file_1 ), backend )
422
+ self .assertEqual (dbm .whichdb (file_2 ), backend )
423
+
424
+ def test_backend_import_error_handling (self ):
425
+ fake_backend = 'dbm.nonexistent'
426
+ with self .assertRaises (ValueError ) as cm :
427
+ dbm .open (_fname , backend = fake_backend )
428
+ self .assertIn ('Unknown backend' , str (cm .exception ))
311
429
312
430
for mod in dbm_iterator ():
313
431
assert mod .__name__ .startswith ('dbm.' )
0 commit comments