Why did you put end_time = end_time or datetime.now()
It works together with having the end_time=None default in the method signature. If the method is not given an end_time, it is None, and then it gets the value of datetime.now().
It is essentially a 1-line version of:if not end_time: end_time = datetime.now()
You can also use and in a similar way, but with a different meaning. E.g.:
some_value = obj and obj.attribute
I.e., if obj is None, obj.attribute will not get called (which would raise an exception), and some_value gets assigned the None.
This is again a more concise version of:some_value = obj if obj: some_value = obj.attribute
... or the much uglier (to me):some_value = obj.attribute if obj else obj
And is this to check to se if the cleaning was started@property def started(self): return bool(self.start_time)
Yes, but it is not really used in this code, and not very useful either, because the main way to get a cleaning object is with the start_cleaning method, so it is always at least started when you have it.