1# SPDX-License-Identifier: MIT
2# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
3# Licensed to PSF under a Contributor Agreement.
4
5import copy
6import datetime
7from decimal import Decimal as D
8from pathlib import Path
9import sys
10import tempfile
11import unittest
12
13from . import tomllib
14
15
16class TestMiscellaneous(unittest.TestCase):
17    def test_load(self):
18        content = "one=1 \n two='two' \n arr=[]"
19        expected = {"one": 1, "two": "two", "arr": []}
20        with tempfile.TemporaryDirectory() as tmp_dir_path:
21            file_path = Path(tmp_dir_path) / "test.toml"
22            file_path.write_text(content)
23
24            with open(file_path, "rb") as bin_f:
25                actual = tomllib.load(bin_f)
26        self.assertEqual(actual, expected)
27
28    def test_incorrect_load(self):
29        content = "one=1"
30        with tempfile.TemporaryDirectory() as tmp_dir_path:
31            file_path = Path(tmp_dir_path) / "test.toml"
32            file_path.write_text(content)
33
34            with open(file_path, "r") as txt_f:
35                with self.assertRaises(TypeError):
36                    tomllib.load(txt_f)  # type: ignore[arg-type]
37
38    def test_parse_float(self):
39        doc = """
40              val=0.1
41              biggest1=inf
42              biggest2=+inf
43              smallest=-inf
44              notnum1=nan
45              notnum2=-nan
46              notnum3=+nan
47              """
48        obj = tomllib.loads(doc, parse_float=D)
49        expected = {
50            "val": D("0.1"),
51            "biggest1": D("inf"),
52            "biggest2": D("inf"),
53            "smallest": D("-inf"),
54            "notnum1": D("nan"),
55            "notnum2": D("-nan"),
56            "notnum3": D("nan"),
57        }
58        for k, expected_val in expected.items():
59            actual_val = obj[k]
60            self.assertIsInstance(actual_val, D)
61            if actual_val.is_nan():
62                self.assertTrue(expected_val.is_nan())
63            else:
64                self.assertEqual(actual_val, expected_val)
65
66    def test_deepcopy(self):
67        doc = """
68              [bliibaa.diibaa]
69              offsettime=[1979-05-27T00:32:00.999999-07:00]
70              """
71        obj = tomllib.loads(doc)
72        obj_copy = copy.deepcopy(obj)
73        self.assertEqual(obj_copy, obj)
74        expected_obj = {
75            "bliibaa": {
76                "diibaa": {
77                    "offsettime": [
78                        datetime.datetime(
79                            1979,
80                            5,
81                            27,
82                            0,
83                            32,
84                            0,
85                            999999,
86                            tzinfo=datetime.timezone(datetime.timedelta(hours=-7)),
87                        )
88                    ]
89                }
90            }
91        }
92        self.assertEqual(obj_copy, expected_obj)
93
94    def test_inline_array_recursion_limit(self):
95        # 465 with default recursion limit
96        nest_count = int(sys.getrecursionlimit() * 0.465)
97        recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]"
98        tomllib.loads(recursive_array_toml)
99
100    def test_inline_table_recursion_limit(self):
101        # 310 with default recursion limit
102        nest_count = int(sys.getrecursionlimit() * 0.31)
103        recursive_table_toml = nest_count * "key = {" + nest_count * "}"
104        tomllib.loads(recursive_table_toml)
105