Skip to content

Commit c7d846c

Browse files
Add setdefault classes for dict (pyccel#2033)
Add setdefault classes for dict in python. Fixes pyccel#1888 --------- Co-authored-by: Emily Bourne <[email protected]>
1 parent 386a150 commit c7d846c

File tree

6 files changed

+78
-2
lines changed

6 files changed

+78
-2
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ Contributors
3535
* Shoaib Moeen
3636
* Kush Choudhary
3737
* Emmmanuel Ferdman
38+
* Mohammed Ayaz Shaikh
3839
* Amir Movassaghi

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
1919
- #1895 : Add Python support for dict initialisation with `dict()`.
2020
- #1886 : Add Python support for dict method `pop()`.
2121
- #1887 : Add Python support for dict method `popitem()`.
22+
- #1888 : Add Python support for dict method `setdefault()`.
2223
- #1885 : Add Python support for dict method `get()`.
2324
- #1844 : Add line numbers and code to errors from built-in function calls.
2425
- #1655 : Add the appropriate C language equivalent for declaring a Python `list` container using the STC library.

docs/builtin-functions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Python contains a limited number of builtin functions defined [here](https://doc
128128
| `pop` | Python-only |
129129
| `popitem` | Python-only |
130130
| `reversed` | No |
131-
| `setdefault` | No |
131+
| `setdefault` | Python-only |
132132
| `update` | No |
133133
| `values` | No |
134134

pyccel/ast/builtin_methods/dict_methods.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
'DictMethod',
1818
'DictPop',
1919
'DictPopitem',
20+
'DictSetDefault',
2021
)
2122

2223
#==============================================================================
@@ -176,4 +177,62 @@ def default_value(self):
176177
"""
177178
return self._args[1]
178179

180+
#==============================================================================
181+
182+
class DictSetDefault(DictMethod):
183+
"""
184+
Represents a call to the .setdefault() method.
185+
186+
The setdefault() method set an element in the dict. The element is set
187+
via a key and a value. If the value is not passed then default value is set
188+
as the value.
189+
190+
If returns the value and if it is not present in the dictionary then the default
191+
value is returned.
192+
193+
Parameters
194+
----------
195+
dict_obj : TypedAstNode
196+
The object from which the method is called.
197+
198+
k : TypedAstNode
199+
The key which is used to set the value from the dictionary.
200+
201+
d : TypedAstNode, optional
202+
The value that should be returned. if the value is not present in the
203+
dictionary then default value is returned.
204+
"""
205+
__slots__ = ('_class_type', '_shape')
206+
name = 'setdefault'
207+
208+
def __init__(self, dict_obj, k, d = None):
209+
dict_type = dict_obj.class_type
210+
self._class_type = dict_type.value_type
211+
212+
self._shape = (None) * self._class_type.rank if self._class_type.rank else None
179213

214+
if k.class_type != dict_type.key_type:
215+
raise TypeError(f"Key passed to setdefault method has type {k.class_type}. Expected {dict_type.key_type}")
216+
if d is None:
217+
raise TypeError("None cannot be used as the default argument for the setdefault method.")
218+
if d and d.class_type != dict_type.value_type:
219+
raise TypeError(f"Default value passed to setdefault method has type {d.class_type}. Expected {dict_type.value_type}")
220+
super().__init__(dict_obj, k, d)
221+
222+
@property
223+
def key(self):
224+
"""
225+
The key that is used to select the element from the dict.
226+
227+
The key that is used to select the element from the dict.
228+
"""
229+
return self._args[0]
230+
231+
@property
232+
def default_value(self):
233+
"""
234+
The value that should be returned if the key is not present in the dictionary.
235+
236+
The value that should be returned if the key is not present in the dictionary.
237+
"""
238+
return self._args[1]

pyccel/ast/class_defs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
from pyccel.ast.builtin_methods.list_methods import (ListAppend, ListInsert, ListPop,
1212
ListClear, ListExtend, ListRemove,
1313
ListCopy, ListSort)
14-
from pyccel.ast.builtin_methods.dict_methods import DictPop, DictPopitem, DictGet
14+
from pyccel.ast.builtin_methods.dict_methods import( DictPop, DictPopitem, DictGet,
15+
DictSetDefault)
1516

1617
from .builtins import PythonImag, PythonReal, PythonConjugate
1718
from .core import ClassDef, PyccelFunctionDef
@@ -177,6 +178,7 @@
177178
PyccelFunctionDef('get', func_class = DictGet),
178179
PyccelFunctionDef('pop', func_class = DictPop),
179180
PyccelFunctionDef('popitem', func_class = DictPopitem),
181+
PyccelFunctionDef('setdefault', func_class = DictSetDefault),
180182
])
181183

182184
#=======================================================================================

tests/epyccel/test_epyccel_dicts.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,19 @@ def dict_contains():
192192
assert isinstance(python_result, type(pyccel_result))
193193
assert python_result == pyccel_result
194194

195+
196+
def test_set_default(python_only_language):
197+
def set_default():
198+
a = {1: 1.0, 2:2.0}
199+
b = a.setdefault(1, 3.0)
200+
c = a.setdefault(3, 4.0)
201+
return a, b, c
202+
epyc_str_keys = epyccel(set_default, language = python_only_language)
203+
pyccel_result = epyc_str_keys()
204+
python_result = set_default()
205+
assert isinstance(python_result, type(pyccel_result))
206+
assert python_result == pyccel_result
207+
195208
def test_dict_ptr(python_only_language):
196209
def dict_ptr():
197210
a = {1:1.0, 2:2.0, 3:3.0}

0 commit comments

Comments
 (0)