Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add include_none_values ClassVar to JSONObject; apply to response-only classes #466

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions linode_api4/objects/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class ImageRegion(JSONObject):
The region and status of an image replica.
"""

include_none_values = True

region: str = ""
status: Optional[ReplicationStatus] = None

Expand Down
6 changes: 6 additions & 0 deletions linode_api4/objects/lke.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class LKENodePoolTaint(JSONObject):
applied to a node pool.
"""

include_none_values = True

key: Optional[str] = None
value: Optional[str] = None
effect: Optional[str] = None
Expand Down Expand Up @@ -103,6 +105,8 @@ class LKEClusterControlPlaneACLAddresses(JSONObject):
to access an LKE cluster's control plane.
"""

include_none_values = True

ipv4: Optional[List[str]] = None
ipv6: Optional[List[str]] = None

Expand All @@ -116,6 +120,8 @@ class LKEClusterControlPlaneACL(JSONObject):
NOTE: Control Plane ACLs may not currently be available to all users.
"""

include_none_values = True

enabled: bool = False
addresses: Optional[LKEClusterControlPlaneACLAddresses] = None

Expand Down
8 changes: 7 additions & 1 deletion linode_api4/objects/serializable.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ class JSONObject(metaclass=JSONFilterableMetaclass):
)
"""

include_none_values: ClassVar[bool] = False
"""
If true, all None values for this class will be explicitly included in
the serialized output for instance of this class.
"""

always_include: ClassVar[Set[str]] = {}
"""
A set of keys corresponding to fields that should always be
Expand Down Expand Up @@ -169,7 +175,7 @@ def should_include(key: str, value: Any) -> bool:
Returns whether the given key/value pair should be included in the resulting dict.
"""

if key in cls.always_include:
if cls.include_none_values or key in cls.always_include:
return True

hint = type_hints.get(key)
Expand Down
21 changes: 21 additions & 0 deletions test/unit/objects/serializable_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,24 @@ class Foo(JSONObject):
assert foo["foo"] == "test"
assert foo["bar"] == "test2"
assert foo["baz"] == "test3"

def test_serialize_optional_include_None(self):
@dataclass
class Foo(JSONObject):
include_none_values = True

foo: Optional[str] = None
bar: Optional[str] = None
baz: str = None

foo = Foo().dict

assert foo["foo"] is None
assert foo["bar"] is None
assert foo["baz"] is None

foo = Foo(foo="test", bar="test2", baz="test3").dict

assert foo["foo"] == "test"
assert foo["bar"] == "test2"
assert foo["baz"] == "test3"