Skip to content

Commit 7f8ea4f

Browse files
authored
Increase coverage (#289)
1 parent 9196e10 commit 7f8ea4f

File tree

8 files changed

+617
-91
lines changed

8 files changed

+617
-91
lines changed

src/ansys/dynamicreporting/core/common_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def get_install_info(
6666
if "CEIDEVROOTDOS" in os.environ:
6767
dirs_to_check.append(Path(os.environ["CEIDEVROOTDOS"]))
6868
# Common, default install locations
69-
if platform.system().startswith("Wind"):
69+
if platform.system().startswith("Wind"): # pragma: no cover
7070
install_loc = Path(rf"C:\Program Files\ANSYS Inc\v{CURRENT_VERSION}\CEI")
7171
else:
7272
install_loc = Path(f"/ansys_inc/v{CURRENT_VERSION}/CEI")

src/ansys/dynamicreporting/core/serverless/__init__.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,43 @@
11
# serverless
22

3-
# Import ADR directly
43
from .adr import ADR
54

6-
# Expose ADR immediately
7-
__all__ = ["ADR"]
5+
# Item-related imports
6+
from .item import HTML, Animation, Dataset, File, Image, Item, Scene, Session, String, Table, Tree
87

9-
# for organization and to avoid repeating the same class names in multiple places
10-
_item_classes = [
8+
# Template-related imports
9+
from .template import (
10+
BasicLayout,
11+
BoxLayout,
12+
CarouselLayout,
13+
DataFilterLayout,
14+
FooterLayout,
15+
HeaderLayout,
16+
ItemsComparisonGenerator,
17+
IteratorGenerator,
18+
IteratorLayout,
19+
PanelLayout,
20+
PPTXLayout,
21+
PPTXSlideLayout,
22+
ReportLinkLayout,
23+
SliderLayout,
24+
SQLQueryGenerator,
25+
StatisticalGenerator,
26+
TabLayout,
27+
TableMergeGenerator,
28+
TableMergeRCFilterGenerator,
29+
TableMergeValueFilterGenerator,
30+
TableReduceGenerator,
31+
TableSortFilterGenerator,
32+
TagPropertyLayout,
33+
Template,
34+
TOCLayout,
35+
TreeMergeGenerator,
36+
UserDefinedLayout,
37+
)
38+
39+
__all__ = [
40+
"ADR",
1141
"Session",
1242
"Dataset",
1343
"Item",
@@ -19,8 +49,6 @@
1949
"Animation",
2050
"Scene",
2151
"File",
22-
]
23-
_template_classes = [
2452
"Template",
2553
"BasicLayout",
2654
"PanelLayout",
@@ -49,16 +77,3 @@
4977
"StatisticalGenerator",
5078
"IteratorGenerator",
5179
]
52-
53-
# Dynamically import classes from item and template using importlib
54-
import importlib
55-
56-
item_module = importlib.import_module(".item", package=__package__)
57-
template_module = importlib.import_module(".template", package=__package__)
58-
59-
# Dynamically add these to the module namespace and __all__
60-
for cls_name in _item_classes + _template_classes:
61-
cls = getattr(item_module, cls_name, None) or getattr(template_module, cls_name, None)
62-
if cls:
63-
globals()[cls_name] = cls
64-
__all__.append(cls_name)

src/ansys/dynamicreporting/core/serverless/adr.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import uuid
1212
import warnings
1313

14-
from django.core import management
14+
from django.core.management import call_command
1515
from django.core.management.utils import get_random_secret_key
1616
from django.db import DatabaseError, connections
1717
from django.http import HttpRequest
@@ -290,7 +290,7 @@ def _check_dir(dir_):
290290
@staticmethod
291291
def _migrate_db(db):
292292
try: # upgrade databases
293-
management.call_command("migrate", "--no-input", "--database", db, "--verbosity", 0)
293+
call_command("migrate", "--no-input", "--database", db, "--verbosity", 0)
294294
except Exception as e:
295295
raise DatabaseMigrationError(extra_detail=str(e))
296296
else:
@@ -308,14 +308,23 @@ def _migrate_db(db):
308308
nexus_group.permissions.set(Permission.objects.all())
309309
nexus_group.user_set.add(user)
310310

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+
311320
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(
313322
"ENGINE", ""
314323
)
315324

316325
def _get_db_path(self, database: str) -> str:
317326
if self._is_sqlite(database):
318-
return self._databases.get(database, {}).get("NAME", "")
327+
return self.get_database_config().get(database, {}).get("NAME", "")
319328
return ""
320329

321330
@classmethod
@@ -485,6 +494,7 @@ def setup(self, collect_static: bool = False) -> None:
485494
# Check for Linux TZ issue
486495
report_utils.apply_timezone_workaround()
487496

497+
# django configuration
488498
try:
489499
from django.conf import settings
490500

@@ -497,8 +507,9 @@ def setup(self, collect_static: bool = False) -> None:
497507
raise ImproperlyConfiguredError(extra_detail=str(e))
498508

499509
# 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:
502513
self._migrate_db(db)
503514
elif self._db_directory is not None:
504515
self._migrate_db("default")
@@ -518,7 +529,7 @@ def setup(self, collect_static: bool = False) -> None:
518529
"The 'static_directory' option must be specified to collect static files."
519530
)
520531
try:
521-
management.call_command("collectstatic", "--no-input", "--verbosity", 0)
532+
call_command("collectstatic", "--no-input", "--verbosity", 0)
522533
except Exception as e:
523534
raise StaticFilesCollectionError(extra_detail=str(e))
524535

@@ -550,7 +561,7 @@ def backup_database(
550561
) -> None:
551562
if self._in_memory:
552563
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():
554565
raise ADRException(f"{database} must be configured first using the 'databases' option.")
555566
target_dir = Path(output_directory).resolve(strict=True)
556567
if not target_dir.is_dir():
@@ -572,19 +583,19 @@ def backup_database(
572583
if ignore_primary_keys:
573584
args.append("--natural-primary")
574585
try:
575-
management.call_command(*args)
586+
call_command(*args)
576587
except Exception as e:
577588
raise ADRException(f"Backup failed: {e}")
578589

579590
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():
581592
raise ADRException(f"{database} must be configured first using the 'databases' option.")
582593
backup_file = Path(input_file).resolve(strict=True)
583594
if not backup_file.is_file():
584595
raise InvalidPath(extra_detail=f"{input_file} is not a valid file.")
585596
# call django management command to load the database
586597
try:
587-
management.call_command(
598+
call_command(
588599
"loaddata",
589600
str(backup_file),
590601
"--database",
@@ -724,7 +735,7 @@ def render_report(
724735
request=self._request, context=context, item_filter=item_filter
725736
)
726737
except Exception as e:
727-
raise e
738+
raise ADRException(f"Report rendering failed: {e}")
728739

729740
@staticmethod
730741
def query(
@@ -748,7 +759,7 @@ def create_objects(
748759
raise ADRException("objects must be an iterable")
749760
count = 0
750761
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
752763
# required if copying across databases
753764
obj.reinit()
754765
obj.save(**kwargs)
@@ -784,7 +795,7 @@ def copy_objects(
784795
target_database: str,
785796
*,
786797
query: str = "",
787-
target_media_dir: str = "",
798+
target_media_dir: str | Path = "",
788799
test: bool = False,
789800
) -> int:
790801
"""
@@ -796,9 +807,12 @@ def copy_objects(
796807
source_database = "default" # todo: allow for source database to be specified
797808

798809
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+
)
800813

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:
802816
raise ADRException(
803817
f"'{source_database}' and '{target_database}' must be configured first using the 'databases' option."
804818
)
@@ -812,7 +826,7 @@ def copy_objects(
812826
# check for media dir if item has a physical file
813827
if getattr(item, "has_file", False) and media_dir is None:
814828
if target_media_dir:
815-
media_dir = target_media_dir
829+
media_dir = Path(target_media_dir).resolve(strict=True)
816830
elif self._is_sqlite(target_database):
817831
media_dir = self._check_dir(
818832
Path(self._get_db_path(target_database)).parent / "media"

tests/serverless/conftest.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ def adr_init(pytestconfig: pytest.Config) -> ADR:
1313
use_local = pytestconfig.getoption("use_local_launcher")
1414

1515
base_dir = Path(__file__).parent / "test_data"
16-
local_db = base_dir / f"auto_delete_{uuid4().hex}"
1716
static_dir = base_dir / "static"
1817
static_dir.mkdir(exist_ok=True)
19-
media_dir = base_dir / "media"
20-
media_dir.mkdir(exist_ok=True)
2118

2219
if use_local:
20+
local_db = base_dir / f"auto_delete_{uuid4().hex}"
21+
media_dir = base_dir / "media"
22+
media_dir.mkdir(exist_ok=True)
2323
adr = ADR(
2424
ansys_installation=pytestconfig.getoption("install_path"),
2525
db_directory=local_db,
@@ -28,12 +28,33 @@ def adr_init(pytestconfig: pytest.Config) -> ADR:
2828
static_url="/static2/",
2929
)
3030
else:
31+
# existing db directory
32+
source_db = base_dir / "documentation_examples"
33+
dest_db = base_dir / "dest"
34+
database_config = {
35+
"default": {
36+
"ENGINE": "sqlite3",
37+
"NAME": str(source_db / "db.sqlite3"),
38+
"USER": "nexus",
39+
"PASSWORD": "cei",
40+
"HOST": "",
41+
"PORT": "",
42+
},
43+
"dest": {
44+
"ENGINE": "sqlite3",
45+
"NAME": str(dest_db / "db.sqlite3"),
46+
"USER": "nexus",
47+
"PASSWORD": "cei",
48+
"HOST": "",
49+
"PORT": "",
50+
},
51+
}
3152
adr = ADR(
3253
ansys_installation="docker",
3354
docker_image=DOCKER_DEV_REPO_URL,
34-
db_directory=local_db,
55+
databases=database_config,
56+
media_directory=source_db / "media",
3557
static_directory=static_dir,
36-
media_directory=media_dir,
3758
media_url="/media1/",
3859
static_url="/static2/",
3960
)

0 commit comments

Comments
 (0)