@@ -425,9 +425,26 @@ mod decl {
425
425
}
426
426
427
427
#[ pyfunction]
428
- fn max ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
428
+ fn max ( vm : & VirtualMachine , mut args : PyFuncArgs ) -> PyResult {
429
+ let default = args. take_keyword ( "default" ) ;
430
+ let key_func = args. take_keyword ( "key" ) ;
431
+ if !args. kwargs . is_empty ( ) {
432
+ let invalid_keyword = args. kwargs . get_index ( 0 ) . unwrap ( ) ;
433
+ return Err ( vm. new_type_error ( format ! (
434
+ "'{}' is an invalid keyword argument for max()" ,
435
+ invalid_keyword. 0
436
+ ) ) ) ;
437
+ }
429
438
let candidates = match args. args . len ( ) . cmp ( & 1 ) {
430
- std:: cmp:: Ordering :: Greater => args. args . clone ( ) ,
439
+ std:: cmp:: Ordering :: Greater => {
440
+ if default. is_some ( ) {
441
+ return Err ( vm. new_type_error (
442
+ "Cannot specify a default for max() with multiple positional arguments"
443
+ . to_owned ( ) ,
444
+ ) ) ;
445
+ }
446
+ args. args . clone ( )
447
+ }
431
448
std:: cmp:: Ordering :: Equal => vm. extract_elements ( & args. args [ 0 ] ) ?,
432
449
std:: cmp:: Ordering :: Less => {
433
450
// zero arguments means type error:
@@ -436,27 +453,32 @@ mod decl {
436
453
} ;
437
454
438
455
if candidates. is_empty ( ) {
439
- let default = args. get_optional_kwarg ( "default" ) ;
440
456
return default
441
457
. ok_or_else ( || vm. new_value_error ( "max() arg is an empty sequence" . to_owned ( ) ) ) ;
442
458
}
443
459
444
- let key_func = args. get_optional_kwarg ( "key" ) ;
445
-
446
460
// Start with first assumption:
447
461
let mut candidates_iter = candidates. into_iter ( ) ;
448
462
let mut x = candidates_iter. next ( ) . unwrap ( ) ;
449
463
// TODO: this key function looks pretty duplicate. Maybe we can create
450
464
// a local function?
451
465
let mut x_key = if let Some ( ref f) = & key_func {
452
- vm. invoke ( f, vec ! [ x. clone( ) ] ) ?
466
+ if vm. is_none ( f) {
467
+ x. clone ( )
468
+ } else {
469
+ vm. invoke ( f, vec ! [ x. clone( ) ] ) ?
470
+ }
453
471
} else {
454
472
x. clone ( )
455
473
} ;
456
474
457
475
for y in candidates_iter {
458
476
let y_key = if let Some ( ref f) = & key_func {
459
- vm. invoke ( f, vec ! [ y. clone( ) ] ) ?
477
+ if vm. is_none ( f) {
478
+ y. clone ( )
479
+ } else {
480
+ vm. invoke ( f, vec ! [ y. clone( ) ] ) ?
481
+ }
460
482
} else {
461
483
y. clone ( )
462
484
} ;
0 commit comments