自己动手编写IPv4地址包含关系测试的小脚本

工作中需要对地址包含关系进行测试,现有ipaddress标准库和IPy无法满足,于是自己动手编写小脚本,主要实现== , in, <等专用功能,其他功能可以后续用到再补充,例如迭代打印网段内所有地址,输出前缀长度等等。


一,含有的类:
Host类:主机地址,eg, Host('192.168.1.1')
Network类:网络地址,eg,Network('192.168.1.0 255.255.255.0')
AddressGroup类:主机地址和网络地址组成的列表,eg,AddressGroup(['192.168.1.0 255.255.255.0', '10.1.1.1'])


二,实现的功能:

Host—>Network—>AddressGroup,低级别向高级别支持in测试
Network/AddressGroup同类之间支持<=测试

1)Host in Network,Host in AddressGroup测试
Host('192.168.1.1') in Network('192.168.1.0 255.255.255.0') # True
Host('192.12.1.5') in Network('192.0.1.0 255.0.255.0') # True,Network可以是通配符
Host('192.12.1.5') in AddressGroup(['192.168.1.0 255.255.255.0', '10.1.1.1']) # True

2)Network in AddressGroup测试
Network(192.168.1.0 255.255.255.0) in AddressGroup(['192.168.0.0 255.255.0.0', '10.1.1.1'])

3)Network <= Network测试
Network(192.168.1.0 255.255.255.0) <= Network('192.168.0.0 255.255.0.0') # True
Network(192.0.1.0 255.0.255.0) <= Network('192.168.0.0 255.255.0.0') # False,Network可以是通配符

4)AddressGroup <= AddressGroup测试
AddressGroup(['192.168.1.0 255.255.255.0', '10.1.1.1']) <= AddressGroup(['192.168.0.0 255.255.255.0', '10.1.1.1']) # True

5)前缀修正
n1 = Network('192.168.1.0 255.0.255.0')
n1.network # 192.0.1.0


三,由于数据源都是标准的地址格式,因此很多细节和出错控制未考虑:
Address('300.1000.2.1') # 未做地址或者网段的出错控制,仅控制了split('.')是否等于4以及元素是否是整数
AddressGroup含C类host明细时,与所属AddressGroup网段进行eq比较时会不等

 

class AddressValueError(ValueError):
    """A Value Error related to the netmask."""


def ip_address(address):
    try:
        return Host(address)
    except AddressValueError:
        pass

    try:
        return Network(address)
    except AddressValueError:
        pass

    raise AddressValueError('Not a valid host or network address: {!r}'.format(address))


def _host_int_from_string(address):
    octets = address.split('.')
    if len(octets) != 4:
        raise AddressValueError("Expected 4 octets in {!r}".format(address))
    try:
        return [int(i) for i in octets]
    except ValueError as exc:
        raise AddressValueError("%s in %r" % (exc, address)) from None


def _network_int_from_string(address):
    parts = address.split()
    if len(parts) != 2:
        raise AddressValueError("Expected network plus netmask in {!r}".format(address))
    return _host_int_from_string(parts[0]), _host_int_from_string(parts[1])


class Host(object):
    """eg, address: 192.168.1.1"""
    __slots__ = ('_address', '_host')

    def __init__(self, address):
        self._address= address
        self._host = _host_int_from_string(address)

    def __repr__(self):
        return '<Host:{!r}>'.format(self._address)

    def __eq__(self, other):
        try:
            return self._address == other._address
        except AttributeError:
            return NotImplemented


