Skip to content

Commit

Permalink
feat: add decoded_properties method to ServiceInfo (#1332)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Dec 13, 2023
1 parent d29553a commit 9b595a1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/zeroconf/_services/info.pxd
Expand Up @@ -53,6 +53,7 @@ cdef class ServiceInfo(RecordUpdateListener):
cdef public str server
cdef public str server_key
cdef public cython.dict _properties
cdef public cython.dict _decoded_properties
cdef public object host_ttl
cdef public object other_ttl
cdef public object interface_index
Expand All @@ -72,6 +73,9 @@ cdef class ServiceInfo(RecordUpdateListener):
@cython.locals(length="unsigned char", index="unsigned int", key_value=bytes, key_sep_value=tuple)
cdef void _unpack_text_into_properties(self)

@cython.locals(k=bytes, v=bytes)
cdef void _generate_decoded_properties(self)

@cython.locals(properties_contain_str=bint)
cpdef _set_properties(self, cython.dict properties)

Expand Down
19 changes: 19 additions & 0 deletions src/zeroconf/_services/info.py
Expand Up @@ -143,6 +143,7 @@ class ServiceInfo(RecordUpdateListener):
"server",
"server_key",
"_properties",
"_decoded_properties",
"host_ttl",
"other_ttl",
"interface_index",
Expand Down Expand Up @@ -192,6 +193,7 @@ def __init__(
self.server = server if server else None
self.server_key = server.lower() if server else None
self._properties: Optional[Dict[bytes, Optional[bytes]]] = None
self._decoded_properties: Optional[Dict[str, Optional[str]]] = None
if isinstance(properties, bytes):
self._set_text(properties)
else:
Expand Down Expand Up @@ -268,6 +270,15 @@ def properties(self) -> Dict[bytes, Optional[bytes]]:
assert self._properties is not None
return self._properties

@property
def decoded_properties(self) -> Dict[str, Optional[str]]:
"""Return properties as strings."""
if self._decoded_properties is None:
self._generate_decoded_properties()
if TYPE_CHECKING:
assert self._decoded_properties is not None
return self._decoded_properties

def async_clear_cache(self) -> None:
"""Clear the cache for this service info."""
self._dns_address_cache = None
Expand Down Expand Up @@ -384,6 +395,14 @@ def _set_text(self, text: bytes) -> None:
self.text = text
# Clear the properties cache
self._properties = None
self._decoded_properties = None

def _generate_decoded_properties(self) -> None:
"""Generates decoded properties from the properties"""
self._decoded_properties = {
k.decode("ascii", "replace"): None if v is None else v.decode("utf-8", "replace")
for k, v in self.properties.items()
}

def _unpack_text_into_properties(self) -> None:
"""Unpacks the text field into properties"""
Expand Down
9 changes: 9 additions & 0 deletions tests/test_services.py
Expand Up @@ -134,6 +134,13 @@ def update_service(self, zeroconf, type, name):
assert info.properties[b'prop_true'] == b'1'
assert info.properties[b'prop_false'] == b'0'

assert info.decoded_properties['prop_none'] is None
assert info.decoded_properties['prop_string'] == b'a_prop'.decode('utf-8')
assert info.decoded_properties['prop_float'] == '1.0'
assert info.decoded_properties['prop_blank'] == b'a blanked string'.decode('utf-8')
assert info.decoded_properties['prop_true'] == '1'
assert info.decoded_properties['prop_false'] == '0'

assert info.addresses == addresses[:1] # no V6 by default
assert set(info.addresses_by_version(r.IPVersion.All)) == set(addresses)

Expand Down Expand Up @@ -194,11 +201,13 @@ def update_service(self, zeroconf, type, name):
info = zeroconf_browser.get_service_info(type_, registration_name)
assert info is not None
assert info.properties[b'prop_blank'] == properties['prop_blank']
assert info.decoded_properties['prop_blank'] == b'an updated string'.decode('utf-8')

cached_info = ServiceInfo(subtype, registration_name)
cached_info.load_from_cache(zeroconf_browser)
assert cached_info.properties is not None
assert cached_info.properties[b'prop_blank'] == properties['prop_blank']
assert cached_info.decoded_properties['prop_blank'] == b'an updated string'.decode('utf-8')

zeroconf_registrar.unregister_service(info_service)
service_removed.wait(1)
Expand Down

0 comments on commit 9b595a1

Please sign in to comment.