Skip to content

test

util.test

API test에 유용하게 사용할 수 있는 함수들을 정의한 파일입니다.

thick_divider module-attribute

thick_divider = '=' * 80

thin_divider module-attribute

thin_divider = '-' * 80

tab module-attribute

tab = ' ' * 2

VERBOSE module-attribute

VERBOSE = False

to_string

to_string(obj, indent=4, depth=0)

Recursively convert object to string.

Source code in SaigeToolkit/util/test.py
def to_string(obj, indent=4, depth=0):
    """Recursively convert object to string."""

    if isinstance(obj, Dict) and obj:
        string = "{" + "\n"
        for k, v in obj.items():
            if k in ["polygon"]:
                k = f"{k} (mid point)"
                v = list(np.mean(np.array(v), axis=-2))
            elif k in ["topk_sparse_matrix"]:
                k = f"{k} (mean value)"
                v = np.mean(v)
            string += " " * indent * (depth + 1) + f'"{k}": ' + to_string(v, depth=depth + 1) + ",\n"
        string += " " * indent * depth + "}"
    elif isinstance(obj, List) and obj:
        string = "[" + "\n"
        string += " " * indent * (depth + 1) + to_string(obj[0], depth=depth + 1) + ",\n"
        string += " " * indent * (depth + 1) + f"...  # {len(obj) - 1} results,\n"
        string += " " * indent * depth + "]"
    elif isinstance(obj, Tuple) and obj:
        string = "(" + "\n"
        for v in obj:
            string += " " * indent * (depth + 1) + to_string(v, depth=depth + 1) + ",\n"
        string += " " * indent * depth + ")"
    elif isinstance(obj, (np.ndarray, torch.Tensor)):
        string = f"{type(obj).__name__}({obj.dtype}, shape={obj.shape}, min={obj.min().item()}, max={obj.max().item()})"
    elif isinstance(obj, str):
        string = f'"{obj}"' + f" ({type(obj).__name__})"
    else:
        string = f"{str(obj)} ({type(obj).__name__})"

    return string

get_print_function

get_print_function(error_message_function=lambda x: '')
Source code in SaigeToolkit/util/test.py
def get_print_function(error_message_function=lambda x: ""):
    def type_checker(output, style, key=None):
        if key is not None:
            output = output[key]
            style = style[key]
        # print(output, style, key)
        if not isinstance(output, type(style)):
            raise RuntimeError(f'value type different for "{key}": {type(output)} / {type(style)}')

        if isinstance(output, dict):
            if len(style.keys()) == 0:
                if len(output.keys()) != 0:
                    added = list(output.keys())
                    raise RuntimeError(f"key error: {added} Added")

            elif list(style.keys())[0] == "0":
                type_checker(list(output.values())[0], list(style.values())[0])

            else:
                if set(output.keys()) != set(style.keys()):
                    added = list(set(output.keys()) - set(style.keys()))
                    deleted = list(set(style.keys()) - set(output.keys()))
                    raise RuntimeError(f"key error: {added} Added / {deleted} Deleted")

                for k in output.keys():
                    type_checker(output, style, k)

        elif isinstance(output, list):
            if len(output) == 0:
                if key == "generated_labels":
                    return
                raise RuntimeError("list should have at least one value")
            if len(style) == 0:
                raise RuntimeError("list should have at least one value")

            type_checker(output[0], style[0])

    def check_and_print(message: str, result: Tuple[int, Any], output_style: Optional[Any] = None):
        error, output = result
        _, error_message = error_message_function(error)

        if output_style:
            type_checker(output, output_style)

        if VERBOSE:
            print(thin_divider)
            print(f"{message:60}  |  {'PASSED' if error == 0 else 'FAILED'}")
            print(f"error code: {error}, {error_message}")
            print(f"return value: {to_string(output)}")

        else:
            print(f"{message:60}  |  {'PASSED' if error == 0 else 'FAILED'}  ({error}, {error_message})")

        if error < 0:
            exit(-1)

        return output

    return check_and_print

sweep_options

sweep_options(options: Dict[str, List[Any]])
Source code in SaigeToolkit/util/test.py
def sweep_options(options: Dict[str, List[Any]]):
    option_tuples = [[(name, value) for value in values] for name, values in options.items()]
    return [dict(option) for option in itertools.product(*option_tuples)]

load_numpy_image

load_numpy_image(image_path) -> ndarray
Source code in SaigeToolkit/util/test.py
def load_numpy_image(image_path) -> np.ndarray:
    # 8bit, 16bit 이미지를 그대로 로드하기 위해 PIL.open 대신 cv2.imread 사용
    image = cv2.imread(filename=image_path, flags=cv2.IMREAD_UNCHANGED)
    if image.ndim == 3:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    return image