class Network(object):
    """eg, address: 192.168.1.0 255.255.255.0"""
    __slots__ = ('_address', '_network', '_netmask')

    def __init__(self, address):
        self._address = address
        self._network, self._netmask = _network_int_from_string(address)
        self._network = [i[0] & i[1] for i in zip(self._network, self._netmask)]

    def __contains__(self, other):
        if isinstance(other, Host):
            network_other = [i[0] & i[1] for i in zip(other._host, self._netmask)]
            if self._network == network_other:
                return True
        return False

    def __eq__(self, other):
        try:
            return self._network == other._network and self._netmask == other._netmask
        except AttributeError:
            return NotImplemented

    def __le__(self, other):
        if isinstance(other, Network):
            parts = [i[0] & i[1] for i in zip(self._network, other._netmask)]
            if parts == other._network and all([i[0] >= i[1] for i in zip(self._netmask, other._netmask)]):
                return True
        return False

    def __repr__(self):
        return '<Network:{!r}>'.format(self._address)

    @property
    def network(self):
        return '.'.join([str(i) for i in self._network])


class AddressGroup(object):
    """ eg,address_group: ['192.168.1.1', '192.168.1.2', '10.1.1.0 255.255.255.0']
    无法继承abc.Set,因为abc.Set中两个Set长度相等直接返回Fasle,本类不一定,因此需要重构__lt__特殊方法 """
    def __init__(self, components):
        self._components = list(components)
        self._compObjs = [ip_address(i) for i in components]

    def __len__(self):
        return len(self._components)

    def __iter__(self):
        for c in self._compObjs:
            yield c

    def __contains__(self, other):
        if isinstance(other, Host):
            for obj in self:
                cond1 = isinstance(obj, Host) and other == obj
                cond2 = isinstance(obj, Network) and other in obj
                if cond1 or cond2:
                    return True
        if isinstance(other, Network):
            for obj in self:
                if isinstance(obj, Network) and other <= obj:
                    return True
        return False

    def __eq__(self, other):
        try:
            return sorted(self._components) == sorted(other._components)
        except AttributeError:
            return NotImplemented

    def __lt__(self, other):
        return all([i in other for i in self._compObjs])

    def __repr__(self):
        return '<AddressGroup:{!r}>'.format(' | '.join(self._components))

 

转载于:https://www.cnblogs.com/guxh/p/10162951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
有重大方便实用功能,如转换比较IPv4地址,判断IPv4地址有效性,判断一个地址是否属于一个网段等等。 是利用javascript处理IPv4地址的核心功能库。 另含有收集的网通IPv4网段地址库。 功能函数列表说明: getmark(num):返回数字,表示num对应多少位掩码,返回值为-1表示num为无效掩码数 num={128,192,224,240,248,252,254,255} getallmarknum(lanmark):返回数字,表示lanmark对应多少位掩码, 返回值为-1表示有掩码位无效 lanmark形如xxx.xxx.xxx.xxx,0<=xxx<=255 lanmarktonum(lanip):返回地址字符串,把xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx 转换为xxx.xxx.xxx.xxx/nn形式,nn<=32 返回值为""表示传入地址无效 lanmarkisnum(lanip):返回bool类型值,lanip为xxx.xxx.xxx.xxx/nn形式则返回true lanstd(lanip):返回地址段字符串标准化形式,标准形式为xxx.xxx.xxx.xxx/nn ipinlan(inip,inlan):返回bool类型值,判断inip是否在inlan地址段内 inip的形式为xxx.xxx.xxx.xxx,0<=xxx<=255 inlan的形式为xxx.xxx.xxx.xxx/nn,0<=xxx<=255,0<=nn<=32 inip在inlan内返回true ipok(inip):返回bool类型值,判断inip是否为有效形式的ip或者ip地址段, 是则返回true iptonum(inip):返回数字,该值为地址字符串inip对应的数字值 mininlan(inlan):返回数字,该值为网段inlan对应的最小ip地址数字值 网段字符串inlan采用xxx.xxx.xxx.xxx/nn形式 maxinlan(inlan):返回数字,该值为网段inlan对应的最大ip地址数字值 网段字符串inlan采用xxx.xxx.xxx.xxx/nn形式 iptolan(inip):返回inip所在网段字符串,inip采用xxx.xxx.xxx.xxx/nn的形式 numtoip(innum):返回IP地址字符串,innum是地址数字值,0<=innum<=0xffffffff
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值