From 1a0533d9f6b9444907f8fc9a5d2dab79b2584a69 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 14 Oct 2020 20:29:49 -0700 Subject: [PATCH] fixes #315: add min/max with default key. Also fix tests on windows --- six.py | 38 ++++++++++++++++++++++++++++++++++++++ test_six.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/six.py b/six.py index 83f69783d..0e90386be 100644 --- a/six.py +++ b/six.py @@ -957,6 +957,44 @@ def python_2_unicode_compatible(klass): return klass +if PY2: + def min(*iterable, key=None, default=None): + """ + min(...) + min(iterable, *[, default=obj, key=func]) -> value + min(arg1, arg2, *args, *[, key=func]) -> value + + With a single iterable argument, return its smallest item. The + default keyword-only argument specifies an object to return if + the provided iterable is empty. + With two or more arguments, return the smallest argument. + """ + if default is not None and len(iterable) == 1 and len(iterable[0]) == 0: + return default + + return __builtins__['min'](*iterable, key=key) + + + def max(*iterable, key=None, default=None): + """ + max(...) + max(iterable, *[, default=obj, key=func]) -> value + max(arg1, arg2, *args, *[, key=func]) -> value + + With a single iterable argument, return its biggest item. The + default keyword-only argument specifies an object to return if + the provided iterable is empty. + With two or more arguments, return the largest argument. + """ + if default is not None and len(iterable) == 1 and len(iterable[0]) == 0: + return default + + return __builtins__['max'](*iterable, key=key) +else: + min = __builtins__['min'] + max = __builtins__['max'] + + # Complete the moves implementation. # This code is at the end of this module to speed up module loading. # Turn this module into a package. diff --git a/test_six.py b/test_six.py index 7b8b03b5e..be0d4a313 100644 --- a/test_six.py +++ b/test_six.py @@ -113,6 +113,12 @@ def test_lazy(): except ImportError: have_gdbm = False +have_ndbm = True +try: + import dbm.ndbm +except ImportError: + have_ndbm = False + @pytest.mark.parametrize("item_name", [item.name for item in six._moved_attributes]) def test_move_items(item_name): @@ -124,11 +130,12 @@ def test_move_items(item_name): except ImportError: if item_name == "winreg" and not sys.platform.startswith("win"): pytest.skip("Windows only module") - if item_name.startswith("tkinter"): - if not have_tkinter: - pytest.skip("requires tkinter") + if item_name.startswith("tkinter") and not have_tkinter: + pytest.skip("requires tkinter") if item_name.startswith("dbm_gnu") and not have_gdbm: pytest.skip("requires gdbm") + if item_name == 'dbm_ndbm' and not have_ndbm: + pytest.skip("requires ndbm") raise assert item_name in dir(six.moves) @@ -220,7 +227,7 @@ def test_map(): def test_getoutput(): from six.moves import getoutput - output = getoutput('echo "foo"') + output = getoutput('echo foo') assert output == 'foo' @@ -1039,3 +1046,19 @@ def test_ensure_text(self): assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, str) # PY3: bytes -> str assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, str) + + + @pytest.mark.parametrize('func_name', ['min', 'max']) + def test_min_max(self, func_name): + func = six.__builtins__[func_name] + six_func = getattr(six, func_name) + + assert func([1,2]) == six_func([1,2]) + assert func(1, 2) == six_func(1, 2) + + def key(l): + return l[1] + + assert func([9, 1], [3, 4], key=key) == six_func([9, 1], [3, 4], key=key) + + assert six_func([], default=12) == 12 \ No newline at end of file