"Generic physical devices"

# Abstract bases
class Device:
	"Abstract base class for all devices"
class NetDevice(Device):
	"Abstract base class for all network devices"
	def __init__(self):
		self.ifaces = []
	def can_connect(self, other):
		raise NotImplemented

# Computers
class Host(NetDevice):
	def can_connect(self, other):
		"A host connects interfaces"
		return isinstance(other, Interface)
class Workstation(Host):
	pass
class Server(Host):
	pass
class Router(Host):
	pass

# Interface cards
class Interface(NetDevice):
	def can_connect(self, other):
		"An interface connects a host and a cable"
		if len(self.ifaces) == 0:
			return (isinstance(other, Cable) or
				isinstance(other, Host))
		elif len(self.ifaces) == 1:
			return ((isinstance(other, Cable) and
				isinstance(self.ifaces[0], Host)) or
				(isinstance(other, Host) and
				isinstance(self.ifaces[0], Cable)))
		else:
			return 0

# Cabling
class Cable(NetDevice):
	def can_connect(self, other):
		"A cable connects two interfaces"
		return isinstance(other, Interface) and len(self.ifaces) < 2

# Miscellaneous devices
class Repeater(NetDevice):
	def can_connect(self, other):
		"A repeater connects two cables"
		return isinstance(other, Cable) and len(self.ifaces) < 2
class Hub(Repeater):
	def can_connect(self, other):
		"A repeater connects cables"
		return isinstance(other, Cable)
class Bridge(NetDevice):
	def can_connect(self, other):
		"A bridge connects two cables"
		return isinstance(other, Cable)
class Switch(Bridge):
	def can_connect(self, other):
		"A switch connects cables"
		return isinstance(other, Cable)
