Skip to content

Commit dc0b808

Browse files
authored
Merge pull request #459 from SameeraSomisetty/master
to allow "default" parameter in min and max issue 334
2 parents 0d8c482 + 61c9aec commit dc0b808

File tree

5 files changed

+83
-6
lines changed

5 files changed

+83
-6
lines changed

src/future/builtins/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# The isinstance import is no longer needed. We provide it only for
1212
# backward-compatibility with future v0.8.2. It will be removed in future v1.0.
1313
from future.builtins.misc import (ascii, chr, hex, input, isinstance, next,
14-
oct, open, pow, round, super)
14+
oct, open, pow, round, super, max, min)
1515
from future.utils import PY3
1616

1717
if PY3:
@@ -43,7 +43,7 @@
4343
__all__ = ['filter', 'map', 'zip',
4444
'ascii', 'chr', 'hex', 'input', 'next', 'oct', 'open', 'pow',
4545
'round', 'super',
46-
'bytes', 'dict', 'int', 'list', 'object', 'range', 'str',
46+
'bytes', 'dict', 'int', 'list', 'object', 'range', 'str', 'max', 'min'
4747
]
4848

4949
else:

src/future/builtins/misc.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
- ``open`` (equivalent to io.open on Py2)
1414
- ``super`` (backport of Py3's magic zero-argument super() function
1515
- ``round`` (new "Banker's Rounding" behaviour from Py3)
16+
- ``max`` (new default option from Py3.4)
17+
- ``min`` (new default option from Py3.4)
1618
1719
``isinstance`` is also currently exported for backwards compatibility
1820
with v0.8.2, although this has been deprecated since v0.9.
@@ -59,6 +61,8 @@
5961
from future.builtins.newnext import newnext as next
6062
from future.builtins.newround import newround as round
6163
from future.builtins.newsuper import newsuper as super
64+
from future.builtins.new_min_max import newmax as max
65+
from future.builtins.new_min_max import newmin as min
6266
from future.types.newint import newint
6367

6468
_SENTINEL = object()
@@ -89,11 +93,12 @@ def pow(x, y, z=_SENTINEL):
8993
else:
9094
return _builtin_pow(x+0j, y, z)
9195

96+
9297
# ``future`` doesn't support Py3.0/3.1. If we ever did, we'd add this:
9398
# callable = __builtin__.callable
9499

95100
__all__ = ['ascii', 'chr', 'hex', 'input', 'isinstance', 'next', 'oct',
96-
'open', 'pow', 'round', 'super']
101+
'open', 'pow', 'round', 'super', 'max', 'min']
97102

98103
else:
99104
import builtins
@@ -109,8 +114,14 @@ def pow(x, y, z=_SENTINEL):
109114
pow = builtins.pow
110115
round = builtins.round
111116
super = builtins.super
112-
113-
__all__ = []
117+
if utils.PY34_PLUS:
118+
max = builtins.max
119+
min = builtins.min
120+
__all__ = []
121+
else:
122+
from future.builtins.new_min_max import newmax as max
123+
from future.builtins.new_min_max import newmin as min
124+
__all__ = ['min', 'max']
114125

115126
# The callable() function was removed from Py3.0 and 3.1 and
116127
# reintroduced into Py3.2+. ``future`` doesn't support Py3.0/3.1. If we ever

src/future/builtins/new_min_max.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from future import utils
2+
if utils.PY2:
3+
from __builtin__ import max as _builtin_max, min as _builtin_min
4+
else:
5+
from builtins import max as _builtin_max, min as _builtin_min
6+
7+
8+
def newmin(*args, **kwargs):
9+
return new_min_max(_builtin_min, *args, **kwargs)
10+
11+
12+
def newmax(*args, **kwargs):
13+
return new_min_max(_builtin_max, *args, **kwargs)
14+
15+
16+
def new_min_max(_builtin_func, *args, **kwargs):
17+
"""
18+
To support the argument "default" introduced in python 3.4 for min and max
19+
:param _builtin_func: builtin min or builtin max
20+
:param args:
21+
:param kwargs:
22+
:return: returns the min or max based on the arguments passed
23+
"""
24+
25+
for key, _ in kwargs.items():
26+
if key not in set(['key', 'default']):
27+
raise TypeError('Illegal argument %s', key)
28+
29+
if len(args) == 0:
30+
raise TypeError
31+
32+
if len(args) != 1 and kwargs.get('default') is not None:
33+
raise TypeError
34+
35+
if len(args) == 1:
36+
try:
37+
next(iter(args[0]))
38+
except StopIteration:
39+
if kwargs.get('default') is not None:
40+
return kwargs.get('default')
41+
else:
42+
raise ValueError('iterable is an empty sequence')
43+
if kwargs.get('key') is not None:
44+
return _builtin_func(args[0], key=kwargs.get('key'))
45+
else:
46+
return _builtin_func(args[0])
47+
48+
if len(args) > 1:
49+
if kwargs.get('key') is not None:
50+
return _builtin_func(args, key=kwargs.get('key'))
51+
else:
52+
return _builtin_func(args)

src/future/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656

5757

5858
PY3 = sys.version_info[0] >= 3
59+
PY34_PLUS = sys.version_info[0:2] >= (3, 4)
5960
PY35_PLUS = sys.version_info[0:2] >= (3, 5)
6061
PY36_PLUS = sys.version_info[0:2] >= (3, 6)
6162
PY2 = sys.version_info[0] == 2

tests/test_future/test_builtins.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from __future__ import absolute_import, division, print_function, unicode_literals
77
from future.builtins import (bytes, dict, int, range, round, str, super,
88
ascii, chr, hex, input, next, oct, open, pow,
9-
filter, map, zip)
9+
filter, map, zip, min, max)
1010

1111
from future.utils import PY3, exec_, native_str, implements_iterator
1212
from future.tests.base import (unittest, skip26, expectedFailurePY2,
@@ -1099,6 +1099,13 @@ def test_max(self):
10991099
self.assertEqual(max(data, key=f),
11001100
sorted(reversed(data), key=f)[-1])
11011101

1102+
self.assertEqual(max([], default=5), 5)
1103+
with self.assertRaises(TypeError):
1104+
max(None, default=5)
1105+
with self.assertRaises(TypeError):
1106+
max(1, 2, default=0)
1107+
self.assertEqual(max([], default=0), 0)
1108+
11021109
def test_min(self):
11031110
self.assertEqual(min('123123'), '1')
11041111
self.assertEqual(min(1, 2, 3), 1)
@@ -1140,6 +1147,12 @@ def __getitem__(self, index):
11401147
f = keys.__getitem__
11411148
self.assertEqual(min(data, key=f),
11421149
sorted(data, key=f)[0])
1150+
self.assertEqual(min([], default=5), 5)
1151+
self.assertEqual(min([], default=0), 0)
1152+
with self.assertRaises(TypeError):
1153+
max(None, default=5)
1154+
with self.assertRaises(TypeError):
1155+
max(1, 2, default=0)
11431156

11441157
def test_next(self):
11451158
it = iter(range(2))

0 commit comments

Comments
 (0)