diff --git a/lib/BUILD b/lib/BUILD index 4435d67..ff49e88 100644 --- a/lib/BUILD +++ b/lib/BUILD @@ -37,7 +37,10 @@ bzl_library( bzl_library( name = "sets", - srcs = ["sets.bzl"], + srcs = [ + "old_sets.bzl", + "sets.bzl", + ], ) bzl_library( diff --git a/lib/old_sets.bzl b/lib/old_sets.bzl new file mode 100644 index 0000000..f62e03d --- /dev/null +++ b/lib/old_sets.bzl @@ -0,0 +1,157 @@ +# Copyright 2017 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. + +"""Skylib module containing common set algorithms. + +CAUTION: Operating on sets, particularly sets contained in providers, may +asymptotically slow down the analysis phase. While constructing large sets with +addition/union is fast (there is no linear-time copy involved), the +`difference` function and various comparison predicates involve linear-time +traversals. + +For convenience, the functions in this module can take either sets or lists as +inputs; operations that take lists treat them as if they were sets (i.e., +duplicate elements are ignored). Functions that return new sets always return +them as the `set` type, regardless of the types of the inputs. +""" + +_depset_type = type(depset()) +_list_type = type([]) + +def _precondition_only_sets_or_lists(*args): + """Verifies that all arguments are either sets or lists. + + The build will fail if any of the arguments is neither a set nor a list. + + Args: + *args: A list of values that must be sets or lists. + """ + for a in args: + t = type(a) + if t not in (_depset_type, _list_type): + fail("Expected arguments to be depset or list, but found type %s: %r" % + (t, a)) + +def _depset_to_list(val): + """Converts a depset to a list. + + If the given value is a depset, will return the list representation of + the depset. Otherwise, will return the value itself. + + Args: + val: The value to be optionally converted and returned. + """ + if type(val) == _depset_type: + return val.to_list() + else: + return val + +def _is_equal(a, b): + """Returns whether two sets are equal. + + Args: + a: A depset or a list. + b: A depset or a list. + + Returns: + True if `a` is equal to `b`, False otherwise. + """ + _precondition_only_sets_or_lists(a, b) + + # Convert both values to a depset then back to a list to remove duplicates. + a = _depset_to_list(depset(a)) + b = _depset_to_list(depset(b)) + return sorted(a) == sorted(b) + +def _is_subset(a, b): + """Returns whether `a` is a subset of `b`. + + Args: + a: A depset or a list. + b: A depset or a list. + + Returns: + True if `a` is a subset of `b`, False otherwise. + """ + _precondition_only_sets_or_lists(a, b) + for e in _depset_to_list(a): + if e not in _depset_to_list(b): + return False + return True + +def _disjoint(a, b): + """Returns whether two sets are disjoint. + + Two sets are disjoint if they have no elements in common. + + Args: + a: A set or list. + b: A set or list. + + Returns: + True if `a` and `b` are disjoint, False otherwise. + """ + _precondition_only_sets_or_lists(a, b) + for e in _depset_to_list(a): + if e in _depset_to_list(b): + return False + return True + +def _intersection(a, b): + """Returns the intersection of two sets. + + Args: + a: A set or list. + b: A set or list. + + Returns: + A set containing the elements that are in both `a` and `b`. + """ + _precondition_only_sets_or_lists(a, b) + return depset([e for e in _depset_to_list(a) if e in _depset_to_list(b)]) + +def _union(*args): + """Returns the union of several sets. + + Args: + *args: An arbitrary number of sets or lists. + + Returns: + The set union of all sets or lists in `*args`. + """ + _precondition_only_sets_or_lists(*args) + args_deps = [depset(x) if type(x) == _list_type else x for x in args] + return depset(transitive = args_deps) + +def _difference(a, b): + """Returns the elements in `a` that are not in `b`. + + Args: + a: A set or list. + b: A set or list. + + Returns: + A set containing the elements that are in `a` but not in `b`. + """ + _precondition_only_sets_or_lists(a, b) + return depset([e for e in _depset_to_list(a) if e not in _depset_to_list(b)]) + +sets = struct( + difference = _difference, + disjoint = _disjoint, + intersection = _intersection, + is_equal = _is_equal, + is_subset = _is_subset, + union = _union, +) diff --git a/lib/sets.bzl b/lib/sets.bzl index f62e03d..15ffc30 100644 --- a/lib/sets.bzl +++ b/lib/sets.bzl @@ -1,4 +1,4 @@ -# Copyright 2017 The Bazel Authors. All rights reserved. +# Copyright 2018 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. @@ -12,146 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Skylib module containing common set algorithms. +"""Skylib module reexporting deprecated set algorithms.""" -CAUTION: Operating on sets, particularly sets contained in providers, may -asymptotically slow down the analysis phase. While constructing large sets with -addition/union is fast (there is no linear-time copy involved), the -`difference` function and various comparison predicates involve linear-time -traversals. +load(":old_sets.bzl", _sets = "sets") -For convenience, the functions in this module can take either sets or lists as -inputs; operations that take lists treat them as if they were sets (i.e., -duplicate elements are ignored). Functions that return new sets always return -them as the `set` type, regardless of the types of the inputs. -""" - -_depset_type = type(depset()) -_list_type = type([]) - -def _precondition_only_sets_or_lists(*args): - """Verifies that all arguments are either sets or lists. - - The build will fail if any of the arguments is neither a set nor a list. - - Args: - *args: A list of values that must be sets or lists. - """ - for a in args: - t = type(a) - if t not in (_depset_type, _list_type): - fail("Expected arguments to be depset or list, but found type %s: %r" % - (t, a)) - -def _depset_to_list(val): - """Converts a depset to a list. - - If the given value is a depset, will return the list representation of - the depset. Otherwise, will return the value itself. - - Args: - val: The value to be optionally converted and returned. - """ - if type(val) == _depset_type: - return val.to_list() - else: - return val - -def _is_equal(a, b): - """Returns whether two sets are equal. - - Args: - a: A depset or a list. - b: A depset or a list. - - Returns: - True if `a` is equal to `b`, False otherwise. - """ - _precondition_only_sets_or_lists(a, b) - - # Convert both values to a depset then back to a list to remove duplicates. - a = _depset_to_list(depset(a)) - b = _depset_to_list(depset(b)) - return sorted(a) == sorted(b) - -def _is_subset(a, b): - """Returns whether `a` is a subset of `b`. - - Args: - a: A depset or a list. - b: A depset or a list. - - Returns: - True if `a` is a subset of `b`, False otherwise. - """ - _precondition_only_sets_or_lists(a, b) - for e in _depset_to_list(a): - if e not in _depset_to_list(b): - return False - return True - -def _disjoint(a, b): - """Returns whether two sets are disjoint. - - Two sets are disjoint if they have no elements in common. - - Args: - a: A set or list. - b: A set or list. - - Returns: - True if `a` and `b` are disjoint, False otherwise. - """ - _precondition_only_sets_or_lists(a, b) - for e in _depset_to_list(a): - if e in _depset_to_list(b): - return False - return True - -def _intersection(a, b): - """Returns the intersection of two sets. - - Args: - a: A set or list. - b: A set or list. - - Returns: - A set containing the elements that are in both `a` and `b`. - """ - _precondition_only_sets_or_lists(a, b) - return depset([e for e in _depset_to_list(a) if e in _depset_to_list(b)]) - -def _union(*args): - """Returns the union of several sets. - - Args: - *args: An arbitrary number of sets or lists. - - Returns: - The set union of all sets or lists in `*args`. - """ - _precondition_only_sets_or_lists(*args) - args_deps = [depset(x) if type(x) == _list_type else x for x in args] - return depset(transitive = args_deps) - -def _difference(a, b): - """Returns the elements in `a` that are not in `b`. - - Args: - a: A set or list. - b: A set or list. - - Returns: - A set containing the elements that are in `a` but not in `b`. - """ - _precondition_only_sets_or_lists(a, b) - return depset([e for e in _depset_to_list(a) if e not in _depset_to_list(b)]) - -sets = struct( - difference = _difference, - disjoint = _disjoint, - intersection = _intersection, - is_equal = _is_equal, - is_subset = _is_subset, - union = _union, -) +sets = _sets