@@ -326,7 +326,7 @@ func (d *Dict) incVersion() {
326326// DelItem removes the entry associated with key from d. It returns true if an
327327// item was removed, or false if it did not exist in d.
328328func (d * Dict ) DelItem (f * Frame , key * Object ) (bool , * BaseException ) {
329- originValue , raised := d .putItem (f , key , nil )
329+ originValue , raised := d .putItem (f , key , nil , true )
330330 if raised != nil {
331331 return false , raised
332332 }
@@ -365,7 +365,7 @@ func (d *Dict) GetItemString(f *Frame, key string) (*Object, *BaseException) {
365365// Pop looks up key in d, returning and removing the associalted value if exist,
366366// or nil if key is not present in d.
367367func (d * Dict ) Pop (f * Frame , key * Object ) (* Object , * BaseException ) {
368- return d .putItem (f , key , nil )
368+ return d .putItem (f , key , nil , true )
369369}
370370
371371// Keys returns a list containing all the keys in d.
@@ -390,7 +390,7 @@ func (d *Dict) Len() int {
390390
391391// putItem associates value with key in d, returning the old associated value if
392392// the key was added, or nil if it was not already present in d.
393- func (d * Dict ) putItem (f * Frame , key , value * Object ) (* Object , * BaseException ) {
393+ func (d * Dict ) putItem (f * Frame , key , value * Object , overwrite bool ) (* Object , * BaseException ) {
394394 hash , raised := Hash (f , key )
395395 if raised != nil {
396396 return nil , raised
@@ -413,7 +413,7 @@ func (d *Dict) putItem(f *Frame, key, value *Object) (*Object, *BaseException) {
413413 d .table .incUsed (- 1 )
414414 d .incVersion ()
415415 }
416- } else {
416+ } else if overwrite || entry == nil {
417417 newEntry := & dictEntry {hash .Value (), key , value }
418418 if newTable , ok := t .writeEntry (f , index , newEntry ); ok {
419419 if newTable != nil {
@@ -435,7 +435,7 @@ func (d *Dict) putItem(f *Frame, key, value *Object) (*Object, *BaseException) {
435435
436436// SetItem associates value with key in d.
437437func (d * Dict ) SetItem (f * Frame , key , value * Object ) * BaseException {
438- _ , raised := d .putItem (f , key , value )
438+ _ , raised := d .putItem (f , key , value , true )
439439 return raised
440440}
441441
@@ -755,6 +755,36 @@ func dictRepr(f *Frame, o *Object) (*Object, *BaseException) {
755755 return NewStr (buf .String ()).ToObject (), nil
756756}
757757
758+ func dictSetDefault (f * Frame , args Args , _ KWArgs ) (* Object , * BaseException ) {
759+ argc := len (args )
760+ if argc == 1 {
761+ return nil , f .RaiseType (TypeErrorType , "setdefault expected at least 1 arguments, got 0" )
762+ }
763+ if argc > 3 {
764+ return nil , f .RaiseType (TypeErrorType , fmt .Sprintf ("setdefault expected at most 2 arguments, got %v" , argc - 1 ))
765+ }
766+ expectedTypes := []* Type {DictType , ObjectType , ObjectType }
767+ if argc == 2 {
768+ expectedTypes = expectedTypes [:2 ]
769+ }
770+ if raised := checkMethodArgs (f , "setdefault" , args , expectedTypes ... ); raised != nil {
771+ return nil , raised
772+ }
773+ d := toDictUnsafe (args [0 ])
774+ key := args [1 ]
775+ var value * Object
776+ if argc > 2 {
777+ value = args [2 ]
778+ } else {
779+ value = None
780+ }
781+ originValue , raised := d .putItem (f , key , value , false )
782+ if originValue != nil {
783+ return originValue , raised
784+ }
785+ return value , raised
786+ }
787+
758788func dictSetItem (f * Frame , o , key , value * Object ) * BaseException {
759789 return toDictUnsafe (o ).SetItem (f , key , value )
760790}
@@ -803,6 +833,7 @@ func initDictType(dict map[string]*Object) {
803833 dict ["itervalues" ] = newBuiltinFunction ("itervalues" , dictIterValues ).ToObject ()
804834 dict ["keys" ] = newBuiltinFunction ("keys" , dictKeys ).ToObject ()
805835 dict ["pop" ] = newBuiltinFunction ("pop" , dictPop ).ToObject ()
836+ dict ["setdefault" ] = newBuiltinFunction ("setdefault" , dictSetDefault ).ToObject ()
806837 dict ["update" ] = newBuiltinFunction ("update" , dictUpdate ).ToObject ()
807838 dict ["values" ] = newBuiltinFunction ("values" , dictValues ).ToObject ()
808839 DictType .slots .Contains = & binaryOpSlot {dictContains }
0 commit comments