Use ipaddress standard library

- Remove IPAddress ESPHome Python class and use standard ipaddress from
  standard library
This commit is contained in:
Jimmy Hedman 2024-09-02 20:38:42 +02:00
parent 68d50cbf9c
commit e4f164f179
No known key found for this signature in database
5 changed files with 39 additions and 62 deletions

View file

@ -3,6 +3,7 @@
from contextlib import contextmanager from contextlib import contextmanager
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime from datetime import datetime
from ipaddress import AddressValueError, IPv4Address, ip_address
import logging import logging
import os import os
import re import re
@ -66,7 +67,6 @@ from esphome.const import (
from esphome.core import ( from esphome.core import (
CORE, CORE,
HexInt, HexInt,
IPAddress,
Lambda, Lambda,
TimePeriod, TimePeriod,
TimePeriodMicroseconds, TimePeriodMicroseconds,
@ -1159,11 +1159,19 @@ def ssid(value):
def ipv4address(value): def ipv4address(value):
return IPAddress(value, allow_ipv6=False) try:
address = IPv4Address(value)
except AddressValueError as exc:
raise Invalid(f"{value} is not a valid IPv4 address") from exc
return address
def ipaddress(value): def ipaddress(value):
return IPAddress(value, allow_ipv6=True) try:
address = ip_address(value)
except ValueError as exc:
raise Invalid(f"{value} is not a valid IP address") from exc
return address
def _valid_topic(value): def _valid_topic(value):

View file

@ -1,4 +1,3 @@
import ipaddress
import logging import logging
import math import math
import os import os
@ -55,17 +54,6 @@ class HexInt(int):
return f"{sign}0x{value:X}" return f"{sign}0x{value:X}"
class IPAddress:
def __init__(self, arg, allow_ipv6=False):
if allow_ipv6:
self.args = str(ipaddress.ip_address(arg))
else:
self.args = str(ipaddress.IPv4Address(arg))
def __str__(self):
return self.args
class MACAddress: class MACAddress:
def __init__(self, *parts): def __init__(self, *parts):
if len(parts) != 6: if len(parts) != 6:

View file

@ -4,6 +4,7 @@ import fnmatch
import functools import functools
import inspect import inspect
from io import TextIOWrapper from io import TextIOWrapper
from ipaddress import _BaseAddress
import logging import logging
import math import math
import os import os
@ -25,7 +26,6 @@ from esphome.core import (
CORE, CORE,
DocumentRange, DocumentRange,
EsphomeError, EsphomeError,
IPAddress,
Lambda, Lambda,
MACAddress, MACAddress,
TimePeriod, TimePeriod,
@ -576,7 +576,7 @@ ESPHomeDumper.add_multi_representer(bool, ESPHomeDumper.represent_bool)
ESPHomeDumper.add_multi_representer(str, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(str, ESPHomeDumper.represent_stringify)
ESPHomeDumper.add_multi_representer(int, ESPHomeDumper.represent_int) ESPHomeDumper.add_multi_representer(int, ESPHomeDumper.represent_int)
ESPHomeDumper.add_multi_representer(float, ESPHomeDumper.represent_float) ESPHomeDumper.add_multi_representer(float, ESPHomeDumper.represent_float)
ESPHomeDumper.add_multi_representer(IPAddress, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(_BaseAddress, ESPHomeDumper.represent_stringify)
ESPHomeDumper.add_multi_representer(MACAddress, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(MACAddress, ESPHomeDumper.represent_stringify)
ESPHomeDumper.add_multi_representer(TimePeriod, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(TimePeriod, ESPHomeDumper.represent_stringify)
ESPHomeDumper.add_multi_representer(Lambda, ESPHomeDumper.represent_lambda) ESPHomeDumper.add_multi_representer(Lambda, ESPHomeDumper.represent_lambda)

View file

@ -1,12 +1,12 @@
import pytest
import string import string
from hypothesis import given, example from hypothesis import example, given
from hypothesis.strategies import one_of, text, integers, builds from hypothesis.strategies import builds, integers, ip_addresses, one_of, text
import pytest
from esphome import config_validation from esphome import config_validation
from esphome.config_validation import Invalid from esphome.config_validation import Invalid
from esphome.core import CORE, Lambda, HexInt from esphome.core import CORE, HexInt, Lambda
def test_check_not_templatable__invalid(): def test_check_not_templatable__invalid():
@ -145,6 +145,28 @@ def test_boolean__invalid(value):
config_validation.boolean(value) config_validation.boolean(value)
@given(value=ip_addresses(v=4).map(str))
def test_ipv4__valid(value):
config_validation.ipv4address(value)
@pytest.mark.parametrize("value", ("127.0.0", "localhost", ""))
def test_ipv4__invalid(value):
with pytest.raises(Invalid, match="is not a valid IPv4 address"):
config_validation.ipv4address(value)
@given(value=ip_addresses(v=6).map(str))
def test_ipv6__valid(value):
config_validation.ipaddress(value)
@pytest.mark.parametrize("value", ("127.0.0", "localhost", "", "2001:db8::2::3"))
def test_ipv6__invalid(value):
with pytest.raises(Invalid, match="is not a valid IP address"):
config_validation.ipaddress(value)
# TODO: ensure_list # TODO: ensure_list
@given(integers()) @given(integers())
def hex_int__valid(value): def hex_int__valid(value):

View file

@ -1,7 +1,4 @@
from ipaddress import AddressValueError
from hypothesis import given from hypothesis import given
from hypothesis.strategies import ip_addresses
import pytest import pytest
from strategies import mac_addr_strings from strategies import mac_addr_strings
@ -27,44 +24,6 @@ class TestHexInt:
assert actual == expected assert actual == expected
class TestIP4Address:
@given(value=ip_addresses(v=4).map(str))
def test_init__valid(self, value):
core.IPAddress(value, allow_ipv6=False)
@pytest.mark.parametrize("value", ("127.0.0", "localhost", ""))
def test_init__invalid(self, value):
with pytest.raises((ValueError, AddressValueError)):
core.IPAddress(value, allow_ipv6=False)
@given(value=ip_addresses(v=4).map(str))
def test_str(self, value):
target = core.IPAddress(value, allow_ipv6=False)
actual = str(target)
assert actual == value
class TestIP6Address:
@given(value=ip_addresses(v=6).map(str))
def test_init__valid(self, value):
core.IPAddress(value, allow_ipv6=True)
@pytest.mark.parametrize("value", ("127.0.0", "localhost", "", "2001:db8::2::3"))
def test_init__invalid(self, value):
with pytest.raises((ValueError, AddressValueError)):
core.IPAddress(value, allow_ipv6=True)
@given(value=ip_addresses(v=6).map(str))
def test_str(self, value):
target = core.IPAddress(value, allow_ipv6=True)
actual = str(target)
assert actual == value
class TestMACAddress: class TestMACAddress:
@given(value=mac_addr_strings()) @given(value=mac_addr_strings())
def test_init__valid(self, value): def test_init__valid(self, value):