From d66590221aba588edb8c7132d0df0e9681b8a1a3 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 26 Feb 2025 14:05:13 -0500 Subject: [PATCH 01/72] disable ci --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 399a419b2..c0b097a2b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} - smoketest: - name: Build and smoke tests - runs-on: ${{ matrix.os }} - needs: [ style ] - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, windows-latest ] - python-version: [ '3.10', '3.11', '3.12', '3.13' ] - steps: - - name: Build wheelhouse - uses: ansys/actions/build-wheelhouse@v8 - with: - library-name: ${{ env.PACKAGE_NAME }} - operating-system: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} - - - name: Install library - run: python --version && python -m pip install ${{ env.install_target }} - - - name: Run smoketest - run: make smoketest +# smoketest: +# name: Build and smoke tests +# runs-on: ${{ matrix.os }} +# needs: [ style ] +# strategy: +# fail-fast: false +# matrix: +# os: [ ubuntu-latest, windows-latest ] +# python-version: [ '3.10', '3.11', '3.12', '3.13' ] +# steps: +# - name: Build wheelhouse +# uses: ansys/actions/build-wheelhouse@v8 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# operating-system: ${{ matrix.os }} +# python-version: ${{ matrix.python-version }} +# +# - name: Install library +# run: python --version && python -m pip install ${{ env.install_target }} +# +# - name: Run smoketest +# run: make smoketest test: name: Testing - needs: [ smoketest ] +# needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index ac2b21f47..f8715eb86 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless test-dev: pip install -e .[test] From b5f9ba33c721a1e49a9762004f1f3e93d715c3b8 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 26 Feb 2025 14:05:36 -0500 Subject: [PATCH 02/72] guids are always str --- src/ansys/dynamicreporting/core/serverless/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index 303f12813..a1a08be05 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -72,7 +72,7 @@ def save(self, **kwargs): raise Template.NotSaved( extra_detail="Failed to save template because its children are not saved" ) - children_order.append(str(child.guid)) + children_order.append(child.guid) self._children_order = ",".join(children_order) self._master = self.parent is None # set properties @@ -148,7 +148,7 @@ def find(cls, query="", **kwargs): return super().find(query=query_string, **kwargs) def reorder_children(self) -> None: - guid_to_child = {str(child.guid): child for child in self.children} + guid_to_child = {child.guid: child for child in self.children} sorted_guids = self.children_order.lower().split(",") # return the children based on the order of guids in children_order reordered = [] From 896e78405ac6091fdcea79ba696076895cda5af0 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 26 Feb 2025 15:20:53 -0500 Subject: [PATCH 03/72] update tests --- .../dynamicreporting/core/serverless/adr.py | 2 +- tests/serverless/test_adr.py | 133 +++++++++--------- tests/serverless/test_item.py | 66 +++++++++ tests/serverless/test_template.py | 0 4 files changed, 137 insertions(+), 64 deletions(-) create mode 100644 tests/serverless/test_item.py create mode 100644 tests/serverless/test_template.py diff --git a/src/ansys/dynamicreporting/core/serverless/adr.py b/src/ansys/dynamicreporting/core/serverless/adr.py index 26eeea037..de2410fec 100644 --- a/src/ansys/dynamicreporting/core/serverless/adr.py +++ b/src/ansys/dynamicreporting/core/serverless/adr.py @@ -319,7 +319,7 @@ def _get_db_path(self, database: str) -> str: return "" @classmethod - def get_instance(cls): + def get_instance(cls) -> "ADR": """Retrieve the configured ADR instance.""" if cls._instance is None: raise RuntimeError("There is no ADR instance available. Instantiate ADR first.") diff --git a/tests/serverless/test_adr.py b/tests/serverless/test_adr.py index 44b4ffa9e..a2f105def 100644 --- a/tests/serverless/test_adr.py +++ b/tests/serverless/test_adr.py @@ -90,6 +90,7 @@ def test_get_instance_dataset(): @pytest.mark.ado_test def test_init_twice(adr_serverless): + # return the same instance from ansys.dynamicreporting.core.constants import DOCKER_DEV_REPO_URL adr = ADR( @@ -159,57 +160,20 @@ def test_create_html(adr_serverless): assert HTML.get(name="intro_html").guid == intro_html.guid -@pytest.mark.ado_test -def test_set_tags(adr_serverless): - from ansys.dynamicreporting.core.serverless import HTML - - intro_html = HTML.get(name="intro_html") - intro_html.set_tags("dp=dp227 section=intro") - intro_html.save() - - assert "section=intro" in HTML.get(guid=intro_html.guid).tags - - -@pytest.mark.ado_test -def test_get_tags(adr_serverless): - from ansys.dynamicreporting.core.serverless import HTML - - intro_html = HTML.get(name="intro_html") - assert "dp=dp227" in intro_html.get_tags() - - @pytest.mark.ado_test def test_edit_html(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML - intro_html = HTML.get(name="intro_html") - intro_html.content = ( - "

Heading 1

" - "

Heading 2

" - "

Heading 3

" - "

Heading 4

" - "
Heading 5
" - "Two breaks below" - "

" - "
Heading 6 (& one break below)
" - "
" + adr_serverless.create_item( + HTML, + name="test_edit_html", + content="

Heading 1

", ) + intro_html = HTML.get(name="test_edit_html") + intro_html.content = "

Heading 2

