Skip to content

Commit

Permalink
Add types.is_set() to test whether an arbitrary object is a set as de…
Browse files Browse the repository at this point in the history
…fined by new_sets.bzl. (bazelbuild#181)

* Add sets.is_set() to test whether an arbitrary object is a set.

Since using sets requires special API, it can be useful to determine
whether an object is a set so special handling can be used.
For example, if a method wants to be able to take a list or a set.
  • Loading branch information
techsy730 authored and c-parsons committed Sep 17, 2019
1 parent 58068fe commit 3154dbb
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ bzl_library(
bzl_library(
name = "new_sets",
srcs = ["new_sets.bzl"],
deps = [":dicts"],
deps = [
":dicts",
],
)

bzl_library(
Expand Down
6 changes: 6 additions & 0 deletions lib/new_sets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
if you pass it an sequence: `sets.make([1, 2, 3])`. This returns a struct containing all of the
values as keys in a dictionary - this means that all passed in values must be hashable. The
values in the set can be retrieved using `sets.to_list(my_set)`.
An arbitrary object can be tested whether it is a set generated by `sets.make()` or not with the
`types.is_set()` method in types.bzl.
"""

load(":dicts.bzl", "dicts")
Expand All @@ -33,6 +36,8 @@ def _make(elements = None):
Returns:
A set containing the passed in values.
"""
# If you change the structure of a set, you need to also update the _is_set method
# in types.bzl.
elements = elements if elements else []
return struct(_values = {e: None for e in elements})

Expand Down Expand Up @@ -233,4 +238,5 @@ sets = struct(
remove = _remove,
repr = _repr,
str = _repr,
# is_set is declared in types.bzl
)
13 changes: 13 additions & 0 deletions lib/types.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ _a_string_type = type("")
_a_tuple_type = type(())
_an_int_type = type(1)
_a_depset_type = type(depset())
_a_struct_type = type(struct())

def _a_function():
pass
Expand Down Expand Up @@ -126,6 +127,17 @@ def _is_depset(v):
"""
return type(v) == _a_depset_type

def _is_set(v):
"""Returns True if v is a set created by sets.make().
Args:
v: The value whose type should be checked.
Returns:
True if v was created by sets.make(), False otherwise.
"""
return type(v) == _a_struct_type and hasattr(v, "_values") and _is_dict(v._values)

types = struct(
is_list = _is_list,
is_string = _is_string,
Expand All @@ -136,4 +148,5 @@ types = struct(
is_dict = _is_dict,
is_function = _is_function,
is_depset = _is_depset,
is_set = _is_set,
)
17 changes: 17 additions & 0 deletions tests/types_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

load("//lib:types.bzl", "types")
load("//lib:unittest.bzl", "asserts", "unittest")
load("//lib:new_sets.bzl", "sets")

def _a_function():
"""A dummy function for testing."""
Expand Down Expand Up @@ -215,6 +216,21 @@ def _is_depset_test(ctx):

is_depset_test = unittest.make(_is_depset_test)

def _is_set_test(ctx):
"""Unit test for types.is_set."""
env = unittest.begin(ctx)

asserts.true(env, types.is_set(sets.make()))
asserts.true(env, types.is_set(sets.make([1])))
asserts.false(env, types.is_set(None))
asserts.false(env, types.is_set({}))
asserts.false(env, types.is_set(struct(foo = 1)))
asserts.false(env, types.is_set(struct(_values = "not really values")))

return unittest.end(env)

is_set_test = unittest.make(_is_set_test)

def types_test_suite():
"""Creates the test targets and test suite for types.bzl tests."""
unittest.suite(
Expand All @@ -228,4 +244,5 @@ def types_test_suite():
is_dict_test,
is_function_test,
is_depset_test,
is_set_test,
)

0 comments on commit 3154dbb

Please sign in to comment.