// Copyright 2016 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.syntax; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; import com.google.devtools.build.lib.syntax.SkylarkMutable.MutableMap; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.Nullable; /** * A Skylark dictionary (dict). * *
Although this implements the {@link Map} interface, it is not mutable via that interface's
* methods. Instead, use the mutators that take in a {@link Mutability} object.
*/
@SkylarkModule(
name = "dict",
category = SkylarkModuleCategory.BUILTIN,
doc =
"A language built-in type representating a dictionary (associative mapping). "
+ "Dictionaries may be constructed with a special literal syntax:
"
+ "
d = {\"a\": 2, \"b\": 5}" + "See also the dict() constructor function. " + "When using the literal syntax, it is an error to have duplicated keys. " + "Use square brackets to access elements:
e = d[\"a\"] # e == 2" + "Like lists, they can also be constructed using a comprehension syntax:
d = {i: 2*i for i in range(20)}\n" + "e = d[8] # e == 16" + "Dictionaries are mutable. You can add new elements or mutate existing ones:" + "
d[\"key\"] = 5" + "
Iterating over a dict is equivalent to iterating over its keys. The "
+ "in
operator tests for membership in the keyset of the dict.
"
+ "
\"a\" in {\"a\" : 2, \"b\" : 5} " + "# evaluates as True" + "The iteration order for a dict is deterministic and specified as the order in which " + "the keys have been added to the dict. The iteration order is not affected if a value " + "associated with an existing key is updated." ) public final class SkylarkDict
key
if key
is in the dictionary, "
+ "else default
. If default
is not given, it defaults to "
+ "None
, so that this method never throws an error.",
parameters = {
@Param(name = "key", noneable = true, doc = "The key to look for."),
@Param(name = "default", defaultValue = "None", noneable = true, named = true,
doc = "The default value to use (instead of None) if the key is not found.")},
allowReturnNones = true
)
public Object get(Object key, Object defaultValue) {
if (this.containsKey(key)) {
return this.get(key);
}
return defaultValue;
}
@SkylarkCallable(
name = "pop",
doc =
"Removes a key
from the dict, and returns the associated value. "
+ "If entry with that key was found, return the specified default
value;"
+ "if no default value was specified, fail instead.",
parameters = {
@Param(name = "key", type = Object.class, doc = "The key.", noneable = true),
@Param(name = "default", type = Object.class, defaultValue = "unbound", named = true,
noneable = true, doc = "a default value if the key is absent."),
},
useLocation = true,
useEnvironment = true
)
public Object pop(Object key, Object defaultValue,
Location loc, Environment env)
throws EvalException {
Object value = get(key);
if (value != null) {
remove(key, loc, env.mutability());
return value;
}
if (defaultValue != Runtime.UNBOUND) {
return defaultValue;
}
throw new EvalException(loc, Printer.format("KeyError: %r", key));
}
@SkylarkCallable(
name = "popitem",
doc =
"Remove and return an arbitrary (key, value)
pair from the dictionary. "
+ "popitem()
is useful to destructively iterate over a dictionary, "
+ "as often used in set algorithms. "
+ "If the dictionary is empty, calling popitem()
fails. "
+ "It is deterministic which pair is returned.",
useLocation = true,
useEnvironment = true
)
public Tuple