#-----------------------------------------------------------------------------# Copyright (c) 2008 by David P. D. Moss. All rights reserved.## Released under the BSD license. See the LICENSE file for details.#-----------------------------------------------------------------------------"""Common code shared between various netaddr sub modules"""importsysas_sysimportpprintas_pprintfromnetaddr.compatimport_callable,_iter_dict_keys#: True if platform is natively big endian, False otherwise.BIG_ENDIAN_PLATFORM=_sys.byteorder=='big'#: Use inet_pton() semantics instead of inet_aton() when parsing IPv4.P=INET_PTON=1#: Remove any preceding zeros from IPv4 address octets before parsing.Z=ZEROFILL=2#: Remove any host bits found to the right of an applied CIDR prefix.N=NOHOST=4#: Use legacy ``inet_aton()`` semantics when parsing IPv4.INET_ATON=8#-----------------------------------------------------------------------------# Custom exceptions.#-----------------------------------------------------------------------------
[docs]classAddrFormatError(Exception):""" An Exception indicating a network address is not correctly formatted. """pass
[docs]classAddrConversionError(Exception):""" An Exception indicating a failure to convert between address types or notations. """pass
[docs]classNotRegisteredError(Exception):""" An Exception indicating that an OUI or IAB was not found in the IEEE Registry. """pass
try:a=42a.bit_length()# No exception, must be Python 2.7 or 3.1+ -> can use bit_length()deladefnum_bits(int_val):""" :param int_val: an unsigned integer. :return: the minimum number of bits needed to represent value provided. """returnint_val.bit_length()exceptAttributeError:# a.bit_length() excepted, must be an older Python version.defnum_bits(int_val):""" :param int_val: an unsigned integer. :return: the minimum number of bits needed to represent value provided. """numbits=0whileint_val:numbits+=1int_val>>=1returnnumbitsclassSubscriber(object):""" An abstract class defining the interface expected by a Publisher. """defupdate(self,data):""" A callback method used by a Publisher to notify this Subscriber about updates. :param data: a Python object containing data provided by Publisher. """raiseNotImplementedError('cannot invoke virtual method!')classPrettyPrinter(Subscriber):""" A concrete Subscriber that employs the pprint in the standard library to format all data from updates received, writing them to a file-like object. Useful as a debugging aid. """def__init__(self,fh=_sys.stdout,write_eol=True):""" Constructor. :param fh: a file-like object to write updates to. Default: sys.stdout. :param write_eol: if ``True`` this object will write newlines to output, if ``False`` it will not. """self.fh=fhself.write_eol=write_eoldefupdate(self,data):""" A callback method used by a Publisher to notify this Subscriber about updates. :param data: a Python object containing data provided by Publisher. """self.fh.write(_pprint.pformat(data))ifself.write_eol:self.fh.write("\n")classPublisher(object):""" A 'push' Publisher that maintains a list of Subscriber objects notifying them of state changes by passing them update data when it encounter events of interest. """def__init__(self):"""Constructor"""self.subscribers=[]defattach(self,subscriber):""" Add a new subscriber. :param subscriber: a new object that implements the Subscriber object interface. """ifhasattr(subscriber,'update')and_callable(subscriber.update):ifsubscribernotinself.subscribers:self.subscribers.append(subscriber)else:raiseTypeError('%r does not support required interface!'%subscriber)defdetach(self,subscriber):""" Remove an existing subscriber. :param subscriber: a new object that implements the Subscriber object interface. """try:self.subscribers.remove(subscriber)exceptValueError:passdefnotify(self,data):""" Send update data to to all registered Subscribers. :param data: the data to be passed to each registered Subscriber. """forsubscriberinself.subscribers:subscriber.update(data)classDictDotLookup(object):""" Creates objects that behave much like a dictionaries, but allow nested key access using object '.' (dot) lookups. Recipe 576586: Dot-style nested lookups over dictionary based data structures - http://code.activestate.com/recipes/576586/ """def__init__(self,d):forkind:ifisinstance(d[k],dict):self.__dict__[k]=DictDotLookup(d[k])elifisinstance(d[k],(list,tuple)):l=[]forvind[k]:ifisinstance(v,dict):l.append(DictDotLookup(v))else:l.append(v)self.__dict__[k]=lelse:self.__dict__[k]=d[k]def__getitem__(self,name):ifnameinself.__dict__:returnself.__dict__[name]def__iter__(self):return_iter_dict_keys(self.__dict__)def__repr__(self):return_pprint.pformat(self.__dict__)