-
Notifications
You must be signed in to change notification settings - Fork 29
Open
Description
Hi!
I noticed that SDK of version 1.28 fails to parse monetary savings accounts that do not have a savings goal.
How to reproduce:
- Create a sandbox test user
- Create a savings account for it (I did it from the bunq mobile app)
- The output of
curl -s -X GET "https://public-api.sandbox.bunq.com/v1/user/<user_id>/monetary-account-savings"
looks like this:
{
"Response": [
{
"MonetaryAccountSavings": {
"id": <user_id>,
"savings_goal": null,
"savings_goal_progress": null,
// ... other fields
}
}
]
}
- The following reproduce script fails:
#!/usr/bin/env python3
from bunq.sdk.context.api_context import ApiContext
from bunq.sdk.context.bunq_context import BunqContext
from bunq.sdk.model.generated.endpoint import MonetaryAccountSavingsApiObject
from bunq import ApiEnvironmentType
# Setup with sandbox API key
API_KEY = "<api_key>"
api_context = ApiContext.create(ApiEnvironmentType.SANDBOX, API_KEY, "test")
BunqContext.load_api_context(api_context)
# This call fails with: TypeError: float() argument must be a string or a real number, not 'NoneType'
# Error occurs in bunq/sdk/json/float_adapter.py line 16: return float(string)
# when trying to parse null savings_goal_progress as float
savings_accounts = MonetaryAccountSavingsApiObject.list()
print(f"Success: {len(savings_accounts.value)} savings accounts found")
with a stacktrace like this:
Traceback (most recent call last):
File "/home/max/accounting/bunq_crawler/minimal_repro.py", line 14, in <module>
savings_accounts = MonetaryAccountSavingsApiObject.list()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/model/generated/endpoint.py", line 26454, in list
cls._from_json_list(response_raw, cls._OBJECT_TYPE_GET)
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/model/core/bunq_model.py", line 111, in _from_json_list
item_deserialized = converter.deserialize(cls, item_unwrapped)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 464, in deserialize
return JsonAdapter.deserialize(cls, obj_raw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 102, in deserialize
return cls._deserialize_default(cls_target, obj_raw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 117, in _deserialize_default
return cls._deserialize_dict(cls_target, obj_raw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 147, in _deserialize_dict
dict_deserialized = cls._deserialize_dict_attributes(cls_target, dict_)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 163, in _deserialize_dict_attributes
dict_deserialized[value_specs.name] = cls._deserialize_value(value_specs.types, dict_[key])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 307, in _deserialize_value
return cls.deserialize(types.main, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/converter.py", line 104, in deserialize
return deserializer.deserialize(cls_target, obj_raw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/max/.local/lib/python3.11/site-packages/bunq/sdk/json/float_adapter.py", line 16, in deserialize
return float(string)
^^^^^^^^^^^^^
TypeError: float() argument must be a string or a real number, not 'NoneType'
I verified using a debugger that the issue is indeed in the savings_goal_progress key. I thought about bringing a PR with a fix, but I am not entirely sure, whether it is an SDK bug (it should handle nulls gracefully), or an API issue (it should not emit keys with null values). According to the documentation, the field "savings_goal_progress" is optional, but it confuses me that I don't see any examples of handling optional primitive values around the sdk/json.
Workaround: setting a saving goal to any amount.
Metadata
Metadata
Assignees
Labels
No labels