spdxlicenseidentifier mit spdxfiletext 2021 taneli hukkinen licensed to psf under a contributor agreement utilities for tests that are in the burntsushi format import datetime from typing import any aliases for converting toml compliance format 1 to burntsushi format 2 1 https github comtomllangcomplianceblobdb7c3211fda30ff9ddb10292f4aeda7e2e10abc4docsjsonencoding md noqa e501 2 https github comburntsushitomltestblob4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993readme md noqa e501 aliases boolean bool offset datetime datetime local datetime datetimelocal local date datelocal local time timelocal def convertobj noqa c901 if isinstanceobj str return type string value obj elif isinstanceobj bool return type bool value strobj lower elif isinstanceobj int return type integer value strobj elif isinstanceobj float return type float value normalizefloatstrstrobj elif isinstanceobj datetime datetime val normalizedatetimestrobj isoformat if obj tzinfo return type datetime value val return type datetimelocal value val elif isinstanceobj datetime time return type timelocal value normalizelocaltimestrstrobj elif isinstanceobj datetime date return type datelocal value strobj elif isinstanceobj list return converti for i in obj elif isinstanceobj dict return k convertv for k v in obj items raise exceptionunsupported type def normalizeobj any any if isinstanceobj list return normalizeitem for item in obj if isinstanceobj dict if type in obj and value in obj type objtype normtype aliases gettype type value objvalue if normtype float normvalue normalizefloatstrvalue elif normtype in datetime datetimelocal normvalue normalizedatetimestrvalue elif normtype timelocal normvalue normalizelocaltimestrvalue else normvalue value if normtype array return normalizeitem for item in value return type normtype value normvalue return k normalizev for k v in obj items raise assertionerrorburntsushi fixtures should be dictslists only def normalizedatetimestrdtstr str str if dtstr1 lower z dtstr dtstr 1 00 00 date dtstr 10 rest dtstr11 if in rest sign elif in rest sign else sign if sign time offset rest partitionsign else time rest offset time time rstrip0 if in time else time return date t time sign offset def normalizelocaltimestrltstr str str return ltstr rstrip0 if in ltstr else ltstr def normalizefloatstrfloatstr str str asfloat floatfloatstr normalize 0 0 and 0 0 if asfloat 0 return 0 return strasfloat spdx license identifier mit spdx filetext 2021 taneli hukkinen licensed to psf under a contributor agreement utilities for tests that are in the burntsushi format aliases for converting toml compliance format 1 to burntsushi format 2 1 https github com toml lang compliance blob db7c3211fda30ff9ddb10292f4aeda7e2e10abc4 docs json encoding md noqa e501 2 https github com burntsushi toml test blob 4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993 readme md noqa e501 noqa c901 normalize test objects this normalizes primitive values e g floats and also converts from toml compliance format 1 to burntsushi format 2 1 https github com toml lang compliance blob db7c3211fda30ff9ddb10292f4aeda7e2e10abc4 docs json encoding md noqa e501 2 https github com burntsushi toml test blob 4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993 readme md noqa e501 normalize 0 0 and 0 0
import datetime
from typing import Any




_aliases = {
    "boolean": "bool",
    "offset datetime": "datetime",
    "local datetime": "datetime-local",
    "local date": "date-local",
    "local time": "time-local",
}


def convert(obj):  
    if isinstance(obj, str):
        return {"type": "string", "value": obj}
    elif isinstance(obj, bool):
        return {"type": "bool", "value": str(obj).lower()}
    elif isinstance(obj, int):
        return {"type": "integer", "value": str(obj)}
    elif isinstance(obj, float):
        return {"type": "float", "value": _normalize_float_str(str(obj))}
    elif isinstance(obj, datetime.datetime):
        val = _normalize_datetime_str(obj.isoformat())
        if obj.tzinfo:
            return {"type": "datetime", "value": val}
        return {"type": "datetime-local", "value": val}
    elif isinstance(obj, datetime.time):
        return {
            "type": "time-local",
            "value": _normalize_localtime_str(str(obj)),
        }
    elif isinstance(obj, datetime.date):
        return {
            "type": "date-local",
            "value": str(obj),
        }
    elif isinstance(obj, list):
        return [convert(i) for i in obj]
    elif isinstance(obj, dict):
        return {k: convert(v) for k, v in obj.items()}
    raise Exception("unsupported type")


def normalize(obj: Any) -> Any:
    
    if isinstance(obj, list):
        return [normalize(item) for item in obj]
    if isinstance(obj, dict):
        if "type" in obj and "value" in obj:
            type_ = obj["type"]
            norm_type = _aliases.get(type_, type_)
            value = obj["value"]
            if norm_type == "float":
                norm_value = _normalize_float_str(value)
            elif norm_type in {"datetime", "datetime-local"}:
                norm_value = _normalize_datetime_str(value)
            elif norm_type == "time-local":
                norm_value = _normalize_localtime_str(value)
            else:
                norm_value = value

            if norm_type == "array":
                return [normalize(item) for item in value]
            return {"type": norm_type, "value": norm_value}
        return {k: normalize(v) for k, v in obj.items()}
    raise AssertionError("Burntsushi fixtures should be dicts/lists only")


def _normalize_datetime_str(dt_str: str) -> str:
    if dt_str[-1].lower() == "z":
        dt_str = dt_str[:-1] + "+00:00"

    date = dt_str[:10]
    rest = dt_str[11:]

    if "+" in rest:
        sign = "+"
    elif "-" in rest:
        sign = "-"
    else:
        sign = ""

    if sign:
        time, _, offset = rest.partition(sign)
    else:
        time = rest
        offset = ""

    time = time.rstrip("0") if "." in time else time
    return date + "T" + time + sign + offset


def _normalize_localtime_str(lt_str: str) -> str:
    return lt_str.rstrip("0") if "." in lt_str else lt_str


def _normalize_float_str(float_str: str) -> str:
    as_float = float(float_str)

    
    if as_float == 0:
        return "0"

    return str(as_float)