" "
" intro_html.save() - assert "end" not in HTML.get(guid=intro_html.guid).content - - -@pytest.mark.ado_test -def test_add_rem_tag(adr_serverless): - from ansys.dynamicreporting.core.serverless import HTML - - intro_html = HTML.get(name="intro_html") - intro_html.add_tag("pptx_slide_title", "headers and breaks") - intro_html.save() - intro_html.rem_tag("pptx_slide_title") - intro_html.save() - - assert "pptx_slide_title" not in HTML.get(guid=intro_html.guid).get_tags() + assert "h1" not in HTML.get(guid=intro_html.guid).content @pytest.mark.ado_test @@ -505,20 +469,48 @@ def test_create_demo_report(adr_serverless): top_parent.children.append(results_panel) top_parent.save() + from ansys.dynamicreporting.core.serverless import Template + + test_parent = Template.get(name="Serverless Simulation Report") + assert test_parent.guid == top_parent.guid + for child in test_parent.children: + assert child.guid in top_parent.children_order + @pytest.mark.ado_test def test_query_items(adr_serverless): from ansys.dynamicreporting.core.serverless import File, Item - objs = adr_serverless.query(query_type=File, query="A|i_name|cont|intro_file;") + # file + adr_serverless.create_item( + File, + name="query_test_file", + content=str(Path(__file__).parent / "test_data" / "input.pptx"), + ) + + objs = adr_serverless.query(query_type=File, query="A|i_name|cont|query_test_file;") objs2 = adr_serverless.query( - query_type=Item, query="A|i_type|cont|file;A|i_name|cont|intro_file;" + query_type=Item, query="A|i_type|cont|file;A|i_name|cont|query_test_file;" ) - assert objs and objs2 + assert len(objs) == 1 and len(objs2) == 1 @pytest.mark.ado_test def test_get_list_reports(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + top_parent = adr_serverless.create_template( + BasicLayout, name="test_get_list_reports", parent=None + ) + top_parent.set_filter("A|i_name|eq|__NonexistentName__;") + top_parent.save() + + toc_layout = adr_serverless.create_template( + TOCLayout, name="test_get_list_reports_toc", parent=top_parent + ) + toc_layout.set_filter("A|i_name|eq|__NonexistentName__;") + toc_layout.save() + count = len(adr_serverless.get_list_reports(r_type="name")) assert count > 0, "No reports found" @@ -527,12 +519,16 @@ def test_get_list_reports(adr_serverless): def test_query_templates(adr_serverless): from ansys.dynamicreporting.core.serverless import Template, TOCLayout - temps = adr_serverless.query(query_type=TOCLayout, query="A|t_name|eq|TOC;") + toc_layout = adr_serverless.create_template(TOCLayout, name="test_query_templates") + toc_layout.set_filter("A|i_name|eq|__NonexistentName__;") + toc_layout.save() + + temps = adr_serverless.query(query_type=TOCLayout, query="A|t_name|eq|test_query_templates;") temps2 = adr_serverless.query( - query_type=Template, query="A|t_types|cont|Layout:toc;A|t_name|eq|TOC;" + query_type=Template, query="A|t_types|cont|Layout:toc;A|t_name|eq|test_query_templates;" ) - assert temps and temps2 + assert len(temps) == 1 and len(temps2) == 1 @pytest.mark.ado_test @@ -549,37 +545,48 @@ def test_query_no_templates(adr_serverless): @pytest.mark.ado_test def test_delete_items(adr_serverless): - from ansys.dynamicreporting.core.serverless import Item + from ansys.dynamicreporting.core.serverless import File, Item - del_items = adr_serverless.query(query_type=Item, query="A|i_tags|cont|dp=dp227;") + # file + adr_serverless.create_item( + File, + name="test_delete_items", + content=str(Path(__file__).parent / "test_data" / "input.pptx"), + tags="test_delete_items", + ) + + del_items = adr_serverless.query(query_type=Item, query="A|i_tags|cont|test_delete_items;") count = del_items.delete() - assert count > 0, "No items deleted" + assert count == 1, "No items deleted" @pytest.mark.ado_test def test_delete_sessions(adr_serverless): from ansys.dynamicreporting.core.serverless import Session - del_sesh = adr_serverless.query(query_type=Session, query="A|s_tags|cont|dp=dp227;") + _ = Session.create(application="test_delete_sessions", tags="test_delete_sessions;") + del_sesh = adr_serverless.query(query_type=Session, query="A|s_tags|cont|test_delete_sessions;") count = del_sesh.delete() - assert count > 0, "No sessions deleted" + assert count == 1, "No sessions deleted" @pytest.mark.ado_test def test_delete_datasets(adr_serverless): from ansys.dynamicreporting.core.serverless import Dataset - del_dataset = adr_serverless.query(query_type=Dataset, query="A|d_tags|cont|dp=dp227;") + _ = Dataset.create(filename="test_delete_datasets", tags="test_delete_datasets;") + del_dataset = adr_serverless.query( + query_type=Dataset, query="A|d_tags|cont|test_delete_datasets" + ) count = del_dataset.delete() - assert count > 0, "No datasets deleted" + assert count == 1, "No datasets deleted" @pytest.mark.ado_test def test_delete_templates(adr_serverless): - from ansys.dynamicreporting.core.serverless import Template + from ansys.dynamicreporting.core.serverless import Template, TOCLayout - del_templates = adr_serverless.query( - query_type=Template, query="A|t_name|eq|Serverless Simulation Report;" - ) - count = del_templates.delete() - assert count > 0, "No templates deleted" + _ = adr_serverless.create_template(TOCLayout, name="test_delete_templates") + temps = adr_serverless.query(query_type=TOCLayout, query="A|t_name|eq|test_delete_templates;") + count = temps.delete() + assert count == 1, "No templates deleted" diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py new file mode 100644 index 000000000..71121ad07 --- /dev/null +++ b/tests/serverless/test_item.py @@ -0,0 +1,66 @@ +import pytest + + +@pytest.mark.ado_test +def test_create_html_cls(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_create_html_cls", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert HTML.get(name="test_create_html_cls").guid == intro_html.guid + + +@pytest.mark.ado_test +def test_add_rem_tag(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_create_html_cls", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.add_tag("pptx_slide_title", "headers and breaks") + intro_html.save() + + assert "pptx_slide_title" in HTML.get(guid=intro_html.guid).get_tags() + + intro_html.rem_tag("pptx_slide_title") + intro_html.remove_tag("pptx_slide_title") + intro_html.save() + + assert "pptx_slide_title" not in HTML.get(guid=intro_html.guid).get_tags() + + +@pytest.mark.ado_test +def test_set_tags(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_set_tags", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.set_tags("section=intro") + intro_html.save() + + assert "section" in HTML.get(guid=intro_html.guid).tags + + +@pytest.mark.ado_test +def test_get_tags(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_set_tags", + tags="dp=dp227", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert "dp=dp227" in HTML.get(guid=intro_html.guid).get_tags() diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py new file mode 100644 index 000000000..e69de29bb From a15845653f16f9adf0c81cc5e3375af344bea0c6 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 26 Feb 2025 15:26:21 -0500 Subject: [PATCH 04/72] Revert "disable ci" This reverts commit d66590221aba588edb8c7132d0df0e9681b8a1a3. --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c0b097a2b..399a419b2 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} -# smoketest: -# name: Build and smoke tests -# runs-on: ${{ matrix.os }} -# needs: [ style ] -# strategy: -# fail-fast: false -# matrix: -# os: [ ubuntu-latest, windows-latest ] -# python-version: [ '3.10', '3.11', '3.12', '3.13' ] -# steps: -# - name: Build wheelhouse -# uses: ansys/actions/build-wheelhouse@v8 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# operating-system: ${{ matrix.os }} -# python-version: ${{ matrix.python-version }} -# -# - name: Install library -# run: python --version && python -m pip install ${{ env.install_target }} -# -# - name: Run smoketest -# run: make smoketest + smoketest: + name: Build and smoke tests + runs-on: ${{ matrix.os }} + needs: [ style ] + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest ] + python-version: [ '3.10', '3.11', '3.12', '3.13' ] + steps: + - name: Build wheelhouse + uses: ansys/actions/build-wheelhouse@v8 + with: + library-name: ${{ env.PACKAGE_NAME }} + operating-system: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} + + - name: Install library + run: python --version && python -m pip install ${{ env.install_target }} + + - name: Run smoketest + run: make smoketest test: name: Testing -# needs: [ smoketest ] + needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index f8715eb86..ac2b21f47 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml test-dev: pip install -e .[test] From eb2515b1abe357d92261cce389a343214f7ec2ee Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 3 Apr 2025 13:55:34 -0400 Subject: [PATCH 05/72] Reapply "disable ci" This reverts commit a15845653f16f9adf0c81cc5e3375af344bea0c6. --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 399a419b2..c0b097a2b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} - smoketest: - name: Build and smoke tests - runs-on: ${{ matrix.os }} - needs: [ style ] - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, windows-latest ] - python-version: [ '3.10', '3.11', '3.12', '3.13' ] - steps: - - name: Build wheelhouse - uses: ansys/actions/build-wheelhouse@v8 - with: - library-name: ${{ env.PACKAGE_NAME }} - operating-system: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} - - - name: Install library - run: python --version && python -m pip install ${{ env.install_target }} - - - name: Run smoketest - run: make smoketest +# smoketest: +# name: Build and smoke tests +# runs-on: ${{ matrix.os }} +# needs: [ style ] +# strategy: +# fail-fast: false +# matrix: +# os: [ ubuntu-latest, windows-latest ] +# python-version: [ '3.10', '3.11', '3.12', '3.13' ] +# steps: +# - name: Build wheelhouse +# uses: ansys/actions/build-wheelhouse@v8 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# operating-system: ${{ matrix.os }} +# python-version: ${{ matrix.python-version }} +# +# - name: Install library +# run: python --version && python -m pip install ${{ env.install_target }} +# +# - name: Run smoketest +# run: make smoketest test: name: Testing - needs: [ smoketest ] +# needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index ac2b21f47..f8715eb86 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless test-dev: pip install -e .[test] From 5d7d687814ba1421c558e369104d68f3b50627d5 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 3 Apr 2025 16:05:20 -0400 Subject: [PATCH 06/72] fix population of dynamic props --- src/ansys/dynamicreporting/core/serverless/base.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index c8a34f53a..53588f5bb 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -75,13 +75,11 @@ def __new__( if parents: # dynamically make the properties listed into class attrs if "_properties" in namespace: - dynamic_props_field = namespace["_properties"] - if hasattr(dynamic_props_field, "default"): - props = dynamic_props_field.default - new_namespace = {**namespace} - for prop in props: - new_namespace[prop] = None - new_cls = super_new(mcs, cls_name, bases, new_namespace, **kwargs) + props = namespace["_properties"] + new_namespace = {**namespace} + for prop in props: + new_namespace[prop] = None + new_cls = super_new(mcs, cls_name, bases, new_namespace, **kwargs) # save every class extending BaseModel mcs._cls_registry[cls_name] = new_cls # add exceptions @@ -562,4 +560,4 @@ def __set__(self, obj, value): @abstractmethod def process(self, value, obj): - pass + pass # pragma: no cover From aa96b529ea0a558659914fb602c3e83997235389 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 3 Apr 2025 17:00:42 -0400 Subject: [PATCH 07/72] add InvalidFieldError --- src/ansys/dynamicreporting/core/exceptions.py | 6 ++++++ src/ansys/dynamicreporting/core/serverless/base.py | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/exceptions.py b/src/ansys/dynamicreporting/core/exceptions.py index 9261557fb..aaf9cd181 100644 --- a/src/ansys/dynamicreporting/core/exceptions.py +++ b/src/ansys/dynamicreporting/core/exceptions.py @@ -135,3 +135,9 @@ class IntegrityError(ADRException): """Exception raised if there is a constraint violation while saving an object in the database.""" detail = "A database integrity check failed." + + +class InvalidFieldError(ADRException): + """Exception raised if a field is not valid.""" + + detail = "Field is invalid." diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 53588f5bb..302a8ccba 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -25,6 +25,7 @@ from ..exceptions import ( ADRException, IntegrityError, + InvalidFieldError, MultipleObjectsReturnedError, ObjectDoesNotExistError, ObjectNotSavedError, @@ -44,7 +45,9 @@ def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except (FieldError, FieldDoesNotExist, ValidationError, DataError) as e: - raise ADRException(extra_detail=f"One or more fields set or accessed are invalid: {e}") + raise InvalidFieldError( + extra_detail=f"One or more fields set or accessed are invalid: {e}" + ) return wrapper From 89e8ad6c7f6d100394803e59a0ff7a907bbc1243 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 3 Apr 2025 17:01:14 -0400 Subject: [PATCH 08/72] update tests --- tests/serverless/test_item.py | 49 +++++++++++++++++++++++ tests/serverless/test_template.py | 65 +++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 71121ad07..ef9480aff 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1,5 +1,28 @@ import pytest +from src.ansys.dynamicreporting.core.exceptions import InvalidFieldError + + +@pytest.mark.ado_test +def test_field_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + with pytest.raises(InvalidFieldError): + assert HTML.get(lol=1) + + +@pytest.mark.ado_test +def test_field_type_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + with pytest.raises(TypeError): + HTML.create( + name=1, # error + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + @pytest.mark.ado_test def test_create_html_cls(adr_serverless): @@ -14,6 +37,32 @@ def test_create_html_cls(adr_serverless): assert HTML.get(name="test_create_html_cls").guid == intro_html.guid +@pytest.mark.ado_test +def test_str(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_str", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert str(intro_html) == f"" + + +@pytest.mark.ado_test +def test_repr(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_repr", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert repr(intro_html) == f"" + + @pytest.mark.ado_test def test_add_rem_tag(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index e69de29bb..eddf3b5d3 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -0,0 +1,65 @@ +import pytest + + +@pytest.mark.ado_test +def test_create_template_cls(adr_serverless): + from ansys.dynamicreporting.core.serverless import PanelLayout + + results_panel = PanelLayout.create(name="test_create_template_cls", tags="dp=dp227") + + assert PanelLayout.get(name="test_create_template_cls").guid == results_panel.guid + + +@pytest.mark.ado_test +def test_init_template_cls(adr_serverless): + from ansys.dynamicreporting.core.serverless import PanelLayout + + results_panel = PanelLayout(name="test_init_template_cls", tags="dp=dp227") + results_panel.save() + + assert PanelLayout.get(name="test_init_template_cls").guid == results_panel.guid + + +@pytest.mark.ado_test +def test_edit_template(adr_serverless): + # Templates/reports + from ansys.dynamicreporting.core.serverless import PanelLayout + + results_panel = PanelLayout.create(name="Results", tags="dp=dp227") + results_panel.params = ( + '{"HTML": "

Results

\\nYour simulation results.", "properties": {"TOCItem": "1"}}' + ) + results_panel.save() + + assert "Your simulation results" in PanelLayout.get(name="Results").params + + +@pytest.mark.ado_test +def test_raise_child_type_init(adr_serverless): + # Templates/reports + from ansys.dynamicreporting.core.serverless import BasicLayout + + with pytest.raises(TypeError): + BasicLayout( + name="test_raise_child_type_init", parent=None, tags="dp=dp227", children=["T1"] + ) + + +@pytest.mark.ado_test +def test_raise_child_type_create(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout + + with pytest.raises(TypeError): + BasicLayout.create( + name="test_raise_child_type_create", parent=None, tags="dp=dp227", children=["T1"] + ) + + +@pytest.mark.ado_test +def test_raise_child_type_save(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, PanelLayout + + with pytest.raises(TypeError): + top_parent = BasicLayout(name="Serverless Simulation Report", parent=None, tags="dp=dp227") + top_parent.children.append("T1") + top_parent.save() From 92129786c5fa2759a04029d12cfd5ab0efc1e7e4 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 3 Apr 2025 17:13:23 -0400 Subject: [PATCH 09/72] Update test_item.py --- tests/serverless/test_item.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index ef9480aff..42d2e326a 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1,10 +1,9 @@ import pytest -from src.ansys.dynamicreporting.core.exceptions import InvalidFieldError - @pytest.mark.ado_test def test_field_error(adr_serverless): + from ansys.dynamicreporting.core.exceptions import InvalidFieldError from ansys.dynamicreporting.core.serverless import HTML with pytest.raises(InvalidFieldError): From 2ff331d766a9db376b5b59969046d1a3ce5195c4 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 15:38:30 -0400 Subject: [PATCH 10/72] add recursive option for as_dict --- src/ansys/dynamicreporting/core/serverless/base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 302a8ccba..e02cb5236 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -267,7 +267,7 @@ def _orm_db(self) -> str: def db(self): return self._orm_db - def as_dict(self): + def as_dict(self, recursive=False) -> dict[str, Any]: out_dict = {} # use a combination of vars and fields cls_fields = set(self._get_field_names() + self._get_var_field_names()) @@ -277,6 +277,9 @@ def as_dict(self): value = getattr(self, field_, None) if value is None: # skip and use defaults continue + if isinstance(value, list) and recursive: + # convert to guids + value = [obj.guid for obj in value] out_dict[field_] = value return out_dict From 85c3731504fc5255b70d56baf2ef2088e219eb25 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 15:38:58 -0400 Subject: [PATCH 11/72] update tests for tags --- tests/serverless/test_item.py | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 42d2e326a..78627b3cc 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -63,11 +63,11 @@ def test_repr(adr_serverless): @pytest.mark.ado_test -def test_add_rem_tag(adr_serverless): +def test_add_tag(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML intro_html = HTML.create( - name="test_create_html_cls", + name="test_add_tag", content="

Heading 1

", session=adr_serverless.session, dataset=adr_serverless.dataset, @@ -77,11 +77,43 @@ def test_add_rem_tag(adr_serverless): assert "pptx_slide_title" in HTML.get(guid=intro_html.guid).get_tags() - intro_html.rem_tag("pptx_slide_title") - intro_html.remove_tag("pptx_slide_title") + +@pytest.mark.ado_test +def test_rem_tag(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_rem_tag", + content="

Heading 1

", + tags="tag1 tag2", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.rem_tag("tag1") + intro_html.remove_tag("tag2") + intro_html.save() + + tags = HTML.get(guid=intro_html.guid).get_tags() + assert "tag1" not in tags and "tag2" not in tags + + +@pytest.mark.ado_test +def test_rem_empty_tag(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_rem_empty_tag", + content="

Heading 1

", + tags="", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.rem_tag("tag1") + intro_html.remove_tag("tag2") intro_html.save() - assert "pptx_slide_title" not in HTML.get(guid=intro_html.guid).get_tags() + tags = HTML.get(guid=intro_html.guid).get_tags() + assert "tag1" not in tags and "tag2" not in tags @pytest.mark.ado_test From 42e65bd2e682ce6cf2009156cfa462214b243dd9 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 15:39:33 -0400 Subject: [PATCH 12/72] test for as_dict --- tests/serverless/test_template.py | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index eddf3b5d3..1bb4c9f82 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -25,13 +25,13 @@ def test_edit_template(adr_serverless): # Templates/reports from ansys.dynamicreporting.core.serverless import PanelLayout - results_panel = PanelLayout.create(name="Results", tags="dp=dp227") + results_panel = PanelLayout.create(name="test_edit_template", tags="dp=dp227") results_panel.params = ( '{"HTML": "

Results

\\nYour simulation results.", "properties": {"TOCItem": "1"}}' ) results_panel.save() - assert "Your simulation results" in PanelLayout.get(name="Results").params + assert "Your simulation results" in PanelLayout.get(name="test_edit_template").params @pytest.mark.ado_test @@ -63,3 +63,32 @@ def test_raise_child_type_save(adr_serverless): top_parent = BasicLayout(name="Serverless Simulation Report", parent=None, tags="dp=dp227") top_parent.children.append("T1") top_parent.save() + + +@pytest.mark.ado_test +def test_as_dict(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + top_parent = adr_serverless.create_template( + BasicLayout, + name="Serverless Simulation Report", + parent=None, + tags="dp=dp227", + params='{"HTML": "

Serverless Simulation Report

"}', + ) + + toc_layout = adr_serverless.create_template( + TOCLayout, name="TOC", parent=top_parent, tags="dp=dp227" + ) + toc_layout.params = '{"TOCitems": 1, "HTML": "

Table of Content

"}' + toc_layout.set_filter("A|i_name|eq|__NonexistentName__;") + toc_layout.save() + + top_dict = top_parent.as_dict(recursive=True) + + assert ( + top_dict["name"] == "Serverless Simulation Report" + and top_dict["tags"] == "dp=dp227" + and top_dict["params"] == '{"HTML": "

Serverless Simulation Report

"}' + and top_dict["children"][0]["name"] == "TOC" + ) From e4f7a6e808e7f9a037383d2c49b4bbd3f1b8c33f Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 15:44:26 -0400 Subject: [PATCH 13/72] Update test_template.py --- tests/serverless/test_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 1bb4c9f82..80050849d 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -90,5 +90,5 @@ def test_as_dict(adr_serverless): top_dict["name"] == "Serverless Simulation Report" and top_dict["tags"] == "dp=dp227" and top_dict["params"] == '{"HTML": "

Serverless Simulation Report

"}' - and top_dict["children"][0]["name"] == "TOC" + and top_dict["children"][0] == toc_layout.guid ) From 9143744ec57b15f8b8016844db4f98c25008577c Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 16:03:30 -0400 Subject: [PATCH 14/72] Update test_item.py --- tests/serverless/test_item.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 78627b3cc..9990c18ad 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -144,3 +144,18 @@ def test_get_tags(adr_serverless): dataset=adr_serverless.dataset, ) assert "dp=dp227" in HTML.get(guid=intro_html.guid).get_tags() + + +@pytest.mark.ado_test +def test_db(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_db", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + from django.conf import settings + + assert intro_html.db in settings.DATABASES From f5acd02014192008038edfbc82cf7e210750b1dc Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 16:03:36 -0400 Subject: [PATCH 15/72] Update conftest.py --- tests/serverless/conftest.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/serverless/conftest.py b/tests/serverless/conftest.py index a1e5de38c..ebc88aa01 100644 --- a/tests/serverless/conftest.py +++ b/tests/serverless/conftest.py @@ -4,7 +4,7 @@ import pytest from ansys.dynamicreporting.core.constants import DOCKER_DEV_REPO_URL -from ansys.dynamicreporting.core.serverless import ADR +from ansys.dynamicreporting.core.serverless import ADR, Item, Template @pytest.fixture(scope="session") @@ -39,3 +39,11 @@ def adr_serverless(pytestconfig: pytest.Config) -> ADR: # Cleanup adr.close() + + +@pytest.fixture(autouse=True, scope="function") +def teardown(adr_serverless): + yield + # delete all objects + adr_serverless.query(query_type=Item, query="") + adr_serverless.query(query_type=Template, query="") From bfa6b1a2103f8ddc2f53b1758841934dc8f65489 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 16:52:57 -0400 Subject: [PATCH 16/72] Update conftest.py --- tests/serverless/conftest.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/serverless/conftest.py b/tests/serverless/conftest.py index ebc88aa01..1ad693245 100644 --- a/tests/serverless/conftest.py +++ b/tests/serverless/conftest.py @@ -39,11 +39,3 @@ def adr_serverless(pytestconfig: pytest.Config) -> ADR: # Cleanup adr.close() - - -@pytest.fixture(autouse=True, scope="function") -def teardown(adr_serverless): - yield - # delete all objects - adr_serverless.query(query_type=Item, query="") - adr_serverless.query(query_type=Template, query="") From 85f4feb7199598b3a0b0d5a350b2ebc4374d755b Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 17:01:15 -0400 Subject: [PATCH 17/72] Update conftest.py --- tests/serverless/conftest.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/serverless/conftest.py b/tests/serverless/conftest.py index 1ad693245..8c2a59dea 100644 --- a/tests/serverless/conftest.py +++ b/tests/serverless/conftest.py @@ -39,3 +39,11 @@ def adr_serverless(pytestconfig: pytest.Config) -> ADR: # Cleanup adr.close() + + +@pytest.fixture(autouse=True, scope="function") +def teardown(adr_serverless): + yield + # delete all objects + adr_serverless.query(query_type=Item, query="").delete() + adr_serverless.query(query_type=Template, query="").delete() From cf9e68996e60039bed202a2939a933ca1924d364 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 18:15:00 -0400 Subject: [PATCH 18/72] Revert "Update conftest.py" This reverts commit 85f4feb7199598b3a0b0d5a350b2ebc4374d755b. --- tests/serverless/conftest.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/serverless/conftest.py b/tests/serverless/conftest.py index 8c2a59dea..1ad693245 100644 --- a/tests/serverless/conftest.py +++ b/tests/serverless/conftest.py @@ -39,11 +39,3 @@ def adr_serverless(pytestconfig: pytest.Config) -> ADR: # Cleanup adr.close() - - -@pytest.fixture(autouse=True, scope="function") -def teardown(adr_serverless): - yield - # delete all objects - adr_serverless.query(query_type=Item, query="").delete() - adr_serverless.query(query_type=Template, query="").delete() From 0b749fe29f0b432359805723673dca7de6cf1dea Mon Sep 17 00:00:00 2001 From: viseshrp Date: Fri, 4 Apr 2025 18:34:50 -0400 Subject: [PATCH 19/72] test for children temps --- .../dynamicreporting/core/serverless/base.py | 1 - .../core/serverless/template.py | 4 ++-- tests/serverless/test_template.py | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index e02cb5236..eaab861db 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -23,7 +23,6 @@ from django.db.utils import IntegrityError as DBIntegrityError from ..exceptions import ( - ADRException, IntegrityError, InvalidFieldError, MultipleObjectsReturnedError, diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index a1a08be05..32b316ab4 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -58,7 +58,7 @@ def master(self): return self._master def save(self, **kwargs): - if self.parent is not None and not self.parent._saved: + if self.parent is not None and not self.parent.saved: raise Template.NotSaved( extra_detail="Failed to save template because its parent is not saved" ) @@ -68,7 +68,7 @@ def save(self, **kwargs): raise TypeError( f"Failed to save template because child '{child}' is not a Template object" ) - if not child._saved: + if not child.saved: raise Template.NotSaved( extra_detail="Failed to save template because its children are not saved" ) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 80050849d..5d2556958 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -1,5 +1,7 @@ import pytest +from ansys.dynamicreporting.core.exceptions import ObjectDoesNotExist + @pytest.mark.ado_test def test_create_template_cls(adr_serverless): @@ -92,3 +94,21 @@ def test_as_dict(adr_serverless): and top_dict["params"] == '{"HTML": "

Serverless Simulation Report

"}' and top_dict["children"][0] == toc_layout.guid ) + + +@pytest.mark.ado_test +def test_child_not_exist(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + top_parent = adr_serverless.create_template( + BasicLayout, + name="Serverless Simulation Report", + parent=None, + tags="dp=dp227", + params='{"HTML": "

Serverless Simulation Report

"}', + ) + toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") + toc_layout._saved = True # fake save + top_parent.children.append(toc_layout) + with pytest.raises(ObjectDoesNotExist): + top_parent.save() From 1566ca0b7fd22080bfba1fc14cc059cf03d91646 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 12:18:53 -0400 Subject: [PATCH 20/72] Update test_template.py --- tests/serverless/test_template.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 5d2556958..a5bc56dd2 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -1,7 +1,5 @@ import pytest -from ansys.dynamicreporting.core.exceptions import ObjectDoesNotExist - @pytest.mark.ado_test def test_create_template_cls(adr_serverless): @@ -59,10 +57,10 @@ def test_raise_child_type_create(adr_serverless): @pytest.mark.ado_test def test_raise_child_type_save(adr_serverless): - from ansys.dynamicreporting.core.serverless import BasicLayout, PanelLayout + from ansys.dynamicreporting.core.serverless import BasicLayout with pytest.raises(TypeError): - top_parent = BasicLayout(name="Serverless Simulation Report", parent=None, tags="dp=dp227") + top_parent = BasicLayout(name="test_raise_child_type_save", parent=None, tags="dp=dp227") top_parent.children.append("T1") top_parent.save() @@ -73,7 +71,7 @@ def test_as_dict(adr_serverless): top_parent = adr_serverless.create_template( BasicLayout, - name="Serverless Simulation Report", + name="test_as_dict", parent=None, tags="dp=dp227", params='{"HTML": "

Serverless Simulation Report

"}', @@ -89,7 +87,7 @@ def test_as_dict(adr_serverless): top_dict = top_parent.as_dict(recursive=True) assert ( - top_dict["name"] == "Serverless Simulation Report" + top_dict["name"] == "test_as_dict" and top_dict["tags"] == "dp=dp227" and top_dict["params"] == '{"HTML": "

Serverless Simulation Report

"}' and top_dict["children"][0] == toc_layout.guid @@ -102,7 +100,7 @@ def test_child_not_exist(adr_serverless): top_parent = adr_serverless.create_template( BasicLayout, - name="Serverless Simulation Report", + name="test_child_not_exist", parent=None, tags="dp=dp227", params='{"HTML": "

Serverless Simulation Report

"}', @@ -110,5 +108,5 @@ def test_child_not_exist(adr_serverless): toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") toc_layout._saved = True # fake save top_parent.children.append(toc_layout) - with pytest.raises(ObjectDoesNotExist): + with pytest.raises(BasicLayout.DoesNotExist): top_parent.save() From 7143bdfcc6b18f3cbeeb7d8d5a36c41dbe3644de Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:06:27 -0400 Subject: [PATCH 21/72] Update test_template.py --- tests/serverless/test_template.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index a5bc56dd2..694714674 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -95,18 +95,17 @@ def test_as_dict(adr_serverless): @pytest.mark.ado_test -def test_child_not_exist(adr_serverless): +def test_child_not_saved(adr_serverless): from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout top_parent = adr_serverless.create_template( BasicLayout, - name="test_child_not_exist", + name="test_child_not_saved", parent=None, tags="dp=dp227", params='{"HTML": "

Serverless Simulation Report

"}', ) toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") - toc_layout._saved = True # fake save top_parent.children.append(toc_layout) - with pytest.raises(BasicLayout.DoesNotExist): + with pytest.raises(BasicLayout.NotSaved): top_parent.save() From 021e4194156720a85857847005825543059809aa Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:11:45 -0400 Subject: [PATCH 22/72] Update template.py --- src/ansys/dynamicreporting/core/serverless/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index 32b316ab4..0c52dd56c 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -59,7 +59,7 @@ def master(self): def save(self, **kwargs): if self.parent is not None and not self.parent.saved: - raise Template.NotSaved( + raise self.__class__.NotSaved( extra_detail="Failed to save template because its parent is not saved" ) children_order = [] @@ -69,7 +69,7 @@ def save(self, **kwargs): f"Failed to save template because child '{child}' is not a Template object" ) if not child.saved: - raise Template.NotSaved( + raise self.__class__.NotSaved( extra_detail="Failed to save template because its children are not saved" ) children_order.append(child.guid) From cf8a7ee6cfb22150424f04b2d51fba73618609c1 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:48:37 -0400 Subject: [PATCH 23/72] more error handling for base save method --- src/ansys/dynamicreporting/core/serverless/base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index eaab861db..431167778 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -296,7 +296,14 @@ def _prepare_for_save(self, **kwargs): continue if isinstance(value, list): objs = [obj._orm_instance for obj in value] - getattr(self._orm_instance, field_).add(*objs) + try: + getattr(self._orm_instance, field_).add(*objs) + except (ObjectDoesNotExist, ValueError) as e: + if objs: + obj_cls = objs[0].__class__ + raise obj_cls.NotSaved(extra_detail=str(e)) + else: + raise ValueError(str(e)) else: if isinstance(value, BaseModel): # relations try: From d17df437fccdc33a476a0540ad143a086c721c80 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:48:59 -0400 Subject: [PATCH 24/72] right exception types for template save --- src/ansys/dynamicreporting/core/serverless/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index 0c52dd56c..c412bcefd 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -59,7 +59,7 @@ def master(self): def save(self, **kwargs): if self.parent is not None and not self.parent.saved: - raise self.__class__.NotSaved( + raise self.parent.__class__.NotSaved( extra_detail="Failed to save template because its parent is not saved" ) children_order = [] @@ -69,7 +69,7 @@ def save(self, **kwargs): f"Failed to save template because child '{child}' is not a Template object" ) if not child.saved: - raise self.__class__.NotSaved( + raise child.__class__.NotSaved( extra_detail="Failed to save template because its children are not saved" ) children_order.append(child.guid) From d568c06108cfd93aa3de64d760011277239ebb66 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:49:29 -0400 Subject: [PATCH 25/72] Update test_template.py --- tests/serverless/test_template.py | 60 ++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 694714674..d2cfe378c 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -1,5 +1,7 @@ import pytest +from src.ansys.dynamicreporting.core.serverless.template import BasicLayout + @pytest.mark.ado_test def test_create_template_cls(adr_serverless): @@ -94,6 +96,44 @@ def test_as_dict(adr_serverless): ) +@pytest.mark.ado_test +def test_parent_not_saved(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + top_parent = BasicLayout( + name="test_parent_not_saved", + parent=None, + tags="dp=dp227", + params='{"HTML": "

Serverless Simulation Report

"}', + ) + toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") + with pytest.raises(BasicLayout.NotSaved): + toc_layout.save() + + +@pytest.mark.ado_test +def test_child_bad_type(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML, BasicLayout + + top_parent = adr_serverless.create_template( + BasicLayout, + name="test_child_bad_type", + parent=None, + tags="dp=dp227", + params='{"HTML": "

Serverless Simulation Report

"}', + ) + # Wrong type of child + toc_layout = HTML.create( + name="test_child_bad_type_item", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + top_parent.children.append(toc_layout) + with pytest.raises(TypeError): + top_parent.save() + + @pytest.mark.ado_test def test_child_not_saved(adr_serverless): from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout @@ -107,5 +147,23 @@ def test_child_not_saved(adr_serverless): ) toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") top_parent.children.append(toc_layout) - with pytest.raises(BasicLayout.NotSaved): + with pytest.raises(TOCLayout.NotSaved): top_parent.save() + + +@pytest.mark.ado_test +def test_child_not_exist(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + top_parent = adr_serverless.create_template( + BasicLayout, + name="test_child_not_exist", + parent=None, + tags="dp=dp227", + params='{"HTML": "

Serverless Simulation Report

"}', + ) + toc_layout = TOCLayout(name="TOC", parent=top_parent, tags="dp=dp227") + toc_layout._saved = True # Simulate that the child is saved, but does not exist in the database + top_parent.children.append(toc_layout) + with pytest.raises(TOCLayout.NotSaved): + toc_layout.save() From 4ddef2613780a4fbc579a60e312f701347c1878f Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 16:54:48 -0400 Subject: [PATCH 26/72] Update test_template.py --- tests/serverless/test_template.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index d2cfe378c..0c526b125 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -1,7 +1,5 @@ import pytest -from src.ansys.dynamicreporting.core.serverless.template import BasicLayout - @pytest.mark.ado_test def test_create_template_cls(adr_serverless): From af6f95e44185d09c1dcb4048d982239bce9cfa46 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 17:03:38 -0400 Subject: [PATCH 27/72] Update test_template.py --- tests/serverless/test_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 0c526b125..1c9f9a69c 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -164,4 +164,4 @@ def test_child_not_exist(adr_serverless): toc_layout._saved = True # Simulate that the child is saved, but does not exist in the database top_parent.children.append(toc_layout) with pytest.raises(TOCLayout.NotSaved): - toc_layout.save() + top_parent.save() From 19b6f228b2a546457c6b0bbcc8a2f299eeac2228 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 17:10:19 -0400 Subject: [PATCH 28/72] Update base.py --- src/ansys/dynamicreporting/core/serverless/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 431167778..9696d7b39 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -299,8 +299,8 @@ def _prepare_for_save(self, **kwargs): try: getattr(self._orm_instance, field_).add(*objs) except (ObjectDoesNotExist, ValueError) as e: - if objs: - obj_cls = objs[0].__class__ + if value: + obj_cls = value[0].__class__ raise obj_cls.NotSaved(extra_detail=str(e)) else: raise ValueError(str(e)) From 2167ce2d9c6cc818dd7f2042c0950a0315c7e9ba Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 17:13:55 -0400 Subject: [PATCH 29/72] Update test_item.py --- tests/serverless/test_item.py | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 9990c18ad..e9d64bcfe 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -137,7 +137,7 @@ def test_get_tags(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML intro_html = HTML.create( - name="test_set_tags", + name="test_get_tags", tags="dp=dp227", content="

Heading 1

", session=adr_serverless.session, @@ -159,3 +159,51 @@ def test_db(adr_serverless): from django.conf import settings assert intro_html.db in settings.DATABASES + + +@pytest.mark.ado_test +def test_reinit(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_reinit", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.reinit() + assert intro_html.saved is False + + +@pytest.mark.ado_test +def test_integrity_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_integrity_error", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(HTML.IntegrityError): + HTML.create( + guid=intro_html.guid, + name="test_integrity_error", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + + +@pytest.mark.ado_test +def test_delete_not_saved(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML( + name="test_delete_not_saved", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(HTML.NotSaved): + intro_html.delete() From 6c7a3a84fdc5d6864a9eac5e27a385c7f25e518d Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 17:48:35 -0400 Subject: [PATCH 30/72] fix get_or_create --- src/ansys/dynamicreporting/core/serverless/base.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 9696d7b39..1cbbfbdc4 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -443,15 +443,7 @@ def get_or_create(cls, **kwargs): try: return cls.get(**kwargs), False except cls.DoesNotExist: - # Try to create an object using passed params. - try: - return cls.create(**kwargs), True - except cls.IntegrityError: - try: - return cls.get(**kwargs), False - except cls.DoesNotExist: - pass - raise + return cls.create(**kwargs), True @classmethod @handle_field_errors From 8fcfbe1c439a11bc4b88e394832d986e43128afd Mon Sep 17 00:00:00 2001 From: viseshrp Date: Mon, 7 Apr 2025 17:55:45 -0400 Subject: [PATCH 31/72] Update test_item.py --- tests/serverless/test_item.py | 85 ++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index e9d64bcfe..e960578cd 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -72,12 +72,28 @@ def test_add_tag(adr_serverless): session=adr_serverless.session, dataset=adr_serverless.dataset, ) - intro_html.add_tag("pptx_slide_title", "headers and breaks") + intro_html.add_tag("pptx_slide_title", value="headers and breaks") intro_html.save() assert "pptx_slide_title" in HTML.get(guid=intro_html.guid).get_tags() +@pytest.mark.ado_test +def test_add_tag_key(adr_serverless): + from ansys.dynamicreporting.core.serverless import String + + intro_text = String( + name="intro_text", + content="intro text", + tags="dp=dp227 section=intro", + source="sls-test", + ) + intro_text.add_tag("sls-test") + intro_text.save() + + assert "sls-test" in String.get(guid=intro_text.guid).tags + + @pytest.mark.ado_test def test_rem_tag(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML @@ -207,3 +223,70 @@ def test_delete_not_saved(adr_serverless): ) with pytest.raises(HTML.NotSaved): intro_html.delete() + + +@pytest.mark.ado_test +def test_get_item(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_get_item", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + item = HTML.get(guid=intro_html.guid) + assert item.guid == intro_html.guid + + +@pytest.mark.ado_test +def test_get_item_does_not_exist(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + with pytest.raises(HTML.DoesNotExist): + HTML.get(guid="non_existent_guid") + + +@pytest.mark.ado_test +def test_get_item_multiple(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + HTML.create( + name="test_get_item_multiple", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + HTML( + name="test_get_item_multiple", + content="

Heading 2

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(HTML.MultipleObjectsReturned): + HTML.get(name="test_get_item_multiple") + + +@pytest.mark.ado_test +def test_get_or_create_item(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + # tree + tree_content = [ + {"key": "root", "name": "Solver", "value": "My Solver"}, + {"key": "root", "name": "Number cells", "value": 10e6}, + {"key": "root", "name": "Mesh Size", "value": "1.0 mm^3"}, + {"key": "root", "name": "Mesh Type", "value": "Hex8"}, + ] + # alternative way of creation + tree_kwargs = { + "name": "intro_tree", + "content": tree_content, + "tags": "dp=dp227 section=data", + "session": adr_serverless.session, + "dataset": adr_serverless.dataset, + "source": "sls-test", + } + tree = Tree.get_or_create(**tree_kwargs) + new_tree = Tree.get_or_create(**tree_kwargs) + assert new_tree.guid == tree.guid From 3456a5bff5c4523ae10529583f8723357aad98ac Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 16:12:45 -0400 Subject: [PATCH 32/72] Update test_item.py --- tests/serverless/test_item.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index e960578cd..7fa627304 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1,3 +1,5 @@ +from uuid import uuid4 + import pytest @@ -87,6 +89,8 @@ def test_add_tag_key(adr_serverless): content="intro text", tags="dp=dp227 section=intro", source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, ) intro_text.add_tag("sls-test") intro_text.save() @@ -244,7 +248,7 @@ def test_get_item_does_not_exist(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML with pytest.raises(HTML.DoesNotExist): - HTML.get(guid="non_existent_guid") + HTML.get(guid=str(uuid4())) @pytest.mark.ado_test @@ -262,7 +266,7 @@ def test_get_item_multiple(adr_serverless): content="

Heading 2

", session=adr_serverless.session, dataset=adr_serverless.dataset, - ) + ).save() with pytest.raises(HTML.MultipleObjectsReturned): HTML.get(name="test_get_item_multiple") @@ -281,7 +285,6 @@ def test_get_or_create_item(adr_serverless): # alternative way of creation tree_kwargs = { "name": "intro_tree", - "content": tree_content, "tags": "dp=dp227 section=data", "session": adr_serverless.session, "dataset": adr_serverless.dataset, From 3c9cee9995e1be0ceb78687a187272feebe2078a Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 16:15:37 -0400 Subject: [PATCH 33/72] Update test_item.py --- tests/serverless/test_item.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 7fa627304..3ae6fcd68 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -275,13 +275,6 @@ def test_get_item_multiple(adr_serverless): def test_get_or_create_item(adr_serverless): from ansys.dynamicreporting.core.serverless import Tree - # tree - tree_content = [ - {"key": "root", "name": "Solver", "value": "My Solver"}, - {"key": "root", "name": "Number cells", "value": 10e6}, - {"key": "root", "name": "Mesh Size", "value": "1.0 mm^3"}, - {"key": "root", "name": "Mesh Type", "value": "Hex8"}, - ] # alternative way of creation tree_kwargs = { "name": "intro_tree", From b3c29640cac02b1f0cfbabb98b3ee83c4956eca7 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:13:01 -0400 Subject: [PATCH 34/72] handle basemodel instances in get --- .../dynamicreporting/core/serverless/base.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 1cbbfbdc4..c7ba8366e 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -426,6 +426,11 @@ def create(cls, **kwargs): @classmethod @handle_field_errors def get(cls, **kwargs): + """Get an object from the database using the ORM model.""" + # convert basemodel instances to orm instances + for key, value in kwargs.items(): + if isinstance(value, BaseModel): + kwargs[key] = value._orm_instance try: orm_instance = cls._orm_model_cls.objects.using(kwargs.pop("using", "default")).get( **kwargs @@ -439,7 +444,7 @@ def get(cls, **kwargs): @classmethod @handle_field_errors - def get_or_create(cls, **kwargs): + def get_or_create(cls, **kwargs) -> tuple["BaseModel", bool]: try: return cls.get(**kwargs), False except cls.DoesNotExist: @@ -447,23 +452,23 @@ def get_or_create(cls, **kwargs): @classmethod @handle_field_errors - def filter(cls, **kwargs): + def filter(cls, **kwargs) -> "ObjectSet": qs = cls._orm_model_cls.objects.using(kwargs.pop("using", "default")).filter(**kwargs) return ObjectSet(_model=cls, _orm_model=cls._orm_model_cls, _orm_queryset=qs) @classmethod @handle_field_errors - def find(cls, query="", **kwargs): + def find(cls, query="", **kwargs) -> "ObjectSet": qs = cls._orm_model_cls.find(query=query, **kwargs) return ObjectSet(_model=cls, _orm_model=cls._orm_model_cls, _orm_queryset=qs) - def get_tags(self): + def get_tags(self) -> str: return self.tags - def set_tags(self, tag_str): + def set_tags(self, tag_str: str) -> None: self.tags = tag_str - def add_tag(self, tag, value=None): + def add_tag(self, tag: str, value: str | None = None) -> None: self.rem_tag(tag) tags = shlex.split(self.get_tags()) if value: @@ -472,14 +477,14 @@ def add_tag(self, tag, value=None): tags.append(tag) self._rebuild_tags(tags) - def rem_tag(self, tag): + def rem_tag(self, tag: str) -> None: tags = shlex.split(self.get_tags()) for t in tags: if t == tag or t.split("=")[0] == tag: tags.remove(t) self._rebuild_tags(tags) - def remove_tag(self, tag): + def remove_tag(self, tag: str) -> None: self.rem_tag(tag) From 2c54707c38d80026d4aa592a245d30ffcf29197e Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:13:17 -0400 Subject: [PATCH 35/72] dont allow content kwarg in some --- .../dynamicreporting/core/serverless/item.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 6d3958ebc..6a1a65e99 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -311,20 +311,23 @@ def create(cls, **kwargs): new_kwargs = {"type": cls.type, **kwargs} return super().create(**new_kwargs) + @classmethod + def _validate_kwargs(cls, **kwargs): + if "content" in kwargs: + raise ValueError("'content' kwarg is not supported for get* and filter methods") + return {"type": cls.type, **kwargs} if cls.type != "none" else kwargs + @classmethod def get(cls, **kwargs): - new_kwargs = {"type": cls.type, **kwargs} if cls.type != "none" else kwargs - return super().get(**new_kwargs) + return super().get(**cls._validate_kwargs(**kwargs)) @classmethod def get_or_create(cls, **kwargs): - new_kwargs = {"type": cls.type, **kwargs} if cls.type != "none" else kwargs - return super().get_or_create(**new_kwargs) + return super().get_or_create(**cls._validate_kwargs(**kwargs)) @classmethod def filter(cls, **kwargs): - new_kwargs = {"type": cls.type, **kwargs} if cls.type != "none" else kwargs - return super().filter(**new_kwargs) + return super().filter(**cls._validate_kwargs(**kwargs)) @classmethod def find(cls, query="", **kwargs): From fa8a2f2dc81b77a99329537fd8f82e5502ef239f Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:13:46 -0400 Subject: [PATCH 36/72] dont allow children kwarg in some --- .../core/serverless/template.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index c412bcefd..334463ed8 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -16,11 +16,11 @@ class Template(BaseModel): item_filter: str = field(compare=False, kw_only=True, default="") parent: "Template" = field(compare=False, kw_only=True, default=None) children: list["Template"] = field(compare=False, kw_only=True, default_factory=list) + report_type: str = "" _children_order: str = field( compare=False, init=False, default="" ) # computed from self.children _master: bool = field(compare=False, init=False, default=True) - report_type: str = "" _properties: tuple = tuple() # todo: add properties of each type ref: report_objects _orm_model: str = "reports.models.Template" # Class-level registry of subclasses keyed by type @@ -121,20 +121,23 @@ def create(cls, **kwargs): new_kwargs = {"report_type": cls.report_type, **kwargs} return super().create(**new_kwargs) + @classmethod + def _validate_kwargs(cls, **kwargs): + if "children" in kwargs: + raise ValueError("'children' kwarg is not supported for get* and filter methods") + return {"report_type": cls.report_type, **kwargs} if cls.report_type else kwargs + @classmethod def get(cls, **kwargs): - new_kwargs = {"report_type": cls.report_type, **kwargs} if cls.report_type else kwargs - return super().get(**new_kwargs) + return super().get(**cls._validate_kwargs(**kwargs)) @classmethod def get_or_create(cls, **kwargs): - new_kwargs = {"report_type": cls.report_type, **kwargs} if cls.report_type else kwargs - return super().get_or_create(**new_kwargs) + return super().get_or_create(**cls._validate_kwargs(**kwargs)) @classmethod def filter(cls, **kwargs): - new_kwargs = {"report_type": cls.report_type, **kwargs} if cls.report_type else kwargs - return super().filter(**new_kwargs) + return super().filter(**cls._validate_kwargs(**kwargs)) @classmethod def find(cls, query="", **kwargs): From f3c4b32c892a6f72fc87b99e81c917a88cd5fdd1 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:14:10 -0400 Subject: [PATCH 37/72] update tests --- tests/serverless/test_item.py | 29 ++++++++++++++++++++++--- tests/serverless/test_template.py | 36 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 3ae6fcd68..22477a297 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -275,7 +275,7 @@ def test_get_item_multiple(adr_serverless): def test_get_or_create_item(adr_serverless): from ansys.dynamicreporting.core.serverless import Tree - # alternative way of creation + # tree tree_kwargs = { "name": "intro_tree", "tags": "dp=dp227 section=data", @@ -283,6 +283,29 @@ def test_get_or_create_item(adr_serverless): "dataset": adr_serverless.dataset, "source": "sls-test", } - tree = Tree.get_or_create(**tree_kwargs) - new_tree = Tree.get_or_create(**tree_kwargs) + tree, _ = Tree.get_or_create(**tree_kwargs) + new_tree, _ = Tree.get_or_create(**tree_kwargs) assert new_tree.guid == tree.guid + + +@pytest.mark.ado_test +def test_get_or_create_item_w_content(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = [ + {"key": "root", "name": "Solver", "value": "My Solver"}, + {"key": "root", "name": "Number cells", "value": 10e6}, + {"key": "root", "name": "Mesh Size", "value": "1.0 mm^3"}, + {"key": "root", "name": "Mesh Type", "value": "Hex8"}, + ] + # tree + tree_kwargs = { + "name": "intro_tree", + "content": tree_content, + "tags": "dp=dp227 section=data", + "session": adr_serverless.session, + "dataset": adr_serverless.dataset, + "source": "sls-test", + } + with pytest.raises(ValueError): + Tree.get_or_create(**tree_kwargs) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 1c9f9a69c..815b1ad93 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -165,3 +165,39 @@ def test_child_not_exist(adr_serverless): top_parent.children.append(toc_layout) with pytest.raises(TOCLayout.NotSaved): top_parent.save() + + +@pytest.mark.ado_test +def test_get_or_create_template(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout + + template_kwargs = { + "name": "test_get_or_create_template", + "parent": None, + "tags": "dp=dp227", + "params": '{"HTML": "

Serverless Simulation Report

"}', + } + + # Create a template + template = BasicLayout.create(**template_kwargs) + + # Get or create the same template + same_template = BasicLayout.get_or_create(**template_kwargs) + assert template.guid == same_template.guid + + +@pytest.mark.ado_test +def test_get_or_create_template_w_children(adr_serverless): + from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout + + toc_layout = TOCLayout.create(name="TOC", parent=top_parent, tags="dp=dp227") + # Shared kwargs + template_kwargs = { + "name": "test_get_or_create_template_w_children", + "parent": None, + "children": [toc_layout], + "tags": "dp=dp227", + "params": '{"HTML": "

Serverless Simulation Report

"}', + } + with pytest.raises(ValueError): + BasicLayout.get_or_create(**template_kwargs) From 423a13ee8d03cfb56021219924b832604df57b77 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:35:01 -0400 Subject: [PATCH 38/72] Update test_template.py --- tests/serverless/test_template.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 815b1ad93..9c12e67c9 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -190,14 +190,18 @@ def test_get_or_create_template(adr_serverless): def test_get_or_create_template_w_children(adr_serverless): from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout - toc_layout = TOCLayout.create(name="TOC", parent=top_parent, tags="dp=dp227") - # Shared kwargs template_kwargs = { "name": "test_get_or_create_template_w_children", "parent": None, - "children": [toc_layout], "tags": "dp=dp227", "params": '{"HTML": "

Serverless Simulation Report

"}', } + top_parent = adr_serverless.create_template( + BasicLayout, + **template_kwargs, + ) + toc_layout = adr_serverless.create_template( + TOCLayout, name="TOC", parent=top_parent, tags="dp=dp227" + ) with pytest.raises(ValueError): - BasicLayout.get_or_create(**template_kwargs) + BasicLayout.get_or_create(**template_kwargs, children=[toc_layout]) From 6e12c1ea46c45100d8a80960aff11496293913bd Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 17:41:18 -0400 Subject: [PATCH 39/72] update tests --- tests/serverless/test_item.py | 1 - tests/serverless/test_template.py | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 22477a297..d8f748779 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -275,7 +275,6 @@ def test_get_item_multiple(adr_serverless): def test_get_or_create_item(adr_serverless): from ansys.dynamicreporting.core.serverless import Tree - # tree tree_kwargs = { "name": "intro_tree", "tags": "dp=dp227 section=data", diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 9c12e67c9..7ab67906f 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -177,12 +177,8 @@ def test_get_or_create_template(adr_serverless): "tags": "dp=dp227", "params": '{"HTML": "

Serverless Simulation Report

"}', } - - # Create a template template = BasicLayout.create(**template_kwargs) - - # Get or create the same template - same_template = BasicLayout.get_or_create(**template_kwargs) + same_template, _ = BasicLayout.get_or_create(**template_kwargs) assert template.guid == same_template.guid From 46293ee74071e81038ad046de3dd889840c7c7fb Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 18:03:11 -0400 Subject: [PATCH 40/72] change ObjectSet.values_list --- src/ansys/dynamicreporting/core/serverless/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index c7ba8366e..e2e3861bd 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -539,8 +539,8 @@ def delete(self): def values_list(self, *fields, flat=False): if flat and len(fields) > 1: - raise TypeError( - "'flat' is not valid when values_list is called with more than one " "field." + raise ValueError( + "'flat' is not valid when values_list is called with more than one field." ) ret = [] for obj in self._obj_set: From 7ee47b21d0bf6ad56573144c19734afa8e328f90 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 18:03:27 -0400 Subject: [PATCH 41/72] add tests for ObjectSet --- tests/serverless/test_item.py | 112 ++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index d8f748779..824741172 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1,3 +1,4 @@ +from pathlib import Path from uuid import uuid4 import pytest @@ -105,7 +106,7 @@ def test_rem_tag(adr_serverless): intro_html = HTML.create( name="test_rem_tag", content="

Heading 1

", - tags="tag1 tag2", + tags="tag1=1 tag2", session=adr_serverless.session, dataset=adr_serverless.dataset, ) @@ -277,10 +278,10 @@ def test_get_or_create_item(adr_serverless): tree_kwargs = { "name": "intro_tree", - "tags": "dp=dp227 section=data", + "source": "sls-test", + "tags": "dp=dp227", "session": adr_serverless.session, "dataset": adr_serverless.dataset, - "source": "sls-test", } tree, _ = Tree.get_or_create(**tree_kwargs) new_tree, _ = Tree.get_or_create(**tree_kwargs) @@ -301,10 +302,111 @@ def test_get_or_create_item_w_content(adr_serverless): tree_kwargs = { "name": "intro_tree", "content": tree_content, - "tags": "dp=dp227 section=data", + "source": "sls-test", + "tags": "dp=dp227", "session": adr_serverless.session, "dataset": adr_serverless.dataset, - "source": "sls-test", } with pytest.raises(ValueError): Tree.get_or_create(**tree_kwargs) + + +@pytest.mark.ado_test +def test_item_objectset_repr(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_objectset_repr", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query(query_type=HTML, query="A|i_name|cont|test_item_objectset_repr;") + assert repr(objs) == f"]>" + + +@pytest.mark.ado_test +def test_item_objectset_str(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_objectset_str", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query(query_type=HTML, query="A|i_name|cont|test_item_objectset_str;") + assert str(objs) == f"[]" + + +@pytest.mark.ado_test +def test_item_objectset_getitem(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_objectset_getitem", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query(query_type=HTML, query="A|i_name|cont|test_item_objectset_getitem;") + assert objs[0].guid == intro_html.guid + + +@pytest.mark.ado_test +def test_item_objectset_saved(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + HTML.create( + name="test_item_objectset_saved", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query(query_type=HTML, query="A|i_name|cont|test_item_objectset_saved;") + assert objs.saved is True + + +@pytest.mark.ado_test +def test_item_objectset_values_list(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + HTML.create( + name="test_item_objectset_values_list", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query( + query_type=HTML, query="A|i_name|cont|test_item_objectset_values_list;" + ) + assert objs.values_list("name") == ["test_item_objectset_values_list"] + + +@pytest.mark.ado_test +def test_item_objectset_values_list_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + HTML.create( + name="test_item_objectset_values_list_error", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query( + query_type=HTML, query="A|i_name|cont|test_item_objectset_values_list_error;" + ) + with pytest.raises(ValueError): + objs.values_list("name", "guid", flat=True) From 759b641f1af9afd0467b7f9d8c3875006d361af9 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 18:08:57 -0400 Subject: [PATCH 42/72] Update test_item.py --- tests/serverless/test_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 824741172..8f60803c4 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -390,7 +390,7 @@ def test_item_objectset_values_list(adr_serverless): objs = adr_serverless.query( query_type=HTML, query="A|i_name|cont|test_item_objectset_values_list;" ) - assert objs.values_list("name") == ["test_item_objectset_values_list"] + assert objs.values_list("name", flat=True) == ["test_item_objectset_values_list"] @pytest.mark.ado_test From d154f1ed069e932b783102289dc66be66cf40d16 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 18:19:46 -0400 Subject: [PATCH 43/72] Revert "Reapply "disable ci"" This reverts commit eb2515b1abe357d92261cce389a343214f7ec2ee. --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c0b097a2b..399a419b2 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} -# smoketest: -# name: Build and smoke tests -# runs-on: ${{ matrix.os }} -# needs: [ style ] -# strategy: -# fail-fast: false -# matrix: -# os: [ ubuntu-latest, windows-latest ] -# python-version: [ '3.10', '3.11', '3.12', '3.13' ] -# steps: -# - name: Build wheelhouse -# uses: ansys/actions/build-wheelhouse@v8 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# operating-system: ${{ matrix.os }} -# python-version: ${{ matrix.python-version }} -# -# - name: Install library -# run: python --version && python -m pip install ${{ env.install_target }} -# -# - name: Run smoketest -# run: make smoketest + smoketest: + name: Build and smoke tests + runs-on: ${{ matrix.os }} + needs: [ style ] + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest ] + python-version: [ '3.10', '3.11', '3.12', '3.13' ] + steps: + - name: Build wheelhouse + uses: ansys/actions/build-wheelhouse@v8 + with: + library-name: ${{ env.PACKAGE_NAME }} + operating-system: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} + + - name: Install library + run: python --version && python -m pip install ${{ env.install_target }} + + - name: Run smoketest + run: make smoketest test: name: Testing -# needs: [ smoketest ] + needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index f8715eb86..ac2b21f47 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml test-dev: pip install -e .[test] From d91f15723f66c75a2b125e32a3a7cd2be01fb3bd Mon Sep 17 00:00:00 2001 From: viseshrp Date: Tue, 8 Apr 2025 18:20:45 -0400 Subject: [PATCH 44/72] Reapply disable ci This reverts commit d154f1ed069e932b783102289dc66be66cf40d16. --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 399a419b2..c0b097a2b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} - smoketest: - name: Build and smoke tests - runs-on: ${{ matrix.os }} - needs: [ style ] - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, windows-latest ] - python-version: [ '3.10', '3.11', '3.12', '3.13' ] - steps: - - name: Build wheelhouse - uses: ansys/actions/build-wheelhouse@v8 - with: - library-name: ${{ env.PACKAGE_NAME }} - operating-system: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} - - - name: Install library - run: python --version && python -m pip install ${{ env.install_target }} - - - name: Run smoketest - run: make smoketest +# smoketest: +# name: Build and smoke tests +# runs-on: ${{ matrix.os }} +# needs: [ style ] +# strategy: +# fail-fast: false +# matrix: +# os: [ ubuntu-latest, windows-latest ] +# python-version: [ '3.10', '3.11', '3.12', '3.13' ] +# steps: +# - name: Build wheelhouse +# uses: ansys/actions/build-wheelhouse@v8 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# operating-system: ${{ matrix.os }} +# python-version: ${{ matrix.python-version }} +# +# - name: Install library +# run: python --version && python -m pip install ${{ env.install_target }} +# +# - name: Run smoketest +# run: make smoketest test: name: Testing - needs: [ smoketest ] +# needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index ac2b21f47..f8715eb86 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless test-dev: pip install -e .[test] From 419ed5a820b6a07d00c61f55ca5f13021ec025da Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 13:06:35 -0400 Subject: [PATCH 45/72] tests for tables --- tests/serverless/test_item.py | 110 ++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 8f60803c4..b6838ed65 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -410,3 +410,113 @@ def test_item_objectset_values_list_error(adr_serverless): ) with pytest.raises(ValueError): objs.values_list("name", "guid", flat=True) + + +@pytest.mark.ado_test +def test_item_objectset_values_list_empty(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + objs = adr_serverless.query( + query_type=HTML, query="A|i_name|cont|test_item_objectset_values_list_empty;" + ) + assert objs.values_list("name", flat=True) == [] + + +@pytest.mark.ado_test +def test_string_content_none(adr_serverless): + from ansys.dynamicreporting.core.serverless import String + + string = String( + name="test_string_content_none", + content=None, + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(ValueError): + string.save() + + +@pytest.mark.ado_test +def test_string_content_wrong_type(adr_serverless): + from ansys.dynamicreporting.core.serverless import String + + string = String( + name="test_string_content_wrong_type", + content=1, + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(TypeError): + string.save() + + +@pytest.mark.ado_test +def test_string_content_empty(adr_serverless): + from ansys.dynamicreporting.core.serverless import String + + string = String( + name="test_string_content_empty", + content="", + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + string.save() + assert String.get(guid=string.guid).content == "" + + +@pytest.mark.ado_test +def test_table_content_not_numpy(adr_serverless): + from ansys.dynamicreporting.core.serverless import Table + + table = Table( + name="test_table_content_not_numpy", + content="", + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(TypeError): + table.save() + + +@pytest.mark.ado_test +def test_table_content_invalid_dtype(adr_serverless): + import numpy as np + + from ansys.dynamicreporting.core.serverless import Table + + table = Table( + name="test_table_content_invalid_dtype", + content=np.array([[1, 2], [3, 4]], dtype=int), # Invalid dtype + session=adr_serverless.session, + tags="dp=dp227", + source="sls-test", + dataset=adr_serverless.dataset, + ) + with pytest.raises(TypeError): + table.save() + + +@pytest.mark.ado_test +def test_table_content_invalid_shape(adr_serverless): + import numpy as np + + from ansys.dynamicreporting.core.serverless import Table + + table = Table( + name="test_table_content_invalid_shape", + content=np.array([1, 2, 3], dtype="|S20"), # Invalid shape (1D array instead of 2D) + session=adr_serverless.session, + tags="dp=dp227", + source="sls-test", + dataset=adr_serverless.dataset, + ) + with pytest.raises(ValueError): + table.save() From 2a837ff6e570154e9b9313117ff47b07592cd325 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 13:09:17 -0400 Subject: [PATCH 46/72] tests for trees --- tests/serverless/test_item.py | 105 ++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index b6838ed65..413daf73a 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -520,3 +520,108 @@ def test_table_content_invalid_shape(adr_serverless): ) with pytest.raises(ValueError): table.save() + + +@pytest.mark.ado_test +def test_create_tree_success(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = [ + {"key": "root", "name": "Solver", "value": "My Solver"}, + {"key": "root", "name": "Number cells", "value": 10e6}, + ] + tree = adr_serverless.create_item( + Tree, + name="intro_tree", + content=tree_content, + tags="dp=dp227 section=data", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + assert Tree.get(name="intro_tree").guid == tree.guid + + +@pytest.mark.ado_test +@pytest.mark.parametrize( + "bad_content", + [ + [{"name": "Missing key", "value": "Oops"}], # Missing 'key' + [{"key": "root", "value": "Oops"}], # Missing 'name' + [{"key": "root", "name": "Missing value"}], # Missing 'value' + ], +) +def test_create_tree_missing_keys(adr_serverless, bad_content): + from ansys.dynamicreporting.core.serverless import Tree + + with pytest.raises(ValueError): + adr_serverless.create_item( + Tree, + name="bad_tree", + content=bad_content, + tags="dp=dp227 section=data", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + +@pytest.mark.ado_test +def test_create_tree_invalid_value_type(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + bad_content = [{"key": "root", "name": "Invalid value", "value": {"not": "allowed"}}] + with pytest.raises(ValueError): + adr_serverless.create_item( + Tree, + name="bad_value_tree", + content=bad_content, + tags="dp=dp227 section=data", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + +@pytest.mark.ado_test +def test_create_tree_non_dict_element(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + bad_content = [ + {"key": "root", "name": "Good", "value": "OK"}, + "I am not a dictionary", + ] + with pytest.raises(ValueError): + adr_serverless.create_item( + Tree, + name="non_dict_tree", + content=bad_content, + tags="dp=dp227 section=data", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + +@pytest.mark.ado_test +def test_create_tree_invalid_nested_value(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + bad_content = [ + { + "key": "root", + "name": "Nested Tree", + "value": "Root", + "children": [{"key": "child", "name": "Bad Child", "value": {"bad": "value"}}], + } + ] + with pytest.raises(ValueError): + adr_serverless.create_item( + Tree, + name="nested_bad_tree", + content=bad_content, + tags="dp=dp227 section=data", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) From 6d228d34b060f71d19433538c2cc2178fdf3194d Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 13:19:33 -0400 Subject: [PATCH 47/72] Update test_item.py --- tests/serverless/test_item.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 413daf73a..58acaf2f2 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -530,16 +530,15 @@ def test_create_tree_success(adr_serverless): {"key": "root", "name": "Solver", "value": "My Solver"}, {"key": "root", "name": "Number cells", "value": 10e6}, ] - tree = adr_serverless.create_item( - Tree, - name="intro_tree", + tree = Tree.create( + name="test_create_tree_success", content=tree_content, tags="dp=dp227 section=data", session=adr_serverless.session, dataset=adr_serverless.dataset, source="sls-test", ) - assert Tree.get(name="intro_tree").guid == tree.guid + assert Tree.get(guid=tree.guid).guid == tree.guid @pytest.mark.ado_test @@ -555,9 +554,8 @@ def test_create_tree_missing_keys(adr_serverless, bad_content): from ansys.dynamicreporting.core.serverless import Tree with pytest.raises(ValueError): - adr_serverless.create_item( - Tree, - name="bad_tree", + Tree.create( + name="test_create_tree_missing_keys", content=bad_content, tags="dp=dp227 section=data", session=adr_serverless.session, @@ -572,9 +570,8 @@ def test_create_tree_invalid_value_type(adr_serverless): bad_content = [{"key": "root", "name": "Invalid value", "value": {"not": "allowed"}}] with pytest.raises(ValueError): - adr_serverless.create_item( - Tree, - name="bad_value_tree", + Tree.create( + name="test_create_tree_invalid_value_type", content=bad_content, tags="dp=dp227 section=data", session=adr_serverless.session, @@ -592,9 +589,8 @@ def test_create_tree_non_dict_element(adr_serverless): "I am not a dictionary", ] with pytest.raises(ValueError): - adr_serverless.create_item( - Tree, - name="non_dict_tree", + Tree.create( + name="test_create_tree_non_dict_element", content=bad_content, tags="dp=dp227 section=data", session=adr_serverless.session, @@ -616,9 +612,8 @@ def test_create_tree_invalid_nested_value(adr_serverless): } ] with pytest.raises(ValueError): - adr_serverless.create_item( - Tree, - name="nested_bad_tree", + Tree.create( + name="test_create_tree_invalid_nested_value", content=bad_content, tags="dp=dp227 section=data", session=adr_serverless.session, From c3b9b4ae65f577b3fdbf024037750e67141e493a Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 13:36:31 -0400 Subject: [PATCH 48/72] Update test_item.py --- tests/serverless/test_item.py | 85 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 58acaf2f2..86a6eebdb 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -426,32 +426,30 @@ def test_item_objectset_values_list_empty(adr_serverless): def test_string_content_none(adr_serverless): from ansys.dynamicreporting.core.serverless import String - string = String( - name="test_string_content_none", - content=None, - tags="dp=dp227", - source="sls-test", - session=adr_serverless.session, - dataset=adr_serverless.dataset, - ) with pytest.raises(ValueError): - string.save() + string = String( + name="test_string_content_none", + content=None, + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) @pytest.mark.ado_test def test_string_content_wrong_type(adr_serverless): from ansys.dynamicreporting.core.serverless import String - string = String( - name="test_string_content_wrong_type", - content=1, - tags="dp=dp227", - source="sls-test", - session=adr_serverless.session, - dataset=adr_serverless.dataset, - ) with pytest.raises(TypeError): - string.save() + string = String( + name="test_string_content_wrong_type", + content=1, + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) @pytest.mark.ado_test @@ -474,16 +472,15 @@ def test_string_content_empty(adr_serverless): def test_table_content_not_numpy(adr_serverless): from ansys.dynamicreporting.core.serverless import Table - table = Table( - name="test_table_content_not_numpy", - content="", - tags="dp=dp227", - source="sls-test", - session=adr_serverless.session, - dataset=adr_serverless.dataset, - ) with pytest.raises(TypeError): - table.save() + table = Table( + name="test_table_content_not_numpy", + content="", + tags="dp=dp227", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) @pytest.mark.ado_test @@ -492,16 +489,15 @@ def test_table_content_invalid_dtype(adr_serverless): from ansys.dynamicreporting.core.serverless import Table - table = Table( - name="test_table_content_invalid_dtype", - content=np.array([[1, 2], [3, 4]], dtype=int), # Invalid dtype - session=adr_serverless.session, - tags="dp=dp227", - source="sls-test", - dataset=adr_serverless.dataset, - ) with pytest.raises(TypeError): - table.save() + table = Table( + name="test_table_content_invalid_dtype", + content=np.array([[1, 2], [3, 4]], dtype=int), # Invalid dtype + session=adr_serverless.session, + tags="dp=dp227", + source="sls-test", + dataset=adr_serverless.dataset, + ) @pytest.mark.ado_test @@ -510,16 +506,15 @@ def test_table_content_invalid_shape(adr_serverless): from ansys.dynamicreporting.core.serverless import Table - table = Table( - name="test_table_content_invalid_shape", - content=np.array([1, 2, 3], dtype="|S20"), # Invalid shape (1D array instead of 2D) - session=adr_serverless.session, - tags="dp=dp227", - source="sls-test", - dataset=adr_serverless.dataset, - ) with pytest.raises(ValueError): - table.save() + table = Table( + name="test_table_content_invalid_shape", + content=np.array([1, 2, 3], dtype="|S20"), # Invalid shape (1D array instead of 2D) + session=adr_serverless.session, + tags="dp=dp227", + source="sls-test", + dataset=adr_serverless.dataset, + ) @pytest.mark.ado_test From 0840575ac189a2a5026e6c2cce1a07f74c3460ea Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 15:58:04 -0400 Subject: [PATCH 49/72] fix None check in Validator --- src/ansys/dynamicreporting/core/serverless/base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index e2e3861bd..a9e526dfc 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -562,9 +562,7 @@ def __get__(self, obj, obj_type=None): return getattr(obj, self._name, self._default) def __set__(self, obj, value): - cleaned_value = None - if value is not None: - cleaned_value = self.process(value, obj) + cleaned_value = self.process(value, obj) setattr(obj, self._name, cleaned_value) @abstractmethod From c899b74a28053ae8dd7382df5bf6adf94a9aaf1e Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 16:06:51 -0400 Subject: [PATCH 50/72] Update item.py --- src/ansys/dynamicreporting/core/serverless/item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 6a1a65e99..7f4013fe1 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -62,7 +62,7 @@ def reset(self): class ItemContent(Validator): def process(self, value, obj): if value is None: - raise ValueError(extra_detail="Content cannot be None") + raise ValueError("Content cannot be None") return value From 049c7cdeaf60aec0d3077d8ca92ffc85b935a6a8 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 16:19:17 -0400 Subject: [PATCH 51/72] Bypass __init__ to skip validation --- src/ansys/dynamicreporting/core/serverless/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index a9e526dfc..971aeaaae 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -350,7 +350,7 @@ def delete(self, **kwargs): def from_db(cls, orm_instance, parent=None): cls_fields = dict(cls._get_field_names(with_types=True, include_private=True)) model_fields = cls._get_orm_field_names(orm_instance) - obj = cls() + obj = cls.__new__(cls) # Bypass __init__ to skip validation for field_ in model_fields: if field_ in cls_fields: attr = field_ From 0547f025fd849b82037ac0388402ef796a0c0711 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 16:22:47 -0400 Subject: [PATCH 52/72] Update test_item.py --- tests/serverless/test_item.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 86a6eebdb..feac49605 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -427,7 +427,7 @@ def test_string_content_none(adr_serverless): from ansys.dynamicreporting.core.serverless import String with pytest.raises(ValueError): - string = String( + String( name="test_string_content_none", content=None, tags="dp=dp227", @@ -442,7 +442,7 @@ def test_string_content_wrong_type(adr_serverless): from ansys.dynamicreporting.core.serverless import String with pytest.raises(TypeError): - string = String( + String( name="test_string_content_wrong_type", content=1, tags="dp=dp227", @@ -473,7 +473,7 @@ def test_table_content_not_numpy(adr_serverless): from ansys.dynamicreporting.core.serverless import Table with pytest.raises(TypeError): - table = Table( + Table( name="test_table_content_not_numpy", content="", tags="dp=dp227", @@ -490,7 +490,7 @@ def test_table_content_invalid_dtype(adr_serverless): from ansys.dynamicreporting.core.serverless import Table with pytest.raises(TypeError): - table = Table( + Table( name="test_table_content_invalid_dtype", content=np.array([[1, 2], [3, 4]], dtype=int), # Invalid dtype session=adr_serverless.session, @@ -507,7 +507,7 @@ def test_table_content_invalid_shape(adr_serverless): from ansys.dynamicreporting.core.serverless import Table with pytest.raises(ValueError): - table = Table( + Table( name="test_table_content_invalid_shape", content=np.array([1, 2, 3], dtype="|S20"), # Invalid shape (1D array instead of 2D) session=adr_serverless.session, From 3d4de9b3a18dd40da53d79a7b4e5b2412fcf3d8f Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 16:30:38 -0400 Subject: [PATCH 53/72] remove get_or_create remove get_or_create --- .../dynamicreporting/core/serverless/adr.py | 12 +++- .../dynamicreporting/core/serverless/base.py | 8 --- .../dynamicreporting/core/serverless/item.py | 6 +- .../core/serverless/template.py | 6 +- tests/serverless/test_item.py | 62 +++++++------------ tests/serverless/test_template.py | 28 +-------- 6 files changed, 37 insertions(+), 85 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/adr.py b/src/ansys/dynamicreporting/core/serverless/adr.py index de2410fec..2c4657cc1 100644 --- a/src/ansys/dynamicreporting/core/serverless/adr.py +++ b/src/ansys/dynamicreporting/core/serverless/adr.py @@ -818,10 +818,16 @@ def copy_objects( "'target_media_dir' argument must be specified because one of the objects" " contains media to copy.'" ) - # save or load sessions, datasets - since it is possible they are shared + # try to load sessions, datasets - since it is possible they are shared # and were saved already. - session, _ = Session.get_or_create(**item.session.as_dict(), using=target_database) - dataset, _ = Dataset.get_or_create(**item.dataset.as_dict(), using=target_database) + try: + session = Session.get(guid=item.session.guid, using=target_database) + except Session.DoesNotExist: + session = Session.create(**item.session.as_dict(), using=target_database) + try: + dataset = Dataset.get(guid=item.dataset.guid, using=target_database) + except Dataset.DoesNotExist: + dataset = Dataset.create(**item.dataset.as_dict(), using=target_database) item.session = session item.dataset = dataset copy_list.append(item) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index 971aeaaae..f304389e1 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -442,14 +442,6 @@ def get(cls, **kwargs): return cls.from_db(orm_instance) - @classmethod - @handle_field_errors - def get_or_create(cls, **kwargs) -> tuple["BaseModel", bool]: - try: - return cls.get(**kwargs), False - except cls.DoesNotExist: - return cls.create(**kwargs), True - @classmethod @handle_field_errors def filter(cls, **kwargs) -> "ObjectSet": diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 7f4013fe1..5729783bb 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -314,17 +314,13 @@ def create(cls, **kwargs): @classmethod def _validate_kwargs(cls, **kwargs): if "content" in kwargs: - raise ValueError("'content' kwarg is not supported for get* and filter methods") + raise ValueError("'content' kwarg is not supported for get and filter methods") return {"type": cls.type, **kwargs} if cls.type != "none" else kwargs @classmethod def get(cls, **kwargs): return super().get(**cls._validate_kwargs(**kwargs)) - @classmethod - def get_or_create(cls, **kwargs): - return super().get_or_create(**cls._validate_kwargs(**kwargs)) - @classmethod def filter(cls, **kwargs): return super().filter(**cls._validate_kwargs(**kwargs)) diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index 334463ed8..1d0f79a09 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -124,17 +124,13 @@ def create(cls, **kwargs): @classmethod def _validate_kwargs(cls, **kwargs): if "children" in kwargs: - raise ValueError("'children' kwarg is not supported for get* and filter methods") + raise ValueError("'children' kwarg is not supported for get and filter methods") return {"report_type": cls.report_type, **kwargs} if cls.report_type else kwargs @classmethod def get(cls, **kwargs): return super().get(**cls._validate_kwargs(**kwargs)) - @classmethod - def get_or_create(cls, **kwargs): - return super().get_or_create(**cls._validate_kwargs(**kwargs)) - @classmethod def filter(cls, **kwargs): return super().filter(**cls._validate_kwargs(**kwargs)) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index feac49605..40e63a533 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -230,6 +230,29 @@ def test_delete_not_saved(adr_serverless): intro_html.delete() +@pytest.mark.ado_test +def test_create_item(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = [ + {"key": "root", "name": "Solver", "value": "My Solver"}, + {"key": "root", "name": "Number cells", "value": 10e6}, + {"key": "root", "name": "Mesh Size", "value": "1.0 mm^3"}, + {"key": "root", "name": "Mesh Type", "value": "Hex8"}, + ] + + tree_kwargs = { + "name": "test_create_item", + "source": "sls-test", + "content": tree_content, + "tags": "dp=dp227", + "session": adr_serverless.session, + "dataset": adr_serverless.dataset, + } + tree = Tree.create(**tree_kwargs) + assert tree.saved is True + + @pytest.mark.ado_test def test_get_item(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML @@ -272,45 +295,6 @@ def test_get_item_multiple(adr_serverless): HTML.get(name="test_get_item_multiple") -@pytest.mark.ado_test -def test_get_or_create_item(adr_serverless): - from ansys.dynamicreporting.core.serverless import Tree - - tree_kwargs = { - "name": "intro_tree", - "source": "sls-test", - "tags": "dp=dp227", - "session": adr_serverless.session, - "dataset": adr_serverless.dataset, - } - tree, _ = Tree.get_or_create(**tree_kwargs) - new_tree, _ = Tree.get_or_create(**tree_kwargs) - assert new_tree.guid == tree.guid - - -@pytest.mark.ado_test -def test_get_or_create_item_w_content(adr_serverless): - from ansys.dynamicreporting.core.serverless import Tree - - tree_content = [ - {"key": "root", "name": "Solver", "value": "My Solver"}, - {"key": "root", "name": "Number cells", "value": 10e6}, - {"key": "root", "name": "Mesh Size", "value": "1.0 mm^3"}, - {"key": "root", "name": "Mesh Type", "value": "Hex8"}, - ] - # tree - tree_kwargs = { - "name": "intro_tree", - "content": tree_content, - "source": "sls-test", - "tags": "dp=dp227", - "session": adr_serverless.session, - "dataset": adr_serverless.dataset, - } - with pytest.raises(ValueError): - Tree.get_or_create(**tree_kwargs) - - @pytest.mark.ado_test def test_item_objectset_repr(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML diff --git a/tests/serverless/test_template.py b/tests/serverless/test_template.py index 7ab67906f..0a905d201 100644 --- a/tests/serverless/test_template.py +++ b/tests/serverless/test_template.py @@ -168,36 +168,14 @@ def test_child_not_exist(adr_serverless): @pytest.mark.ado_test -def test_get_or_create_template(adr_serverless): +def test_create_template(adr_serverless): from ansys.dynamicreporting.core.serverless import BasicLayout template_kwargs = { - "name": "test_get_or_create_template", + "name": "test_create_template", "parent": None, "tags": "dp=dp227", "params": '{"HTML": "

Serverless Simulation Report

"}', } template = BasicLayout.create(**template_kwargs) - same_template, _ = BasicLayout.get_or_create(**template_kwargs) - assert template.guid == same_template.guid - - -@pytest.mark.ado_test -def test_get_or_create_template_w_children(adr_serverless): - from ansys.dynamicreporting.core.serverless import BasicLayout, TOCLayout - - template_kwargs = { - "name": "test_get_or_create_template_w_children", - "parent": None, - "tags": "dp=dp227", - "params": '{"HTML": "

Serverless Simulation Report

"}', - } - top_parent = adr_serverless.create_template( - BasicLayout, - **template_kwargs, - ) - toc_layout = adr_serverless.create_template( - TOCLayout, name="TOC", parent=top_parent, tags="dp=dp227" - ) - with pytest.raises(ValueError): - BasicLayout.get_or_create(**template_kwargs, children=[toc_layout]) + assert template.saved is True From f933dc74629e54086b48467566f4e42659cc2dda Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 18:07:09 -0400 Subject: [PATCH 54/72] more tree tests --- tests/serverless/test_item.py | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 40e63a533..f081cd154 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -599,3 +599,55 @@ def test_create_tree_invalid_nested_value(adr_serverless): dataset=adr_serverless.dataset, source="sls-test", ) + + +@pytest.mark.ado_test +def test_tree_content_value_list_valid(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = [ + {"key": "root", "name": "Solver List", "value": ["Ansys", "Fluent", "CFX"]}, + ] + tree = Tree.create( + name="test_tree_content_value_list_valid", + content=tree_content, + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + assert Tree.get(guid=tree.guid).guid == tree.guid + + +@pytest.mark.ado_test +def test_tree_content_value_list_invalid(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = [ + {"key": "root", "name": "Solver List", "value": ["Ansys", object()]}, + ] + with pytest.raises(ValueError): + Tree.create( + name="test_tree_content_value_list_invalid", + content=tree_content, + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + +@pytest.mark.ado_test +def test_tree_content_invalid(adr_serverless): + from ansys.dynamicreporting.core.serverless import Tree + + tree_content = "This is not a valid content" + with pytest.raises(ValueError): + Tree.create( + name="test_tree_content_invalid", + content=tree_content, + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) \ No newline at end of file From e8087fd073f9b40e60bc75835f7fa8ed62b04f41 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Wed, 9 Apr 2025 18:22:05 -0400 Subject: [PATCH 55/72] fix Item instantiation error --- src/ansys/dynamicreporting/core/serverless/item.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 5729783bb..c6f64400e 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -269,9 +269,8 @@ def __init_subclass__(cls, **kwargs): Item._type_registry[cls.type] = cls def __post_init__(self): - # todo: can be bypassed by setting type at instantiation - if self.type == "none": - raise TypeError("Cannot instantiate Item directly. Use Item.create()") + if self.__class__ is Item: + raise ADRException("Cannot instantiate Item directly. Use the Item.create() method.") super().__post_init__() def save(self, **kwargs): From d911f433a1f421359681b7c69d6f127cfb45d4ee Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 13:37:22 -0400 Subject: [PATCH 56/72] fix super class checks --- src/ansys/dynamicreporting/core/serverless/base.py | 3 +++ src/ansys/dynamicreporting/core/serverless/item.py | 6 +++--- src/ansys/dynamicreporting/core/serverless/template.py | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/base.py b/src/ansys/dynamicreporting/core/serverless/base.py index f304389e1..d56298639 100644 --- a/src/ansys/dynamicreporting/core/serverless/base.py +++ b/src/ansys/dynamicreporting/core/serverless/base.py @@ -445,6 +445,9 @@ def get(cls, **kwargs): @classmethod @handle_field_errors def filter(cls, **kwargs) -> "ObjectSet": + for key, value in kwargs.items(): + if isinstance(value, BaseModel): + kwargs[key] = value._orm_instance qs = cls._orm_model_cls.objects.using(kwargs.pop("using", "default")).filter(**kwargs) return ObjectSet(_model=cls, _orm_model=cls._orm_model_cls, _orm_queryset=qs) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index c6f64400e..5e71d6ef4 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -326,11 +326,11 @@ def filter(cls, **kwargs): @classmethod def find(cls, query="", **kwargs): - if cls.type == "none": + if cls is Item: return super().find(query=query, **kwargs) if "i_type|cont" in query: raise ADRException( - extra_detail="The 'i_type' filter is not required if using a subclass of Item" + extra_detail="The 'i_type' filter is not allowed if using a subclass of Item" ) return super().find(query=f"A|i_type|cont|{cls.type};{query}", **kwargs) # noqa: E702 @@ -424,7 +424,7 @@ def save(self, **kwargs): target_ext = "png" if not self._enhanced else self._file_ext self._orm_instance.payloadfile = f"{self.guid}_image.{target_ext}" # Save the image - if target_ext == "png" and self._file_ext != target_ext: + if self._file_ext != target_ext and target_ext == "png": try: image.save(self.file_path, format="PNG") except OSError as e: diff --git a/src/ansys/dynamicreporting/core/serverless/template.py b/src/ansys/dynamicreporting/core/serverless/template.py index 1d0f79a09..6ac53f536 100644 --- a/src/ansys/dynamicreporting/core/serverless/template.py +++ b/src/ansys/dynamicreporting/core/serverless/template.py @@ -32,7 +32,7 @@ def __init_subclass__(cls, **kwargs): Template._type_registry[cls.report_type] = cls def __post_init__(self): - if self.report_type == "": + if self.__class__ is Template: raise TypeError("Cannot instantiate Template directly. Use Template.create()") super().__post_init__() @@ -137,11 +137,11 @@ def filter(cls, **kwargs): @classmethod def find(cls, query="", **kwargs): - if not cls.report_type: + if cls is Template: return super().find(query=query, **kwargs) if "t_types|cont" in query: raise ADRException( - extra_detail="The 't_types' filter is not required if using a subclass of Template" + extra_detail="The 't_types' filter is not allowed if using a subclass of Template" ) query_string = f"A|t_types|cont|{cls.report_type};{query}" # noqa: E702 return super().find(query=query_string, **kwargs) From 814784e5aa41db1c2e50eed50daa005acda0382c Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 13:37:38 -0400 Subject: [PATCH 57/72] tests for item class methods --- tests/serverless/test_item.py | 167 +++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index f081cd154..b3c4c24bf 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -3,6 +3,8 @@ import pytest +from ansys.dynamicreporting.core.exceptions import ADRException + @pytest.mark.ado_test def test_field_error(adr_serverless): @@ -39,6 +41,124 @@ def test_create_html_cls(adr_serverless): assert HTML.get(name="test_create_html_cls").guid == intro_html.guid +@pytest.mark.ado_test +def test_create_item_cls(adr_serverless): + from ansys.dynamicreporting.core.serverless import Item + + intro_html = Item.create( + name="test_create_item_cls", + type="html", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert Item.get(guid=intro_html.guid).guid == intro_html.guid + + +@pytest.mark.ado_test +def test_create_item_cls_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import Item + + with pytest.raises(ADRException): + Item.create( + name="test_create_item_cls_error", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + + +@pytest.mark.ado_test +def test_item_cls_init(adr_serverless): + from ansys.dynamicreporting.core.serverless import Item + + with pytest.raises(ADRException): + Item( + name="test_item_cls_init", + type="tree", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + + +@pytest.mark.ado_test +def test_item_get_w_content_error(adr_serverless): + from ansys.dynamicreporting.core.serverless import Item + + intro_html = Item.create( + name="test_create_item_cls", + type="html", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(ValueError): + Item.get(content=intro_html.content) + + +@pytest.mark.ado_test +def test_item_filter(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_filter", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert ( + HTML.filter( + name="test_item_filter", session=adr_serverless.session, dataset=adr_serverless.dataset + )[0].guid + == intro_html.guid + ) + + +@pytest.mark.ado_test +def test_item_cls_filter(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML, Item + + intro_html = HTML.create( + name="test_item_cls_filter", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert ( + Item.filter( + name="test_item_filter", session=adr_serverless.session, dataset=adr_serverless.dataset + )[0].guid + == intro_html.guid + ) + + +@pytest.mark.ado_test +def test_item_find(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_find", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert HTML.find(query="A|i_name|cont|test_item_find")[0].guid == intro_html.guid + + +@pytest.mark.ado_test +def test_item_cls_find(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML, Item + + intro_html = HTML.create( + name="test_item_cls_find", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert Item.find(query="A|i_name|cont|test_item_cls_find")[0].guid == intro_html.guid + + @pytest.mark.ado_test def test_str(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML @@ -650,4 +770,49 @@ def test_tree_content_invalid(adr_serverless): session=adr_serverless.session, dataset=adr_serverless.dataset, source="sls-test", - ) \ No newline at end of file + ) + + +@pytest.mark.ado_test +def test_item_file_ext(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + # image + intro_image = Image( + name="test_item_file_ext", + content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), + tags="dp=dp227 section=data", + source="sls-test", + ) + + assert intro_image.file_ext == "png" + + +@pytest.mark.ado_test +def test_item_has_file(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + # image + intro_image = Image( + name="test_item_has_file", + content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), + tags="dp=dp227 section=data", + source="sls-test", + ) + + assert intro_image.has_file is True + + +@pytest.mark.ado_test +def test_item_is_enhanced(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + # image + intro_image = Image( + name="test_item_is_enhanced", + content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), + tags="dp=dp227 section=data", + source="sls-test", + ) + + assert intro_image.enhanced is False From 4701ab37727f1bf00fd30451af1e84cf0bd05a9e Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 13:42:53 -0400 Subject: [PATCH 58/72] Update test_item.py --- tests/serverless/test_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index b3c4c24bf..57a07db3d 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -127,7 +127,7 @@ def test_item_cls_filter(adr_serverless): ) assert ( Item.filter( - name="test_item_filter", session=adr_serverless.session, dataset=adr_serverless.dataset + name="test_item_cls_filter", session=adr_serverless.session, dataset=adr_serverless.dataset )[0].guid == intro_html.guid ) From 97a322cd0472db7062f08a8533c5c3cb5a6dfd2a Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 13:45:49 -0400 Subject: [PATCH 59/72] Update test_item.py --- tests/serverless/test_item.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 57a07db3d..a5ff48d3f 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -127,7 +127,9 @@ def test_item_cls_filter(adr_serverless): ) assert ( Item.filter( - name="test_item_cls_filter", session=adr_serverless.session, dataset=adr_serverless.dataset + name="test_item_cls_filter", + session=adr_serverless.session, + dataset=adr_serverless.dataset, )[0].guid == intro_html.guid ) From 2f4f72ca0f6aa040206af50bb1830b7ab95e5fe5 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 14:21:00 -0400 Subject: [PATCH 60/72] raise during png conversion --- src/ansys/dynamicreporting/core/serverless/item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 5e71d6ef4..1e4567fbc 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -428,7 +428,7 @@ def save(self, **kwargs): try: image.save(self.file_path, format="PNG") except OSError as e: - print(f"Error converting image to PNG: {e}") + raise ADRException(f"Error converting image to PNG: {e}") from e else: # save image as is (if enhanced or already PNG) self._save_file(self.file_path, img_bytes) image.close() From bd8d8f644aa8151ad28f80dcc45ae00b31c60ec8 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 14:21:03 -0400 Subject: [PATCH 61/72] Update test_item.py --- tests/serverless/test_item.py | 205 ++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index a5ff48d3f..4812b4cbf 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1,6 +1,9 @@ from pathlib import Path +import tempfile +from unittest import mock from uuid import uuid4 +from PIL import Image as PILImage import pytest from ansys.dynamicreporting.core.exceptions import ADRException @@ -148,6 +151,15 @@ def test_item_find(adr_serverless): assert HTML.find(query="A|i_name|cont|test_item_find")[0].guid == intro_html.guid +@pytest.mark.ado_test +def test_item_find_raises_exception(adr_serverless): + from ansys.dynamicreporting.core.exceptions import ADRException + from ansys.dynamicreporting.core.serverless import HTML + + with pytest.raises(ADRException): + HTML.find(query="A|i_type|cont|html") + + @pytest.mark.ado_test def test_item_cls_find(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML, Item @@ -352,6 +364,76 @@ def test_delete_not_saved(adr_serverless): intro_html.delete() +@pytest.mark.ado_test +def test_save_item(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML( + name="test_save_item", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.save() + assert HTML.get(guid=intro_html.guid).guid == intro_html.guid + + +@pytest.mark.ado_test +def test_save_item_no_session(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML( + name="test_save_item_no_session", + content="

Heading 1

", + dataset=adr_serverless.dataset, + ) + with pytest.raises(ADRException): + intro_html.save() + + +@pytest.mark.ado_test +def test_save_item_no_dataset(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML( + name="test_save_item_no_dataset", + content="

Heading 1

", + session=adr_serverless.session, + ) + with pytest.raises(ADRException): + intro_html.save() + + +@pytest.mark.ado_test +def test_save_item_session_unsaved(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML, Session + + session = Session() + intro_html = HTML( + name="test_save_item_session_unsaved", + content="

Heading 1

", + session=session, + dataset=adr_serverless.dataset, + ) + with pytest.raises(HTML.SessionUnsaved): + intro_html.save() + + +@pytest.mark.ado_test +def test_save_item_dataset_unsaved(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML, Dataset + + dataset = Dataset() + intro_html = HTML( + name="test_save_item_dataset_unsaved", + content="

Heading 1

", + session=adr_serverless.session, + dataset=dataset, + ) + with pytest.raises(HTML.DatasetUnsaved): + intro_html.save() + + @pytest.mark.ado_test def test_create_item(adr_serverless): from ansys.dynamicreporting.core.serverless import Tree @@ -818,3 +900,126 @@ def test_item_is_enhanced(adr_serverless): ) assert intro_image.enhanced is False + + +@pytest.mark.ado_test +def test_file_size_zero_fails_validation(adr_serverless): + from ansys.dynamicreporting.core.serverless import File + + with tempfile.NamedTemporaryFile(delete=False, suffix=".txt") as tmp: + tmp_path = Path(tmp.name) + + try: + with pytest.raises(ValueError, match="The file specified is empty"): + File.create( + name="test_file_size_zero_fails_validation", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + finally: + tmp_path.unlink() + + +@pytest.mark.ado_test +def test_image_conversion_to_png(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image # Import your Image class + + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: + tmp_path = Path(tmp.name) + img = PILImage.new("RGB", (10, 10), color="red") + img.save(tmp_path, "JPEG") # Save as JPEG + + try: + image_obj = Image.create( + name="test_image_conversion_to_png", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + image_obj.save() + + assert image_obj._orm_instance.payloadfile.endswith(".png") + assert image_obj.file_path.is_file() + assert image_obj.file_path.suffix == ".png" + + finally: + tmp_path.unlink(missing_ok=True) + + +@pytest.mark.ado_test +def test_invalid_file_extension_fails(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as tmp: + tmp_path = Path(tmp.name) + tmp.write(b"Dummy content") + tmp.flush() + + try: + with pytest.raises(ValueError, match="File type txt is not supported"): + Image.create( + name="test_invalid_file_extension_fails", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + finally: + tmp_path.unlink(missing_ok=True) + + +@pytest.mark.ado_test +def test_image_save_raises_adr_exception(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: + tmp_path = Path(tmp.name) + img = PILImage.new("RGB", (10, 10), color="red") + img.save(tmp_path, "JPEG") + + try: + image_obj = Image.create( + name="test_image_save_raises_adr_exception", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + + with mock.patch("PIL.Image.Image.save", side_effect=OSError("Simulated save error")): + with pytest.raises(ADRException, match="Error converting image to PNG:"): + image_obj.save() + + finally: + tmp_path.unlink(missing_ok=True) + + +@pytest.mark.ado_test +def test_is_enhanced_fails_on_non_enhanced_tiff(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + with tempfile.NamedTemporaryFile(suffix=".tiff", delete=False) as tmp: + tmp_path = Path(tmp.name) + img = PILImage.new("RGB", (10, 10), color="blue") + img.save(tmp_path, format="TIFF") + + try: + with pytest.raises(ADRException, match="The enhanced image is empty"): + Image.create( + name="test_is_enhanced_fails_on_non_enhanced_tiff", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + finally: + tmp_path.unlink(missing_ok=True) From a9e6ec44aa872bb0b6cc8f0b1a7fbf03a8f76aec Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 14:28:10 -0400 Subject: [PATCH 62/72] Update test_item.py --- tests/serverless/test_item.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 4812b4cbf..428f79dd2 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -415,7 +415,7 @@ def test_save_item_session_unsaved(adr_serverless): session=session, dataset=adr_serverless.dataset, ) - with pytest.raises(HTML.SessionUnsaved): + with pytest.raises(Session.NotSaved): intro_html.save() @@ -430,7 +430,7 @@ def test_save_item_dataset_unsaved(adr_serverless): session=adr_serverless.session, dataset=dataset, ) - with pytest.raises(HTML.DatasetUnsaved): + with pytest.raises(Dataset.NotSaved): intro_html.save() @@ -944,7 +944,6 @@ def test_image_conversion_to_png(adr_serverless): image_obj.save() - assert image_obj._orm_instance.payloadfile.endswith(".png") assert image_obj.file_path.is_file() assert image_obj.file_path.suffix == ".png" From 3060e7492e2ef68021c85d1f28788c9090436893 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 14:35:40 -0400 Subject: [PATCH 63/72] Update test_item.py --- tests/serverless/test_item.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 428f79dd2..15491245e 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -943,10 +943,8 @@ def test_image_conversion_to_png(adr_serverless): ) image_obj.save() - - assert image_obj.file_path.is_file() - assert image_obj.file_path.suffix == ".png" - + file_path = Path(image_obj.file_path) + assert file_path.is_file() and file_path.suffix == ".png" finally: tmp_path.unlink(missing_ok=True) From 6d4cec05deed90c7a5fb7435043dde9d40fb7ad6 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 15:09:57 -0400 Subject: [PATCH 64/72] Update test_item.py --- tests/serverless/test_item.py | 59 ++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 15491245e..dba5e0a62 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -471,6 +471,21 @@ def test_get_item(adr_serverless): assert item.guid == intro_html.guid +@pytest.mark.ado_test +def test_item_delete(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_delete", + content="

Heading 1

", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + intro_html.delete() + with pytest.raises(HTML.DoesNotExist): + HTML.get(guid=intro_html.guid) + + @pytest.mark.ado_test def test_get_item_does_not_exist(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML @@ -531,6 +546,24 @@ def test_item_objectset_str(adr_serverless): assert str(objs) == f"[]" +@pytest.mark.ado_test +def test_item_objectset_delete(adr_serverless): + from ansys.dynamicreporting.core.serverless import HTML + + intro_html = HTML.create( + name="test_item_objectset_delete", + content="

Heading 1

", + source="sls-test", + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + objs = adr_serverless.query(query_type=HTML, query="A|i_name|cont|test_item_objectset_delete;") + objs.delete() + with pytest.raises(HTML.DoesNotExist): + HTML.get(guid=intro_html.guid) + + @pytest.mark.ado_test def test_item_objectset_getitem(adr_serverless): from ansys.dynamicreporting.core.serverless import HTML @@ -923,32 +956,6 @@ def test_file_size_zero_fails_validation(adr_serverless): tmp_path.unlink() -@pytest.mark.ado_test -def test_image_conversion_to_png(adr_serverless): - from ansys.dynamicreporting.core.serverless import Image # Import your Image class - - with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: - tmp_path = Path(tmp.name) - img = PILImage.new("RGB", (10, 10), color="red") - img.save(tmp_path, "JPEG") # Save as JPEG - - try: - image_obj = Image.create( - name="test_image_conversion_to_png", - content=str(tmp_path), - tags="dp=dp227", - session=adr_serverless.session, - dataset=adr_serverless.dataset, - source="sls-test", - ) - - image_obj.save() - file_path = Path(image_obj.file_path) - assert file_path.is_file() and file_path.suffix == ".png" - finally: - tmp_path.unlink(missing_ok=True) - - @pytest.mark.ado_test def test_invalid_file_extension_fails(adr_serverless): from ansys.dynamicreporting.core.serverless import Image From f8aeb9c6b7fc574495eb4bda011596bd07393c5d Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 16:28:31 -0400 Subject: [PATCH 65/72] fix File and Image handling --- .../dynamicreporting/core/serverless/item.py | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index 1e4567fbc..ee491079a 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -206,16 +206,24 @@ class FilePayloadMixin: _file_ext: str = field(init=False, compare=False, default="") @property - def file_ext(self): - return self._file_ext + def file_path(self): + try: + return self._orm_instance.payloadfile.path + except (AttributeError, ValueError): + # If the file path is not set, return None + return None @property def has_file(self): - return self._file is not None + return self.file_path is not None and Path(self.file_path).is_file() @property - def file_path(self): - return self._orm_instance.payloadfile.path + def file_ext(self): + try: + return Path(self._orm_instance.payloadfile.path).suffix.lower().lstrip(".") + except (AttributeError, ValueError): + # If the file path is not set, return None + return None @classmethod def from_db(cls, orm_instance, **kwargs): @@ -236,7 +244,6 @@ def _save_file(target_path, content): out_file.write(chunk) def save(self, **kwargs): - # todo: check backward compatibility: _movie is now _anim. self._orm_instance.payloadfile = f"{self.guid}_{self.type}.{self._file_ext}" # Save file to the target path self._save_file(self.file_path, self._file) @@ -425,8 +432,10 @@ def save(self, **kwargs): self._orm_instance.payloadfile = f"{self.guid}_image.{target_ext}" # Save the image if self._file_ext != target_ext and target_ext == "png": + # Convert to PNG format + self._file_ext = target_ext try: - image.save(self.file_path, format="PNG") + image.save(self.file_path, format=self._file_ext.upper()) except OSError as e: raise ADRException(f"Error converting image to PNG: {e}") from e else: # save image as is (if enhanced or already PNG) From 042bc658c8ea37e5ffb6641a0fe6fe75b5e93384 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 16:28:34 -0400 Subject: [PATCH 66/72] Update test_item.py --- tests/serverless/test_item.py | 68 +++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index dba5e0a62..72db5d7b9 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -905,6 +905,21 @@ def test_item_file_ext(adr_serverless): assert intro_image.file_ext == "png" +@pytest.mark.ado_test +def test_item_has_no_file(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + # image + intro_image = Image( + name="test_item_has_no_file", + content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), + tags="dp=dp227 section=data", + source="sls-test", + ) + + assert intro_image.has_file is False + + @pytest.mark.ado_test def test_item_has_file(adr_serverless): from ansys.dynamicreporting.core.serverless import Image @@ -916,6 +931,7 @@ def test_item_has_file(adr_serverless): tags="dp=dp227 section=data", source="sls-test", ) + intro_image.save() assert intro_image.has_file is True @@ -956,6 +972,56 @@ def test_file_size_zero_fails_validation(adr_serverless): tmp_path.unlink() +def test_image_on_disk(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp: + tmp_path = Path(tmp.name) + img = PILImage.new("RGB", (10, 10), color="blue") + img.save(tmp_path, "PNG") + + try: + image_obj = Image.create( + name="test_image_on_disk", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + assert Path(image_obj.file_path).is_file() is True and image_obj.file_ext == "png" + finally: + tmp_path.unlink(missing_ok=True) + + +@pytest.mark.ado_test +def test_image_conversion_to_png(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: + tmp_path = Path(tmp.name) + img = PILImage.new("RGB", (10, 10), color="red") + img.save(tmp_path, "JPEG") # Save as JPEG + + try: + image_obj = Image.create( + name="test_image_conversion_to_png", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) + file_path = Path(image_obj.file_path) + assert ( + Path(image_obj._file.name).suffix == ".jpg" + and file_path.is_file() + and file_path.suffix == ".png" + ) + finally: + tmp_path.unlink(missing_ok=True) + + @pytest.mark.ado_test def test_invalid_file_extension_fails(adr_serverless): from ansys.dynamicreporting.core.serverless import Image @@ -997,11 +1063,9 @@ def test_image_save_raises_adr_exception(adr_serverless): dataset=adr_serverless.dataset, source="sls-test", ) - with mock.patch("PIL.Image.Image.save", side_effect=OSError("Simulated save error")): with pytest.raises(ADRException, match="Error converting image to PNG:"): image_obj.save() - finally: tmp_path.unlink(missing_ok=True) From d1a2eed88a3a989d1c5d3e59329722eb67422ad4 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 16:47:42 -0400 Subject: [PATCH 67/72] update image conv error --- src/ansys/dynamicreporting/core/serverless/item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/dynamicreporting/core/serverless/item.py b/src/ansys/dynamicreporting/core/serverless/item.py index ee491079a..a248430ae 100644 --- a/src/ansys/dynamicreporting/core/serverless/item.py +++ b/src/ansys/dynamicreporting/core/serverless/item.py @@ -437,7 +437,7 @@ def save(self, **kwargs): try: image.save(self.file_path, format=self._file_ext.upper()) except OSError as e: - raise ADRException(f"Error converting image to PNG: {e}") from e + raise ADRException(f"Error converting image to {self._file_ext}: {e}") from e else: # save image as is (if enhanced or already PNG) self._save_file(self.file_path, img_bytes) image.close() From 7043d1835d47f8d3d77633a2a8f498d9d2f2fec0 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 16:47:59 -0400 Subject: [PATCH 68/72] Update test_item.py --- tests/serverless/test_item.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 72db5d7b9..9ac3835f7 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -890,6 +890,22 @@ def test_tree_content_invalid(adr_serverless): ) +@pytest.mark.ado_test +def test_item_file_ext_no_save(adr_serverless): + from ansys.dynamicreporting.core.serverless import Image + + # image + intro_image = Image( + name="test_item_file_ext_no_save", + content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), + tags="dp=dp227 section=data", + source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + ) + assert intro_image.file_ext is None + + @pytest.mark.ado_test def test_item_file_ext(adr_serverless): from ansys.dynamicreporting.core.serverless import Image @@ -900,7 +916,10 @@ def test_item_file_ext(adr_serverless): content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), tags="dp=dp227 section=data", source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, ) + intro_image.save() assert intro_image.file_ext == "png" @@ -915,6 +934,8 @@ def test_item_has_no_file(adr_serverless): content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), tags="dp=dp227 section=data", source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, ) assert intro_image.has_file is False @@ -930,6 +951,8 @@ def test_item_has_file(adr_serverless): content=str(Path(__file__).parent / "test_data" / "nexus_logo.png"), tags="dp=dp227 section=data", source="sls-test", + session=adr_serverless.session, + dataset=adr_serverless.dataset, ) intro_image.save() From 0800ca0e73427ab33866ac913c99dbdc443666ed Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 16:50:35 -0400 Subject: [PATCH 69/72] Update test_item.py --- tests/serverless/test_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index 9ac3835f7..a446baea9 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1087,7 +1087,7 @@ def test_image_save_raises_adr_exception(adr_serverless): source="sls-test", ) with mock.patch("PIL.Image.Image.save", side_effect=OSError("Simulated save error")): - with pytest.raises(ADRException, match="Error converting image to PNG:"): + with pytest.raises(ADRException, match="Error converting image"): image_obj.save() finally: tmp_path.unlink(missing_ok=True) From ed062400f63baf1b22029be1781abfe9aef99711 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 17:04:45 -0400 Subject: [PATCH 70/72] Update test_item.py --- tests/serverless/test_item.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/serverless/test_item.py b/tests/serverless/test_item.py index a446baea9..e2540ae6b 100644 --- a/tests/serverless/test_item.py +++ b/tests/serverless/test_item.py @@ -1078,17 +1078,16 @@ def test_image_save_raises_adr_exception(adr_serverless): img.save(tmp_path, "JPEG") try: - image_obj = Image.create( - name="test_image_save_raises_adr_exception", - content=str(tmp_path), - tags="dp=dp227", - session=adr_serverless.session, - dataset=adr_serverless.dataset, - source="sls-test", - ) with mock.patch("PIL.Image.Image.save", side_effect=OSError("Simulated save error")): with pytest.raises(ADRException, match="Error converting image"): - image_obj.save() + Image.create( + name="test_image_save_raises_adr_exception", + content=str(tmp_path), + tags="dp=dp227", + session=adr_serverless.session, + dataset=adr_serverless.dataset, + source="sls-test", + ) finally: tmp_path.unlink(missing_ok=True) From ed5307ce8679a6949d6a4cbd22b14492fcd8c98d Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 17:25:33 -0400 Subject: [PATCH 71/72] Revert "Reapply disable ci" This reverts commit d91f15723f66c75a2b125e32a3a7cd2be01fb3bd. --- .github/workflows/ci_cd.yml | 46 ++++++++++++++++++------------------- Makefile | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c0b097a2b..399a419b2 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,32 +44,32 @@ jobs: # with: # token: ${{ secrets.GITHUB_TOKEN }} -# smoketest: -# name: Build and smoke tests -# runs-on: ${{ matrix.os }} -# needs: [ style ] -# strategy: -# fail-fast: false -# matrix: -# os: [ ubuntu-latest, windows-latest ] -# python-version: [ '3.10', '3.11', '3.12', '3.13' ] -# steps: -# - name: Build wheelhouse -# uses: ansys/actions/build-wheelhouse@v8 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# operating-system: ${{ matrix.os }} -# python-version: ${{ matrix.python-version }} -# -# - name: Install library -# run: python --version && python -m pip install ${{ env.install_target }} -# -# - name: Run smoketest -# run: make smoketest + smoketest: + name: Build and smoke tests + runs-on: ${{ matrix.os }} + needs: [ style ] + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest ] + python-version: [ '3.10', '3.11', '3.12', '3.13' ] + steps: + - name: Build wheelhouse + uses: ansys/actions/build-wheelhouse@v8 + with: + library-name: ${{ env.PACKAGE_NAME }} + operating-system: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} + + - name: Install library + run: python --version && python -m pip install ${{ env.install_target }} + + - name: Run smoketest + run: make smoketest test: name: Testing -# needs: [ smoketest ] + needs: [ smoketest ] runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Makefile b/Makefile index f8715eb86..ac2b21f47 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ pull-docker: test: pip install -e .[test] - pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml tests/serverless + pytest -rvx --setup-show --cov=ansys.dynamicreporting.core --cov-report html:coverage-html --cov-report term --cov-report xml:coverage.xml test-dev: pip install -e .[test] From 91999e73950f9d26a6fc40ee897ff583931609f3 Mon Sep 17 00:00:00 2001 From: viseshrp Date: Thu, 10 Apr 2025 17:52:19 -0400 Subject: [PATCH 72/72] Update ci_cd.yml --- .github/workflows/ci_cd.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 399a419b2..37218ec55 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - name: PyAnsys code style checks - uses: ansys/actions/code-style@v8 + uses: ansys/actions/code-style@v9.0 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} show-diff-on-failure: false @@ -55,7 +55,7 @@ jobs: python-version: [ '3.10', '3.11', '3.12', '3.13' ] steps: - name: Build wheelhouse - uses: ansys/actions/build-wheelhouse@v8 + uses: ansys/actions/build-wheelhouse@v9.0 with: library-name: ${{ env.PACKAGE_NAME }} operating-system: ${{ matrix.os }} @@ -75,7 +75,6 @@ jobs: matrix: os: [ ubuntu-latest ] python-version: [ '3.10', '3.11', '3.12', '3.13' ] - steps: - uses: actions/checkout@v4 @@ -118,7 +117,7 @@ jobs: # needs: [docs-style] steps: - name: Run Ansys documentation building action - uses: ansys/actions/doc-build@v8 + uses: ansys/actions/doc-build@v9.0 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} check-links: false @@ -130,7 +129,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Build library source and wheel artifacts - uses: ansys/actions/build-library@v8 + uses: ansys/actions/build-library@v9.0 with: library-name: ${{ env.PACKAGE_NAME }} python-version: ${{ env.MAIN_PYTHON_VERSION }} @@ -142,14 +141,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Release to the public PyPI repository - uses: ansys/actions/release-pypi-public@v8 + uses: ansys/actions/release-pypi-public@v9.0 with: library-name: ${{ env.PACKAGE_NAME }} twine-username: "__token__" twine-token: ${{ secrets.PYPI_TOKEN }} - name: Release to GitHub - uses: ansys/actions/release-github@v8 + uses: ansys/actions/release-github@v9.0 if: ${{ !env.ACT }} with: library-name: ${{ env.PACKAGE_NAME }} @@ -161,7 +160,7 @@ jobs: needs: [ docs, package ] steps: - name: Deploy the latest documentation - uses: ansys/actions/doc-deploy-dev@v8 + uses: ansys/actions/doc-deploy-dev@v9.0 if: ${{ !env.ACT }} with: cname: ${{ env.DOCUMENTATION_CNAME }} @@ -176,7 +175,7 @@ jobs: needs: [ docs, release ] steps: - name: Deploy the stable documentation - uses: ansys/actions/doc-deploy-stable@v8 + uses: ansys/actions/doc-deploy-stable@v9.0 if: ${{ !env.ACT }} with: cname: ${{ env.DOCUMENTATION_CNAME }} @@ -194,7 +193,7 @@ jobs: - name: Microsoft Teams Notification uses: jdcargile/ms-teams-notification@v1.4 with: - github-token: ${{ github.token }} # this will use the runner's token. + github-token: ${{ github.token }} ms-teams-webhook-uri: ${{ secrets.MS_TEAMS_WEBHOOK_URI_CI }} notification-summary: CI build failure notification-color: dc3545