class UnpairedException(Exception):
    pass


class PairedConnections(dict):
    def __init__(self, *args, **kwargs):
        self.waiting = set()  # сдесь хранятся соединения "в состоянии ожидания"
        super().__init__(*args, **kwargs)

    def __delitem__(self, key):
        paired_key = self[key]
        if paired_key is not None:
            try:
                super().__delitem__(paired_key)
            except KeyError as e:
                raise UnpairedException(f"Paired key {paired_key} not found")
        else:
            self.waiting.remove(key)
        super().__delitem__(key)

    def __setitem__(self, key, value):
        if value is not None:
            try:
                self[value]
            except KeyError as e:
                raise UnpairedException(f"Connection {key}-{value} not paired")
            super().__setitem__(value, key)
            self.waiting.remove(key)
            self.waiting.remove(value)
        else:
            self.waiting.add(key)
        super().__setitem__(key, value)

# тест
if __name__ == "__main__":
	conns = PairedConnections()
	conns['one'] = None
	conns['two'] = None
	conns['three'] = None
	print('1:', conns)
	print('\t', conns.waiting)
	conns['two'] = 'one'
	print('2:', conns)
	print('\t', conns.waiting)
	del conns['one']
	print('3:', conns)
	print('\t', conns.waiting)
	del conns['three']
	print('4:', conns)
	print('\t', conns.waiting)
	# по идее ошибок возникать не должно