@@ -1498,15 +1498,21 @@ def __init__(
14981498 self .type = type_
14991499 self .name = name
15001500 if addresses is not None :
1501- self .addresses = addresses
1501+ self ._addresses = addresses
15021502 elif address is not None :
15031503 warnings .warn ("address is deprecated, use addresses instead" , DeprecationWarning )
15041504 if isinstance (address , list ):
1505- self .addresses = address
1505+ self ._addresses = address
15061506 else :
1507- self .addresses = [address ]
1507+ self ._addresses = [address ]
15081508 else :
1509- self .addresses = []
1509+ self ._addresses = []
1510+ # This results in an ugly error when registering, better check now
1511+ invalid = [a for a in self ._addresses
1512+ if not isinstance (a , bytes ) or len (a ) not in (4 , 16 )]
1513+ if invalid :
1514+ raise TypeError ('Addresses must be bytes, got %s. Hint: convert string addresses '
1515+ 'with socket.inet_pton' % invalid )
15101516 self .port = port
15111517 self .weight = weight
15121518 self .priority = priority
@@ -1524,6 +1530,7 @@ def __init__(
15241530 def address (self ):
15251531 warnings .warn ("ServiceInfo.address is deprecated, use addresses instead" , DeprecationWarning )
15261532 try :
1533+ # Return the first V4 address for compatibility
15271534 return self .addresses [0 ]
15281535 except IndexError :
15291536 return None
@@ -1532,9 +1539,27 @@ def address(self):
15321539 def address (self , value ):
15331540 warnings .warn ("ServiceInfo.address is deprecated, use addresses instead" , DeprecationWarning )
15341541 if value is None :
1535- self .addresses = []
1542+ self ._addresses = []
15361543 else :
1537- self .addresses = [value ]
1544+ self ._addresses = [value ]
1545+
1546+ @property
1547+ def addresses (self ):
1548+ """IPv4 addresses of this service.
1549+
1550+ Only IPv4 addresses are returned for backward compatibility.
1551+ Use :meth:`addresses_by_version` or :meth:`parsed_addresses` to
1552+ include IPv6 addresses as well.
1553+ """
1554+ return self .addresses_by_version (IPVersion .V4Only )
1555+
1556+ @addresses .setter
1557+ def addresses (self , value ):
1558+ """Replace the addresses list.
1559+
1560+ This replaces all currently stored addresses, both IPv4 and IPv6.
1561+ """
1562+ self ._addresses = value
15381563
15391564 @property
15401565 def properties (self ) -> ServicePropertiesType :
@@ -1543,11 +1568,19 @@ def properties(self) -> ServicePropertiesType:
15431568 def addresses_by_version (self , version : IPVersion ) -> List [bytes ]:
15441569 """List addresses matching IP version."""
15451570 if version == IPVersion .V4Only :
1546- return [addr for addr in self .addresses if not _is_v6_address (addr )]
1571+ return [addr for addr in self ._addresses if not _is_v6_address (addr )]
15471572 elif version == IPVersion .V6Only :
1548- return list (filter (_is_v6_address , self .addresses ))
1573+ return list (filter (_is_v6_address , self ._addresses ))
15491574 else :
1550- return self .addresses
1575+ return self ._addresses
1576+
1577+ def parsed_addresses (self , version : IPVersion = IPVersion .All ) -> List [str ]:
1578+ """List addresses in their parsed string form."""
1579+ result = self .addresses_by_version (version )
1580+ return [
1581+ socket .inet_ntop (socket .AF_INET6 if _is_v6_address (addr ) else socket .AF_INET , addr )
1582+ for addr in result
1583+ ]
15511584
15521585 def _set_properties (self , properties : Union [bytes , ServicePropertiesType ]):
15531586 """Sets properties and text of this info from a dictionary"""
@@ -1625,8 +1658,8 @@ def update_record(self, zc: 'Zeroconf', now: float, record: DNSRecord) -> None:
16251658 assert isinstance (record , DNSAddress )
16261659 # if record.name == self.name:
16271660 if record .name == self .server :
1628- if record .address not in self .addresses :
1629- self .addresses .append (record .address )
1661+ if record .address not in self ._addresses :
1662+ self ._addresses .append (record .address )
16301663 elif record .type == _TYPE_SRV :
16311664 assert isinstance (record , DNSService )
16321665 if record .name == self .name :
@@ -1660,12 +1693,12 @@ def request(self, zc: 'Zeroconf', timeout: float) -> bool:
16601693 if cached :
16611694 self .update_record (zc , now , cached )
16621695
1663- if self .server is not None and self .text is not None and self .addresses :
1696+ if self .server is not None and self .text is not None and self ._addresses :
16641697 return True
16651698
16661699 try :
16671700 zc .add_listener (self , DNSQuestion (self .name , _TYPE_ANY , _CLASS_IN ))
1668- while self .server is None or self .text is None or not self .addresses :
1701+ while self .server is None or self .text is None or not self ._addresses :
16691702 if last <= now :
16701703 return False
16711704 if next_ <= now :
0 commit comments