浏览代码

Added type annotations in own classes (first commit of two resulting from the code review)

Denis Waßmann 7 年之前
父节点
当前提交
bdfcd84a6d
共有 3 个文件被更改,包括 54 次插入51 次删除
  1. 34 33
      code/ID2TLib/IPv4.py
  2. 19 17
      code/ID2TLib/OldLibs/IPGenerator.py
  3. 1 1
      code/ID2TLib/OldLibs/MacAddressGenerator.py

+ 34 - 33
code/ID2TLib/IPv4.py

@@ -1,4 +1,5 @@
 import re
+from typing import Union, Any, Optional
 
 
 class IPAddress:
@@ -13,7 +14,7 @@ class IPAddress:
 	# 4 numbers between 0 and 255, joined together with dots
 	IP_REGEXP = r"{0}\.{0}\.{0}\.{0}".format(_IP_NUMBER_REGEXP)
 	
-	def __init__(self, intlist):
+	def __init__(self, intlist: list[int]) -> "IPAddress":
 		"""
 		Construct an ipv4-address with a list of 4 integers, e.g. to construct the ip 10.0.0.0 pass [10, 0, 0, 0]
 		"""
@@ -26,7 +27,7 @@ class IPAddress:
 		self.ipnum = int.from_bytes(bytes(intlist), "big")
 	
 	@staticmethod
-	def parse(ip: str):
+	def parse(ip: str) -> "IPAddress":
 		"""
 		Parse an ip-address-string. If the string does not comply to the ipv4-format a ValueError is raised
 		:param ip: A string-representation of an ip-address, e.g. "10.0.0.0"
@@ -41,7 +42,7 @@ class IPAddress:
 		return IPAddress(numbers)
 	
 	@staticmethod
-	def from_int(numeric: int):
+	def from_int(numeric: int) -> "IPAddress":
 		if numeric not in range(1 << 32):
 			raise ValueError("numeric value must be in uint-range")
 		
@@ -49,7 +50,7 @@ class IPAddress:
 		return IPAddress(list(numeric.to_bytes(4, "big")))
 	
 	@staticmethod
-	def is_ipv4(ip: str):
+	def is_ipv4(ip: str) -> bool:
 		"""
 		Check if the supplied string is in ipv4-format
 		"""
@@ -57,19 +58,19 @@ class IPAddress:
 		match = re.match("^" + IPAddress.IP_REGEXP + "$", ip)
 		return True if match else False
 
-	def to_int(self):
+	def to_int(self) -> int:
 		"""
 		Convert the ip-address to a 32-bit uint, e.g. IPAddress.parse("10.0.0.255").to_int() returns 0x0a0000ff
 		"""
 		return self.ipnum
 	
-	def is_private(self):
+	def is_private(self) -> bool:
 		"""
 		Returns a boolean indicating if the ip-address lies in the private ip-segments (see ReservedIPBlocks)
 		"""
 		return ReservedIPBlocks.is_private(self)
 	
-	def get_private_segment(self):
+	def get_private_segment(self) -> bool:
 		"""
 		Return the private ip-segment the ip-address belongs to (there are several)
 		If this ip does not belong to a private ip-segment a ValueError is raised
@@ -77,55 +78,55 @@ class IPAddress:
 		"""
 		return ReservedIPBlocks.get_private_segment(self)
 
-	def is_localhost(self):
+	def is_localhost(self) -> bool:
 		"""
 		Returns a boolean indicating if the ip-address lies in the localhost-segment
 		"""
 		return ReservedIPBlocks.is_localhost(self)
 	
-	def is_multicast(self):
+	def is_multicast(self) -> bool:
 		"""
 		Returns a boolean indicating if the ip-address lies in the multicast-segment
 		"""
 		return ReservedIPBlocks.is_multicast(self)
 	
-	def is_reserved(self):
+	def is_reserved(self) -> bool:
 		"""
 		Returns a boolean indicating if the ip-address lies in the reserved-segment
 		"""
 		return ReservedIPBlocks.is_reserved(self)
 	
-	def is_zero_conf(self):
+	def is_zero_conf(self) -> bool:
 		"""
 		Returns a boolean indicating if the ip-address lies in the zeroconf-segment
 		"""
 		return ReservedIPBlocks.is_zero_conf(self)
 	
-	def _tuple(self):
+	def _tuple(self) -> (int,int,int,int):
 		return tuple(self.ipnum.to_bytes(4, "big"))
 	
-	def __repr__(self):
+	def __repr__(self) -> str:
 		"""
 		Following the python style guide, eval(repr(obj)) should equal obj
 		"""
 		return "IPAddress([%i, %i, %i, %i])" % self._tuple()
 	
-	def __str__(self):
+	def __str__(self) -> str:
 		"""
 		Return the ip-address described by this object in ipv4-format
 		"""
 		return "%i.%i.%i.%i" % self._tuple()
 	
-	def __hash__(self):
+	def __hash__(self) -> int:
 		return self.ipnum
 	
-	def __eq__(self, other):
+	def __eq__(self, other: Any) -> bool:
 		if other is None:
 			return False
 		
 		return isinstance(other, IPAddress) and self.ipnum == other.ipnum
 	
-	def __lt__(self, other):
+	def __lt__(self, other: Any) -> bool:
 		if other is None:
 			raise TypeError("Cannot compare to None")
 		if not isinstance(other, IPAddress):
@@ -133,7 +134,7 @@ class IPAddress:
 		
 		return self.ipnum < other.ipnum
 	
-	def __int__(self):
+	def __int__(self) -> bool:
 		return self.ipnum
 
 class IPAddressBlock:
@@ -146,7 +147,7 @@ class IPAddressBlock:
 	# this regex describes CIDR-notation (an ip-address plus "/XX", whereas XX is a number between 1 and 32)
 	CIDR_REGEXP = IPAddress.IP_REGEXP + r"(\/(3[0-2]|[12]?\d)|)?"
 	
-	def __init__(self, ip, netmask = 32):
+	def __init__(self, ip: Union(str, list, IPAddress), netmask = 32) -> "IPAddressBlock":
 		"""
 		Construct a ip-block given a ip-address and a netmask. Given an ip and a netmask,
 		the constructed ip-block will describe the range ip/netmask (e.g. 127.0.0.1/8)
