11
11
import uuid
12
12
import warnings
13
13
14
- from django .core import management
14
+ from django .core . management import call_command
15
15
from django .core .management .utils import get_random_secret_key
16
16
from django .db import DatabaseError , connections
17
17
from django .http import HttpRequest
@@ -290,7 +290,7 @@ def _check_dir(dir_):
290
290
@staticmethod
291
291
def _migrate_db (db ):
292
292
try : # upgrade databases
293
- management . call_command ("migrate" , "--no-input" , "--database" , db , "--verbosity" , 0 )
293
+ call_command ("migrate" , "--no-input" , "--database" , db , "--verbosity" , 0 )
294
294
except Exception as e :
295
295
raise DatabaseMigrationError (extra_detail = str (e ))
296
296
else :
@@ -308,14 +308,23 @@ def _migrate_db(db):
308
308
nexus_group .permissions .set (Permission .objects .all ())
309
309
nexus_group .user_set .add (user )
310
310
311
+ @classmethod
312
+ def get_database_config (cls ) -> dict | None :
313
+ """Get the database configuration."""
314
+ if not cls ._is_setup :
315
+ return None
316
+ from django .conf import settings
317
+
318
+ return settings .DATABASES
319
+
311
320
def _is_sqlite (self , database : str ) -> bool :
312
- return not self ._in_memory and "sqlite" in self ._databases .get (database , {}).get (
321
+ return not self ._in_memory and "sqlite" in self .get_database_config () .get (database , {}).get (
313
322
"ENGINE" , ""
314
323
)
315
324
316
325
def _get_db_path (self , database : str ) -> str :
317
326
if self ._is_sqlite (database ):
318
- return self ._databases .get (database , {}).get ("NAME" , "" )
327
+ return self .get_database_config () .get (database , {}).get ("NAME" , "" )
319
328
return ""
320
329
321
330
@classmethod
@@ -485,6 +494,7 @@ def setup(self, collect_static: bool = False) -> None:
485
494
# Check for Linux TZ issue
486
495
report_utils .apply_timezone_workaround ()
487
496
497
+ # django configuration
488
498
try :
489
499
from django .conf import settings
490
500
@@ -497,8 +507,9 @@ def setup(self, collect_static: bool = False) -> None:
497
507
raise ImproperlyConfiguredError (extra_detail = str (e ))
498
508
499
509
# migrations
500
- if self ._databases :
501
- for db in self ._databases :
510
+ database_config = self .get_database_config ()
511
+ if database_config :
512
+ for db in database_config :
502
513
self ._migrate_db (db )
503
514
elif self ._db_directory is not None :
504
515
self ._migrate_db ("default" )
@@ -518,7 +529,7 @@ def setup(self, collect_static: bool = False) -> None:
518
529
"The 'static_directory' option must be specified to collect static files."
519
530
)
520
531
try :
521
- management . call_command ("collectstatic" , "--no-input" , "--verbosity" , 0 )
532
+ call_command ("collectstatic" , "--no-input" , "--verbosity" , 0 )
522
533
except Exception as e :
523
534
raise StaticFilesCollectionError (extra_detail = str (e ))
524
535
@@ -550,7 +561,7 @@ def backup_database(
550
561
) -> None :
551
562
if self ._in_memory :
552
563
raise ADRException ("Backup is not available in in-memory mode." )
553
- if database != "default" and database not in self ._databases :
564
+ if database != "default" and database not in self .get_database_config () :
554
565
raise ADRException (f"{ database } must be configured first using the 'databases' option." )
555
566
target_dir = Path (output_directory ).resolve (strict = True )
556
567
if not target_dir .is_dir ():
@@ -572,19 +583,19 @@ def backup_database(
572
583
if ignore_primary_keys :
573
584
args .append ("--natural-primary" )
574
585
try :
575
- management . call_command (* args )
586
+ call_command (* args )
576
587
except Exception as e :
577
588
raise ADRException (f"Backup failed: { e } " )
578
589
579
590
def restore_database (self , input_file : str | Path , * , database : str = "default" ) -> None :
580
- if database != "default" and database not in self ._databases :
591
+ if database != "default" and database not in self .get_database_config () :
581
592
raise ADRException (f"{ database } must be configured first using the 'databases' option." )
582
593
backup_file = Path (input_file ).resolve (strict = True )
583
594
if not backup_file .is_file ():
584
595
raise InvalidPath (extra_detail = f"{ input_file } is not a valid file." )
585
596
# call django management command to load the database
586
597
try :
587
- management . call_command (
598
+ call_command (
588
599
"loaddata" ,
589
600
str (backup_file ),
590
601
"--database" ,
@@ -724,7 +735,7 @@ def render_report(
724
735
request = self ._request , context = context , item_filter = item_filter
725
736
)
726
737
except Exception as e :
727
- raise e
738
+ raise ADRException ( f"Report rendering failed: { e } " )
728
739
729
740
@staticmethod
730
741
def query (
@@ -748,7 +759,7 @@ def create_objects(
748
759
raise ADRException ("objects must be an iterable" )
749
760
count = 0
750
761
for obj in objects :
751
- if obj .db and kwargs .get ("using" , "default" ) != obj .db :
762
+ if obj .db and kwargs .get ("using" , "default" ) != obj .db : # pragma: no cover
752
763
# required if copying across databases
753
764
obj .reinit ()
754
765
obj .save (** kwargs )
@@ -784,7 +795,7 @@ def copy_objects(
784
795
target_database : str ,
785
796
* ,
786
797
query : str = "" ,
787
- target_media_dir : str = "" ,
798
+ target_media_dir : str | Path = "" ,
788
799
test : bool = False ,
789
800
) -> int :
790
801
"""
@@ -796,9 +807,12 @@ def copy_objects(
796
807
source_database = "default" # todo: allow for source database to be specified
797
808
798
809
if not issubclass (object_type , (Item , Template , Session , Dataset )):
799
- raise TypeError (f"{ object_type } is not valid" )
810
+ raise TypeError (
811
+ f"'{ object_type .__name__ } ' is not a type of Item, Template, Session, or Dataset"
812
+ )
800
813
801
- if target_database not in self ._databases or source_database not in self ._databases :
814
+ database_config = self .get_database_config ()
815
+ if target_database not in database_config or source_database not in database_config :
802
816
raise ADRException (
803
817
f"'{ source_database } ' and '{ target_database } ' must be configured first using the 'databases' option."
804
818
)
@@ -812,7 +826,7 @@ def copy_objects(
812
826
# check for media dir if item has a physical file
813
827
if getattr (item , "has_file" , False ) and media_dir is None :
814
828
if target_media_dir :
815
- media_dir = target_media_dir
829
+ media_dir = Path ( target_media_dir ). resolve ( strict = True )
816
830
elif self ._is_sqlite (target_database ):
817
831
media_dir = self ._check_dir (
818
832
Path (self ._get_db_path (target_database )).parent / "media"
0 commit comments