from threading import Thread
from time import sleep
class Knob:
def __init__(self, d):
self.__door = d
self.__latched = True
@property
def is_latched_off(self):
return not self.__latched
def turn(self):
self.__latched = False
def unturn(self):
if self.__door.is_close:
self.__latched = True
class Door:
def __init__(self):
self.knob = Knob(self)
self.__closed = True
@property
def is_close(self):
return self.__closed
@property
def is_open(self):
return not self.is_close
@property
def can_be_open(self):
return self.is_open or self.knob.is_latched_off
def be_open(self):
if self.can_be_open:
self.__closed = False
def be_close(self):
self.__closed = True
self.knob.unturn()
def push(self):
self.be_open()
def pull(self):
self.be_close()
door1 = Door()
print("door1 is a Door...")
door1.knob.turn()
print("door1.knob.turn(); door1.can_be_open => {0}".format(door1.can_be_open))
door1.knob.unturn()
print("door1.knob.unturn(); door1.can_be_open => {0}".format(door1.can_be_open))
door1.push()
print("door1.push(); door1.is_open => {0}".format(door1.is_open))
door1.knob.turn(); door1.push()
print("door1.knob.turn(); door1.push(); door1.is_open => {0}".format(door1.is_open))
door1.pull()
print("door1.pull(); door1.is_close => {0}".format(door1.is_close))
print("door1.can_be_open => {0}\n".format(door1.can_be_open))
class DoorCloserPull(Thread):
def __init__(self, door):
super().__init__()
self.__door = door
self.expired = None
def run(self):
self.expired = False
sleep(self.__door.delay_sec)
if not self.expired:
self.expired = True
self.__door.pull()
class DoorCloserMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__delay_sec = 0.3
self.__delayed_pull = None
@property
def delay_sec(self):
return self.__delay_sec
@delay_sec.setter
def delay_sec(self, value):
self.__delay_sec = value
self.exec_delayed_pull()
def exec_delayed_pull(self):
if self.is_open:
if self.__delayed_pull and not self.__delayed_pull.expired:
self.__delayed_pull.expired = True
self.__delayed_pull = DoorCloserPull(self)
self.__delayed_pull.daemon = True
self.__delayed_pull.start()
def push(self):
super().push()
self.exec_delayed_pull()
class DoorWithCloser(DoorCloserMixin, Door):
pass
door2 = DoorWithCloser()
print("door2 is a DoorWithCloser with {0} seconds delay ...".format(door2.delay_sec))
door2.knob.turn(); door2.push()
print("door2.knob.turn(); door2.push(); door2.is_open => {0}".format(door2.is_open))
print("0.1 second after", end='')
sleep(0.1)
print(", door2.is_open => {0}".format(door2.is_open))
print("0.4 seconds after", end='')
sleep(0.3)
print(", door2.is_close => {0}".format(door2.is_close))
door2.knob.turn(); door2.push(); door2.delay_sec = 0.6
print("door2.knob.turn(); door2.push(); door2.delay_sec = 0.6; door2.is_open => {0}".format(door2.is_open))
print("0.4 seconds after", end='')
sleep(0.4)
print(", door2.is_close => {0}".format(door2.is_close))
print("0.7 seconds after", end='')
sleep(0.3)
print(", door2.is_close => {0}\n".format(door2.is_close))
class DoorStopperMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__stoppered = False
@property
def is_stoppered(self):
return self.__stoppered
def be_stoppered_on(self):
self.__stoppered = True
def be_stoppered_off(self):
self.__stoppered = False
def pull(self):
if not self.is_stoppered:
super().pull()
def push(self):
self.__stoppered = False
super().push()
class DoorWithStopper(DoorStopperMixin, Door):
pass
door3 = DoorWithStopper()
print("door3 is a DoorWithStopper...")
door3.knob.turn(); door3.push()
print("door3.knob.turn(); door3.push(); door3.is_open => {0}".format(door3.is_open))
door3.be_stoppered_on(); door3.pull()
print("door3.be_stoppered_on(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
door3.be_stoppered_off(); door3.pull()
print("door3.be_stoppered_off(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
door3.knob.turn(); door3.push()
print("door3.knob.turn(); door3.push(); door3.is_open => {0}".format(door3.is_open))
door3.be_stoppered_on(); door3.pull()
print("door3.be_stoppered_on(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
door3.push(); door3.pull()
print("door3.push(); door3.pull(); door3.is_close => {0}\n".format(door3.is_close))
class DoorWithCloserStopper(DoorCloserMixin, DoorStopperMixin, Door):
def be_stoppered_off(self):
super().be_stoppered_off()
self.exec_delayed_pull()
door4 = DoorWithCloserStopper()
print("door4 is a DoorWithCloserStopper with {0} seconds delay ...".format(door4.delay_sec))
door4.knob.turn(); door4.push()
print("door4.knob.turn(); door4.push(); door4.is_open => {0}".format(door4.is_open))
door4.be_stoppered_on()
print("door4.be_stoppered_on(); 0.4 seconds after", end='')
sleep(0.4)
print(", door4.is_open => {0}".format(door4.is_open))
door4.be_stoppered_off()
print("door4.be_stoppered_off(); 0.4 seconds after", end='')
sleep(0.4)
print(", door4.is_close => {0}".format(door4.is_close))
door4.knob.turn(); door4.push()
print("door4.knob.turn(); door4.push(); door4.is_open => {0}".format(door4.is_open))
door4.be_stoppered_on()
print("door4.be_stoppered_on(); 0.4 seconds after", end='')
sleep(0.4)
print(", door4.is_open => {0}".format(door4.is_open))
door4.push()
print("door4.push(); 0.4 seconds after", end='')
sleep(0.4)
print(", door4.is_close => {0}\n".format(door4.is_close))