<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def inspect(self):
 """Inspect device requests and sensors, update model Returns ------- Tornado future that resolves with: model_changes : Nested AttrDict or None Contains sets of added/removed request/sensor names Example structure: {'requests': { 'added': set(['req1', 'req2']), 'removed': set(['req10', 'req20'])} 'sensors': { 'added': set(['sens1', 'sens2']), 'removed': set(['sens10', 'sens20'])} } If there are no changes keys may be omitted. If an item is in both the 'added' and 'removed' sets that means that it changed. If neither request not sensor changes are present, None is returned instead of a nested structure. """

        timeout_manager = future_timeout_manager(self.sync_timeout)
        sensor_index_before = copy.copy(self._sensors_index)
        request_index_before = copy.copy(self._requests_index)
        try:
            request_changes = yield self.inspect_requests(
                timeout=timeout_manager.remaining())
            sensor_changes = yield self.inspect_sensors(
                timeout=timeout_manager.remaining())
        except Exception:
            # Ensure atomicity of sensor and request updates ; if the one
            # fails, the other should act as if it has failed too.
            self._sensors_index = sensor_index_before
            self._requests_index = request_index_before
            raise

        model_changes = AttrDict()
        if request_changes:
            model_changes.requests = request_changes
        if sensor_changes:
            model_changes.sensors = sensor_changes
        if model_changes:
            raise Return(model_changes)