diff --git a/asyncpg/types.py b/asyncpg/types.py index 5124718f..bd5813fc 100644 --- a/asyncpg/types.py +++ b/asyncpg/types.py @@ -85,6 +85,39 @@ def upper_inf(self): def isempty(self): return self._empty + def _issubset_lower(self, other): + if other._lower is None: + return True + if self._lower is None: + return False + + return self._lower > other._lower or ( + self._lower == other._lower + and (other._lower_inc or not self._lower_inc) + ) + + def _issubset_upper(self, other): + if other._upper is None: + return True + if self._upper is None: + return False + + return self._upper < other._upper or ( + self._upper == other._upper + and (other._upper_inc or not self._upper_inc) + ) + + def issubset(self, other): + if self._empty: + return True + if other._empty: + return False + + return self._issubset_lower(other) and self._issubset_upper(other) + + def issuperset(self, other): + return other.issubset(self) + def __bool__(self): return not self._empty diff --git a/tests/test_types.py b/tests/test_types.py new file mode 100644 index 00000000..04241953 --- /dev/null +++ b/tests/test_types.py @@ -0,0 +1,56 @@ +# Copyright (C) 2016-present the ayncpg authors and contributors +# +# +# This module is part of asyncpg and is released under +# the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 + +from itertools import product + +from asyncpg.types import Range +from asyncpg import _testbase as tb + + +class TestTypes(tb.TestCase): + + def test_range_issubset(self): + subs = [ + Range(empty=True), + Range(lower=1, upper=5, lower_inc=True, upper_inc=False), + Range(lower=1, upper=5, lower_inc=True, upper_inc=True), + Range(lower=1, upper=5, lower_inc=False, upper_inc=True), + Range(lower=1, upper=5, lower_inc=False, upper_inc=False), + Range(lower=-5, upper=10), + Range(lower=2, upper=3), + Range(lower=1, upper=None), + Range(lower=None, upper=None) + ] + + sups = [ + Range(empty=True), + Range(lower=1, upper=5, lower_inc=True, upper_inc=False), + Range(lower=1, upper=5, lower_inc=True, upper_inc=True), + Range(lower=1, upper=5, lower_inc=False, upper_inc=True), + Range(lower=1, upper=5, lower_inc=False, upper_inc=False), + Range(lower=None, upper=None) + ] + + # Each row is 1 subs with all sups + results = [ + True, True, True, True, True, True, + False, True, True, False, False, True, + False, False, True, False, False, True, + False, False, True, True, False, True, + False, True, True, True, True, True, + False, False, False, False, False, True, + False, True, True, True, True, True, + False, False, False, False, False, True, + False, False, False, False, False, True + ] + + for (sub, sup), res in zip(product(subs, sups), results): + self.assertIs( + sub.issubset(sup), res, "Sub:{}, Sup:{}".format(sub, sup) + ) + self.assertIs( + sup.issuperset(sub), res, "Sub:{}, Sup:{}".format(sub, sup) + )