@@ -165,7 +166,7 @@ class IPAddressBlock:
 		self.netmask = netmask
 
 	@staticmethod
-	def parse(cidr: str):
+	def parse(cidr: str) -> "IPAddressBlock":
 		"""
 		Parse a string in cidr-notation and return a IPAddressBlock describing the ip-segment
 		If the string is not in cidr-notation a ValueError is raised
@@ -180,42 +181,42 @@ class IPAddressBlock:
 		
 		return IPAddressBlock(ip, suffix)
 	
-	def block_size(self):
+	def block_size(self) -> int:
 		"""
 		Return the size of the ip-address-block. E.g. the size of someip/24 is 256
 		"""
 		return 2 ** (32 - self.netmask)
 	
-	def first_address(self):
+	def first_address(self) -> IPAddress:
 		"""
 		Return the first ip-address of the ip-block
 		"""
 		return IPAddress.from_int(self.ipnum)
 
-	def last_address(self):
+	def last_address(self) -> IPAddress:
 		"""
 		Return the last ip-address of the ip-block
 		"""
 		return IPAddress.from_int(self.ipnum + self.block_size() - 1)
 
-	def _bitmask(self, netmask):
+	def _bitmask(self, netmask: int) -> int:
 		ones = lambda x: (1 << x) - 1
 		
 		return ones(32) ^ ones(32 - netmask)
 	
-	def __repr__(self):
+	def __repr__(self) -> str:
 		"""
 		Conforming to python style-guide, eval(repr(obj)) equals obj
 		"""
 		return "IPAddressBlock(%s, %i)" % (repr(IPAddress.from_int(self.ipnum)), self.netmask)
 	
-	def __str__(self):
+	def __str__(self) -> str:
 		"""
 		Return a string in cidr-notation
 		"""
 		return str(IPAddress.from_int(self.ipnum)) + "/" + str(self.netmask)
 	
-	def __contains__(self, ip):
+	def __contains__(self, ip: IPAddress) -> bool:
 		return (ip.to_int() & self._bitmask(self.netmask)) == self.ipnum
 
 class ReservedIPBlocks:
@@ -239,11 +240,11 @@ class ReservedIPBlocks:
 	ZERO_CONF_SEGMENT = IPAddressBlock.parse("169.254.0.0/16")
 	
 	@staticmethod
-	def is_private(ip):
+	def is_private(ip: IPAddress) -> bool:
 		return any(ip in block for block in ReservedIPBlocks.PRIVATE_IP_SEGMENTS)
 	
 	@staticmethod
-	def get_private_segment(ip):
+	def get_private_segment(ip: IPAddress) -> Optional[IPAddressBlock]:
 		if not ReservedIPBlocks.is_private(ip):
 			raise ValueError("%s is not part of a private IP segment" % ip)
 
@@ -252,18 +253,18 @@ class ReservedIPBlocks:
 				return block
 
 	@staticmethod
-	def is_localhost(ip):
+	def is_localhost(ip: IPAddress) -> bool:
 		return ip in ReservedIPBlocks.LOCALHOST_SEGMENT
 	
 	@staticmethod
-	def is_multicast(ip):
+	def is_multicast(ip: IPAddressBlock) -> bool:
 		return ip in ReservedIPBlocks.MULTICAST_SEGMENT
 	
 	@staticmethod
-	def is_reserved(ip):
+	def is_reserved(ip: IPAddress) -> bool:
 		return ip in ReservedIPBlocks.RESERVED_SEGMENT
 	
 	@staticmethod
-	def is_zero_conf(ip):
+	def is_zero_conf(ip: IPAddressBlock) -> bool:
 		return ip in ReservedIPBlocks.ZERO_CONF_SEGMENT
 

+ 19 - 17
code/ID2TLib/OldLibs/IPGenerator.py

@@ -1,45 +1,47 @@
 import random
 from code.ID2TLib import IPv4 as ip
+from typing import Union, Any
+
 
 class IPChooser:
-	def random_ip(self):
+	def random_ip(self) -> ip.IPAddress:
 		return ip.IPAddress.from_int(random.randrange(0, 1 << 32))
 	
-	def size(self):
+	def size(self) -> int:
 		return 1 << 32
 	
-	def __len__(self):
+	def __len__(self) -> int:
 		return self.size()
 
 class IPChooserByRange(IPChooser):
-	def __init__(self, ip_range):
+	def __init__(self, ip_range: ip.IPAddressBlock) -> "IPChooserByRange":
 		self.range = ip_range
 	
-	def random_ip(self):
+	def random_ip(self) -> ip.IPAddress:
 		start = int(self.range.first_address())
 		end = start + self.range.block_size()
 		return ip.IPAddress.from_int(random.randrange(start, end))
 	
-	def size(self):
+	def size(self) -> int:
 		return self.range.block_size()
 
 class IPChooserByList(IPChooser):
-	def __init__(self, ips):
+	def __init__(self, ips: list[ip.IPAddress]) -> "IPChooserByList":
 		self.ips = list(ips)
 		if not self.ips:
 			raise ValueError("list of ips must not be empty")
 	
-	def random_ip(self):
+	def random_ip(self) -> ip.IPAddress:
 		return random.choice(self.ips)
 	
-	def size(self):
+	def size(self) -> int:
 		return len(self.ips)
 
 class IPGenerator:
 	def __init__(self, ip_chooser = IPChooser(), # include all ip-addresses by default (before the blacklist)
 			include_private_ips = False, include_localhost = False,
 			include_multicast = False, include_reserved = False,
-			include_link_local = False, blacklist = None):
+			include_link_local = False, blacklist = None) -> "IPGenerator":
 		self.blacklist = []
 		self.generated_ips = set()
 		
@@ -60,16 +62,16 @@ class IPGenerator:
 		self.chooser = ip_chooser
 	
 	@staticmethod
-	def from_range(range, *args, **kwargs):
+	def from_range(range: ip.IPAddressBlock, *args, **kwargs) -> "IPGenerator":
 		return IPGenerator(IPChooserByRange(range), *args, **kwargs)
 	
-	def add_to_blacklist(self, ip_segment):
+	def add_to_blacklist(self, ip_segment: Union[ip.IPAddressBlock, str]):
 		if isinstance(ip_segment, ip.IPAddressBlock):
 			self.blacklist.append(ip_segment)
 		else:
 			self.blacklist.append(ip.IPAddressBlock.parse(ip_segment))
 	
-	def random_ip(self):
+	def random_ip(self) -> ip.IPAddress:
 		if len(self.generated_ips) == self.chooser.size():
 			raise ValueError("Exhausted the space of possible ip-addresses, no new unique ip-address can be generated")
 		
@@ -84,11 +86,11 @@ class IPGenerator:
 		if clear_blacklist: self.blacklist.clear()
 		if clear_generated_ips: self.generated_ips.clear()
 	
-	def _is_in_blacklist(self, ip: ip.IPAddress):
+	def _is_in_blacklist(self, ip: ip.IPAddress) -> bool:
 		return any(ip in block for block in self.blacklist)
 
 class MappingIPGenerator(IPGenerator):
-	def __init__(self, *args, **kwargs):
+	def __init__(self, *args, **kwargs) -> "MappingIPGenerator":
 		super().__init__(self, *args, **kwargs)
 		
 		self.mapping = {}
@@ -98,11 +100,11 @@ class MappingIPGenerator(IPGenerator):
 		if clear_generated_ips:
 			self.mapping  = {}
 	
-	def get_mapped_ip(self, key):
+	def get_mapped_ip(self, key: Any) -> ip.IPAddress:
 		if key not in self.mapping:
 			self.mapping[key] = self.random_ip()
 		
 		return self.mapping[key]
 	
-	def __getitem__(self, item):
+	def __getitem__(self, item: Any) -> ip.IPAddress:
 		return self.get_mapped_ip(item)

+ 1 - 1
code/ID2TLib/OldLibs/MacAddressGenerator.py

@@ -1,7 +1,7 @@
 from random import getrandbits
 
 class MacAddressGenerator:
-	def __init__(self, include_broadcast_macs = False, include_virtual_macs = False):
+	def __init__(self, include_broadcast_macs = False, include_virtual_macs = False) -> "MacAddressGenerator":
 		self.broadcast = include_broadcast_macs
 		self.virtual = include_virtual_macs