github.com/k14s/starlark-go@v0.0.0-20200720175618-3a5c849cc368/starlark/testdata/dict.star (about)

     1  # Tests of Starlark 'dict'
     2  # option:nesteddef
     3  
     4  load("assert.star", "assert", "freeze")
     5  
     6  # literals
     7  assert.eq({}, {})
     8  assert.eq({"a": 1}, {"a": 1})
     9  assert.eq({"a": 1,}, {"a": 1})
    10  
    11  # truth
    12  assert.true({False: False})
    13  assert.true(not {})
    14  
    15  # dict + dict is no longer supported.
    16  assert.fails(lambda: {"a": 1} + {"b": 2}, 'unknown binary op: dict \+ dict')
    17  
    18  # dict comprehension
    19  assert.eq({x: x*x for x in range(3)}, {0: 0, 1: 1, 2: 4})
    20  
    21  # dict.pop
    22  x6 = {"a": 1, "b": 2}
    23  assert.eq(x6.pop("a"), 1)
    24  assert.eq(str(x6), '{"b": 2}')
    25  assert.fails(lambda: x6.pop("c"), "pop: missing key")
    26  assert.eq(x6.pop("c", 3), 3)
    27  assert.eq(x6.pop("c", None), None) # default=None tests an edge case of UnpackArgs
    28  assert.eq(x6.pop("b"), 2)
    29  assert.eq(len(x6), 0)
    30  
    31  # dict.popitem
    32  x7 = {"a": 1, "b": 2}
    33  assert.eq([x7.popitem(), x7.popitem()], [("a", 1), ("b", 2)])
    34  assert.fails(x7.popitem, "empty dict")
    35  assert.eq(len(x7), 0)
    36  
    37  # dict.keys, dict.values
    38  x8 = {"a": 1, "b": 2}
    39  assert.eq(x8.keys(), ["a", "b"])
    40  assert.eq(x8.values(), [1, 2])
    41  
    42  # equality
    43  assert.eq({"a": 1, "b": 2}, {"a": 1, "b": 2})
    44  assert.eq({"a": 1, "b": 2,}, {"a": 1, "b": 2})
    45  assert.eq({"a": 1, "b": 2}, {"b": 2, "a": 1})
    46  
    47  # insertion order is preserved
    48  assert.eq(dict([("a", 0), ("b", 1), ("c", 2), ("b", 3)]).keys(), ["a", "b", "c"])
    49  assert.eq(dict([("b", 0), ("a", 1), ("b", 2), ("c", 3)]).keys(), ["b", "a", "c"])
    50  assert.eq(dict([("b", 0), ("a", 1), ("b", 2), ("c", 3)])["b"], 2)
    51  # ...even after rehashing (which currently occurs after key 'i'):
    52  small = dict([("a", 0), ("b", 1), ("c", 2)])
    53  small.update([("d", 4), ("e", 5), ("f", 6), ("g", 7), ("h", 8), ("i", 9), ("j", 10), ("k", 11)])
    54  assert.eq(small.keys(), ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"])
    55  
    56  # Duplicate keys are not permitted in dictionary expressions (see b/35698444).
    57  # (Nor in keyword args to function calls---checked by resolver.)
    58  assert.fails(lambda: {"aa": 1, "bb": 2, "cc": 3, "bb": 4}, 'duplicate key: "bb"')
    59  
    60  # Check that even with many positional args, keyword collisions are detected.
    61  assert.fails(lambda: dict({'b': 3}, a=4, **dict(a=5)), 'dict: duplicate keyword arg: "a"')
    62  assert.fails(lambda: dict({'a': 2, 'b': 3}, a=4, **dict(a=5)), 'dict: duplicate keyword arg: "a"')
    63  # positional/keyword arg key collisions are ok
    64  assert.eq(dict((['a', 2], ), a=4), {'a': 4})
    65  assert.eq(dict((['a', 2], ['a', 3]), a=4), {'a': 4})
    66  
    67  # index
    68  def setIndex(d, k, v):
    69    d[k] = v
    70  
    71  x9 = {}
    72  assert.fails(lambda: x9["a"], 'key "a" not in dict')
    73  x9["a"] = 1
    74  assert.eq(x9["a"], 1)
    75  assert.eq(x9, {"a": 1})
    76  assert.fails(lambda: setIndex(x9, [], 2), 'unhashable type: list')
    77  freeze(x9)
    78  assert.fails(lambda: setIndex(x9, "a", 3), 'cannot insert into frozen hash table')
    79  
    80  x9a = {}
    81  x9a[1, 2] = 3  # unparenthesized tuple is allowed here
    82  assert.eq(x9a.keys()[0], (1, 2))
    83  
    84  # dict.get
    85  x10 = {"a": 1}
    86  assert.eq(x10.get("a"), 1)
    87  assert.eq(x10.get("b"), None)
    88  assert.eq(x10.get("a", 2), 1)
    89  assert.eq(x10.get("b", 2), 2)
    90  
    91  # dict.clear
    92  x11 = {"a": 1}
    93  assert.contains(x11, "a")
    94  assert.eq(x11["a"], 1)
    95  x11.clear()
    96  assert.fails(lambda: x11["a"], 'key "a" not in dict')
    97  assert.true("a" not in x11)
    98  freeze(x11)
    99  assert.fails(x11.clear, "cannot clear frozen hash table")
   100  
   101  # dict.setdefault
   102  x12 = {"a": 1}
   103  assert.eq(x12.setdefault("a"), 1)
   104  assert.eq(x12["a"], 1)
   105  assert.eq(x12.setdefault("b"), None)
   106  assert.eq(x12["b"], None)
   107  assert.eq(x12.setdefault("c", 2), 2)
   108  assert.eq(x12["c"], 2)
   109  assert.eq(x12.setdefault("c", 3), 2)
   110  assert.eq(x12["c"], 2)
   111  freeze(x12)
   112  assert.eq(x12.setdefault("a", 1), 1) # no change, no error
   113  assert.fails(lambda: x12.setdefault("d", 1), "cannot insert into frozen hash table")
   114  
   115  # dict.update
   116  x13 = {"a": 1}
   117  x13.update(a=2, b=3)
   118  assert.eq(x13, {"a": 2, "b": 3})
   119  x13.update([("b", 4), ("c", 5)])
   120  assert.eq(x13, {"a": 2, "b": 4, "c": 5})
   121  x13.update({"c": 6, "d": 7})
   122  assert.eq(x13, {"a": 2, "b": 4, "c": 6, "d": 7})
   123  freeze(x13)
   124  assert.fails(lambda: x13.update({"a": 8}), "cannot insert into frozen hash table")
   125  
   126  # dict as a sequence
   127  #
   128  # for loop
   129  x14 = {1:2, 3:4}
   130  def keys(dict):
   131    keys = []
   132    for k in dict: keys.append(k)
   133    return keys
   134  assert.eq(keys(x14), [1, 3])
   135  #
   136  # comprehension
   137  assert.eq([x for x in x14], [1, 3])
   138  #
   139  # varargs
   140  def varargs(*args): return args
   141  x15 = {"one": 1}
   142  assert.eq(varargs(*x15), ("one",))
   143  
   144  # kwargs parameter does not alias the **kwargs dict
   145  def kwargs(**kwargs): return kwargs
   146  x16 = kwargs(**x15)
   147  assert.eq(x16, x15)
   148  x15["two"] = 2 # mutate
   149  assert.ne(x16, x15)
   150  
   151  # iterator invalidation
   152  def iterator1():
   153    dict = {1:1, 2:1}
   154    for k in dict:
   155      dict[2*k] = dict[k]
   156  assert.fails(iterator1, "insert.*during iteration")
   157  
   158  def iterator2():
   159    dict = {1:1, 2:1}
   160    for k in dict:
   161      dict.pop(k)
   162  assert.fails(iterator2, "delete.*during iteration")
   163  
   164  def iterator3():
   165    def f(d):
   166      d[3] = 3
   167    dict = {1:1, 2:1}
   168    _ = [f(dict) for x in dict]
   169  assert.fails(iterator3, "insert.*during iteration")
   170  
   171  # This assignment is not a modification-during-iteration:
   172  # the sequence x should be completely iterated before
   173  # the assignment occurs.
   174  def f():
   175    x = {1:2, 2:4}
   176    a, x[0] = x
   177    assert.eq(a, 1)
   178    assert.eq(x, {1: 2, 2: 4, 0: 2})
   179  f()
   180  
   181  # Regression test for a bug in hashtable.delete
   182  def test_delete():
   183    d = {}
   184  
   185    # delete tail first
   186    d["one"] = 1
   187    d["two"] = 2
   188    assert.eq(str(d), '{"one": 1, "two": 2}')
   189    d.pop("two")
   190    assert.eq(str(d), '{"one": 1}')
   191    d.pop("one")
   192    assert.eq(str(d), '{}')
   193  
   194    # delete head first
   195    d["one"] = 1
   196    d["two"] = 2
   197    assert.eq(str(d), '{"one": 1, "two": 2}')
   198    d.pop("one")
   199    assert.eq(str(d), '{"two": 2}')
   200    d.pop("two")
   201    assert.eq(str(d), '{}')
   202  
   203    # delete middle
   204    d["one"] = 1
   205    d["two"] = 2
   206    d["three"] = 3
   207    assert.eq(str(d), '{"one": 1, "two": 2, "three": 3}')
   208    d.pop("two")
   209    assert.eq(str(d), '{"one": 1, "three": 3}')
   210    d.pop("three")
   211    assert.eq(str(d), '{"one": 1}')
   212    d.pop("one")
   213    assert.eq(str(d), '{}')
   214  
   215  test_delete()
   216  
   217  # Regression test for github.com/google/starlark-go/issues/128.
   218  assert.fails(lambda: dict(None), 'got NoneType, want iterable')
   219  assert.fails(lambda: {}.update(None), 'got NoneType, want iterable')
   220  
   221  ---
   222  # Verify position of an "unhashable key" error in a dict literal.
   223  
   224  _ = {
   225      "one": 1,
   226      ["two"]: 2, ### "unhashable type: list"
   227      "three": 3,
   228  }
   229  
   230  ---
   231  # Verify position of a "duplicate key" error in a dict literal.
   232  
   233  _ = {
   234      "one": 1,
   235      "one": 1, ### `duplicate key: "one"`
   236      "three": 3,
   237  }
   238  
   239  ---
   240  # Verify position of an "unhashable key" error in a dict comprehension.
   241  
   242  _ = {
   243      k: v ### "unhashable type: list"
   244      for k, v in [
   245          ("one", 1),
   246          (["two"], 2),
   247          ("three", 3),
   248      ]
   249  }