Skip to content
Snippets Groups Projects
Select Git revision
  • b767a8c141de04906c4db5b695ae2e901b303545
  • main default protected
  • f-yaml-parser-enums
  • dev protected
  • f-fix-paths
  • f-fix-validate-to-dict
  • f-labfolder-converter
  • f-state-machine-script
  • f-xlsx-converter-warnings-errors
  • f-rename
  • f-extra-deps
  • f-more-jsonschema-export
  • f-henrik
  • f-fix-89
  • f-trigger-advanced-user-tools
  • f-real-rename-test
  • f-linkahead-rename
  • f-register-integrationtests
  • f-fix-id
  • f-h5-files
  • f-json-schema
  • v0.14.0
  • v0.13.0
  • v0.12.0
  • v0.11.0
  • v0.10.0-numpy2
  • v0.10.0
  • v0.9.0
  • v0.8.0
  • v0.7.0
  • v0.6.1
  • v0.6.0
  • v0.5.0
  • v0.4.1
  • v0.4.0
  • v0.3.1
  • v0.3.0
37 results

cfood.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    utils.py 4.68 KiB
    # encoding: utf-8
    #
    # This file is a part of the LinkAhead Project.
    #
    # Copyright (C) 2024 IndiScale GmbH <info@indiscale.com>
    # Copyright (C) 2024 Daniel Hornung <d.hornung@indiscale.com>
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Affero General Public License as
    # published by the Free Software Foundation, either version 3 of the
    # License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU Affero General Public License for more details.
    #
    # You should have received a copy of the GNU Affero General Public License
    # along with this program. If not, see <https://www.gnu.org/licenses/>.
    
    """Utilities for the tests.
    """
    
    from typing import Iterable, Union
    
    from openpyxl import Workbook
    
    
    def assert_equal_jsons(json1, json2, allow_none: bool = True, allow_empty: bool = True,
                           path: list = None) -> None:
        """Compare two json objects for near equality.
    
    Raise an assertion exception if they are not equal."""
        if path is None:
            path = []
        assert isinstance(json1, dict) == isinstance(json2, dict), f"Type mismatch, path: {path}"
        if isinstance(json1, dict):
            keys = set(json1.keys()).union(json2.keys())
            for key in keys:
                this_path = path + [key]
                # Case 1: exists in both collections
                if key in json1 and key in json2:
                    el1 = json1[key]
                    el2 = json2[key]
                    assert type(el1) is type(el2), f"Type mismatch, path: {this_path}"
                    if isinstance(el1, (dict, list)):
                        # Iterables: Recursion
                        assert_equal_jsons(el1, el2, allow_none=allow_none, allow_empty=allow_empty,
                                           path=this_path)
                        continue
                    assert el1 == el2, f"Values at path {this_path} are not equal:\n{el1},\n{el2}"
                    continue
                # Case 2: exists only in one collection
                existing = json1.get(key, json2.get(key))
                assert ((allow_none and _is_recursively_none(existing))
                        or (allow_empty and existing == [])), (
                    f"Element at path {this_path} is None or empty in one json and does not exist in "
                    "the other.")
            return
        assert isinstance(json1, list) and isinstance(json2, list), f"Is not a list, path: {path}"
        assert len(json1) == len(json2), f"Lists must have equal length, path: {path}"
        for idx, (el1, el2) in enumerate(zip(json1, json2)):
            this_path = path + [idx]
            if isinstance(el1, dict):
                assert_equal_jsons(el1, el2, allow_none=allow_none, allow_empty=allow_empty,
                                   path=this_path)
            else:
                assert el1 == el2
    
    
    def compare_workbooks(wb1: Workbook, wb2: Workbook, hidden: bool = True):
        """Compare two workbooks for equal content.
    
    Raises an error if differences are found.
    
    Parameters
    ----------
    
    hidden: bool, optional
      Test if the "hidden" status of rows and columns is the same.
        """
        assert wb1.sheetnames == wb2.sheetnames, (
            f"Sheet names are different: \n{wb1.sheetnames}\n   !=\n{wb2.sheetnames}"
        )
        for sheetname in wb2.sheetnames:
            sheet_1 = wb1[sheetname]
            sheet_2 = wb2[sheetname]
            for irow, (row1, row2) in enumerate(zip(sheet_1.iter_rows(), sheet_2.iter_rows())):
                if hidden:
                    assert (sheet_1.row_dimensions[irow].hidden
                            == sheet_2.row_dimensions[irow].hidden), f"hidden row: {sheetname}, {irow}"
                for icol, (cell1, cell2) in enumerate(zip(row1, row2)):
                    if hidden:
                        assert (sheet_1.column_dimensions[cell1.column_letter].hidden
                                == sheet_2.column_dimensions[cell2.column_letter].hidden), (
                                    f"hidden col: {sheetname}, {icol}")
                    assert cell1.value == cell2.value, (
                        f"Sheet: {sheetname}, cell: {cell1.coordinate}, Values: \n"
                        f"{cell1.value}\n{cell2.value}"
                    )
    
    
    def _is_recursively_none(obj: Union[list, dict] = None):
        """Test if ``obj`` is None or recursively consists only of None-like objects."""
        if obj is None:
            return True
        if isinstance(obj, (list, dict)):
            if isinstance(obj, list):
                mylist: Iterable = obj
            else:
                mylist = obj.values()
            for element in mylist:
                if not _is_recursively_none(element):
                    return False
            return True
        return False