17db96d56Sopenharmony_ci# SPDX-License-Identifier: MIT 27db96d56Sopenharmony_ci# SPDX-FileCopyrightText: 2021 Taneli Hukkinen 37db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci"""Utilities for tests that are in the "burntsushi" format.""" 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ciimport datetime 87db96d56Sopenharmony_cifrom typing import Any 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci# Aliases for converting TOML compliance format [1] to BurntSushi format [2] 117db96d56Sopenharmony_ci# [1] https://github.com/toml-lang/compliance/blob/db7c3211fda30ff9ddb10292f4aeda7e2e10abc4/docs/json-encoding.md # noqa: E501 127db96d56Sopenharmony_ci# [2] https://github.com/BurntSushi/toml-test/blob/4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993/README.md # noqa: E501 137db96d56Sopenharmony_ci_aliases = { 147db96d56Sopenharmony_ci "boolean": "bool", 157db96d56Sopenharmony_ci "offset datetime": "datetime", 167db96d56Sopenharmony_ci "local datetime": "datetime-local", 177db96d56Sopenharmony_ci "local date": "date-local", 187db96d56Sopenharmony_ci "local time": "time-local", 197db96d56Sopenharmony_ci} 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_cidef convert(obj): # noqa: C901 237db96d56Sopenharmony_ci if isinstance(obj, str): 247db96d56Sopenharmony_ci return {"type": "string", "value": obj} 257db96d56Sopenharmony_ci elif isinstance(obj, bool): 267db96d56Sopenharmony_ci return {"type": "bool", "value": str(obj).lower()} 277db96d56Sopenharmony_ci elif isinstance(obj, int): 287db96d56Sopenharmony_ci return {"type": "integer", "value": str(obj)} 297db96d56Sopenharmony_ci elif isinstance(obj, float): 307db96d56Sopenharmony_ci return {"type": "float", "value": _normalize_float_str(str(obj))} 317db96d56Sopenharmony_ci elif isinstance(obj, datetime.datetime): 327db96d56Sopenharmony_ci val = _normalize_datetime_str(obj.isoformat()) 337db96d56Sopenharmony_ci if obj.tzinfo: 347db96d56Sopenharmony_ci return {"type": "datetime", "value": val} 357db96d56Sopenharmony_ci return {"type": "datetime-local", "value": val} 367db96d56Sopenharmony_ci elif isinstance(obj, datetime.time): 377db96d56Sopenharmony_ci return { 387db96d56Sopenharmony_ci "type": "time-local", 397db96d56Sopenharmony_ci "value": _normalize_localtime_str(str(obj)), 407db96d56Sopenharmony_ci } 417db96d56Sopenharmony_ci elif isinstance(obj, datetime.date): 427db96d56Sopenharmony_ci return { 437db96d56Sopenharmony_ci "type": "date-local", 447db96d56Sopenharmony_ci "value": str(obj), 457db96d56Sopenharmony_ci } 467db96d56Sopenharmony_ci elif isinstance(obj, list): 477db96d56Sopenharmony_ci return [convert(i) for i in obj] 487db96d56Sopenharmony_ci elif isinstance(obj, dict): 497db96d56Sopenharmony_ci return {k: convert(v) for k, v in obj.items()} 507db96d56Sopenharmony_ci raise Exception("unsupported type") 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_cidef normalize(obj: Any) -> Any: 547db96d56Sopenharmony_ci """Normalize test objects. 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ci This normalizes primitive values (e.g. floats), and also converts from 577db96d56Sopenharmony_ci TOML compliance format [1] to BurntSushi format [2]. 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci [1] https://github.com/toml-lang/compliance/blob/db7c3211fda30ff9ddb10292f4aeda7e2e10abc4/docs/json-encoding.md # noqa: E501 607db96d56Sopenharmony_ci [2] https://github.com/BurntSushi/toml-test/blob/4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993/README.md # noqa: E501 617db96d56Sopenharmony_ci """ 627db96d56Sopenharmony_ci if isinstance(obj, list): 637db96d56Sopenharmony_ci return [normalize(item) for item in obj] 647db96d56Sopenharmony_ci if isinstance(obj, dict): 657db96d56Sopenharmony_ci if "type" in obj and "value" in obj: 667db96d56Sopenharmony_ci type_ = obj["type"] 677db96d56Sopenharmony_ci norm_type = _aliases.get(type_, type_) 687db96d56Sopenharmony_ci value = obj["value"] 697db96d56Sopenharmony_ci if norm_type == "float": 707db96d56Sopenharmony_ci norm_value = _normalize_float_str(value) 717db96d56Sopenharmony_ci elif norm_type in {"datetime", "datetime-local"}: 727db96d56Sopenharmony_ci norm_value = _normalize_datetime_str(value) 737db96d56Sopenharmony_ci elif norm_type == "time-local": 747db96d56Sopenharmony_ci norm_value = _normalize_localtime_str(value) 757db96d56Sopenharmony_ci else: 767db96d56Sopenharmony_ci norm_value = value 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci if norm_type == "array": 797db96d56Sopenharmony_ci return [normalize(item) for item in value] 807db96d56Sopenharmony_ci return {"type": norm_type, "value": norm_value} 817db96d56Sopenharmony_ci return {k: normalize(v) for k, v in obj.items()} 827db96d56Sopenharmony_ci raise AssertionError("Burntsushi fixtures should be dicts/lists only") 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_cidef _normalize_datetime_str(dt_str: str) -> str: 867db96d56Sopenharmony_ci if dt_str[-1].lower() == "z": 877db96d56Sopenharmony_ci dt_str = dt_str[:-1] + "+00:00" 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci date = dt_str[:10] 907db96d56Sopenharmony_ci rest = dt_str[11:] 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci if "+" in rest: 937db96d56Sopenharmony_ci sign = "+" 947db96d56Sopenharmony_ci elif "-" in rest: 957db96d56Sopenharmony_ci sign = "-" 967db96d56Sopenharmony_ci else: 977db96d56Sopenharmony_ci sign = "" 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci if sign: 1007db96d56Sopenharmony_ci time, _, offset = rest.partition(sign) 1017db96d56Sopenharmony_ci else: 1027db96d56Sopenharmony_ci time = rest 1037db96d56Sopenharmony_ci offset = "" 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci time = time.rstrip("0") if "." in time else time 1067db96d56Sopenharmony_ci return date + "T" + time + sign + offset 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_cidef _normalize_localtime_str(lt_str: str) -> str: 1107db96d56Sopenharmony_ci return lt_str.rstrip("0") if "." in lt_str else lt_str 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_cidef _normalize_float_str(float_str: str) -> str: 1147db96d56Sopenharmony_ci as_float = float(float_str) 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci # Normalize "-0.0" and "+0.0" 1177db96d56Sopenharmony_ci if as_float == 0: 1187db96d56Sopenharmony_ci return "0" 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci return str(as_float) 121