github.com/google/skylark@v0.0.0-20181101142754-a5f7082aabed/testdata/dict.sky (about)

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