text: """Timer"""
  import time
  import functools
  from threading import Thread
  
  
  class Chronometer:
      """Simple chronometer with context manager support
  
      # Properties
          partial: float, current couting in seconds
          running: boolean, chronometer current state
  
      # Example
  
      ```python
      import time
  
      chr = Chronometer()
      chr.start()
      time.sleep(5)
      print('Partial:', chr.partial)
      chr.stop()
      assert not chr.running
      chr.reset()
  
      # or use with the context manager
  
      with Chronometer() as chr:
          assert chr.running
          time.sleep(5)
          print('Partial:', chr.partial)
      ```
      """
      def __init__(self):
          self.__running = False
          self.__start = None
          self.__end = None
          self.__stop_partial = 0
      
      def __enter__(self):
          self.start()
          return self
  
      def __exit__(self, *i):
          self.stop()
  
      def start(self):
          """Starts the chronometer or resume the latest stop"""
          if self.__running == True:
              return
  
          self.__running = True
          self.__start = time.clock()
  
      def reset(self):
          """Call Chronometer.stop(reset=True)"""
          self.stop(reset=True)
  
      def stop(self, reset=False):
          """Stops the chronometer
          
          # Arguments
              reset: optional, boolean, default `False`
                  - `True` - Reset the chronometer to zero
                  - `False` - Maintain the current count
          """
          if reset:
              self.__stop_partial = 0
          else:
              self.__stop_partial = self.partial
  
          self.__running = False
  
      @property
      def partial(self):
          if self.__running:
              return time.clock() - self.__start + self.__stop_partial
          else:
              return self.__stop_partial
      
      @property
      def running(self):
          return self.__running
  
  
  class ChronometerDecorator(Chronometer):
      """Chronometer Decorator
  
      Use this decorator to measure time when executing functions
      or methods.
  
      # Example
  
      ```python
      import time
  
  
      @ChronometerDecorator()
      def foo(msg):
          print(msg)
          time.sleep(3)
  
      @ChronometerDecorator(print_sum=True)
      def bar():
          time.sleep(1)
  
      class baz:
          def __init__(self):
              self.message = 'Works on methods as well!'
              
          @ChronometerDecorator(method=True)
          def qux(self):
              time.sleep(3)
              print(self.message)
  
      foo('Starting ChronometerDecorator test!')
      for _ in range(3): bar()
      baz().qux()
  
      ''' Result example:
      Starting ChronometerDecorator test!
      [ChronometerDecorator]: Function foo > Time: 2.9994740292006554
      [ChronometerDecorator]: Function bar > Time: 1.000767622853573 - Total: 1.000767622853573
      [ChronometerDecorator]: Function bar > Time: 0.9999331681037802 - Total: 2.000700790957353
      [ChronometerDecorator]: Function bar > Time: 0.9999622418665695 - Total: 3.0006630328239225
      Works on methods as well!
      [ChronometerDecorator]: Method qux > Time: 3.0000543717121673
      '''
      
      ```
      """
      
      def __init__(self, method=False, print_sum=False):
          self.time_ls = []
          self.method = method
          self.print_sum = print_sum
          super().__init__()
          
      def __call__(self, function=None):
          self._function = function
          self.func_name = function.__name__
          
          if self.method:
              return functools.partialmethod(ChronometerDecorator.method_call, self)
          else:
              return self.function_call
          
      def function_call(self, *a, **kw):
          self.start()
          self._function(*a, **kw)
          self.stop()
          self.register()
  
      @staticmethod
      def method_call(func_self, self, *a, **kw):
          self.start()
          self._function(func_self, *a, **kw)
          self.stop()
          self.register()
          
      def register(self):
          self.time_ls.append(self.partial)
          
          msg_sum = ''
          if self.print_sum:
              msg_sum = ' - Total: {}'.format(sum(self.time_ls))
              
          msg_func_name = 'Method' if self.method else 'Function' 
          msg_func_name += ' {} >'.format(self.func_name)
          msg = '[ChronometerDecorator]: {} Time: {}{}'\
              .format(msg_func_name, self.partial, msg_sum)
          print(msg)
          self.reset()
  
  
  class Timer(Chronometer):
      """Countdown Timer with callback
  
      Timer inherit from [Chronometer](#chronometer-class)
  
      # Arguments
          time: int, required
              - Start of the countdown in seconds
          callback: function, optional, default `None`
              - Function to be triggered when the countdown hits zero
  
      # Properties
          time_left: float, time left in seconds
  
      # Example
  
      ```python
      import time
  
      def time_out():
          print('Time out!')
  
      timer = Timer(30, callback=time_out)
  
      with timer:
          assert timer.running
          print('Burning 10 seconds...')
          time.sleep(10)
  
      assert not timer.running
  
      print('Time left:', timer.time_left)
      print('Waiting without running the clock...')
      time.sleep(10)
      print('Time left:', timer.time_left)
  
      with timer:
          print('Running the clock till timeout')
          while timer.running:
              print('> + 15 seconds...')
              time.sleep(15)
  
      print('Finished!')
      ```
      """
      def __init__(self, time, callback=None):
          super().__init__()
          self.time_limit = time
          self.callback = callback
          self.time_out = False
  
      def __copy__(self):
          """Custom copy to clean the `callback` function"""
          new = type(self)(None, None)
          new.__dict__.update(self.__dict__)
          new.callback = None
          return self
  
      def __deepcopy__(self, memo):
          return self.__copy__()
  
      def start(self):
          """Starts the countdown and starts the thread (`_time_out` method)
          which will trigger the `callback`
          """
          if self.time_out:
              self.reset()
  
          super().start()
          Thread(target=self._time_out).start()
  
      def stop(self, **i):
          """Stops the countdown and stops the running thread"""
          super().stop(**i)
  
      def reset(self):
          super().reset()
          self.time_out = False
  
      @property
      def time_left(self):
          time_left = self.time_limit - self.partial
          time_left = time_left if time_left > 0 else 0
          return time_left
  
      def _time_out(self):
          """Asynchronous method that trigger the `callback` function
          when the `time_left` is zero
          """
          while True:
              if self.running:
                  if self.time_left > 0:
                      time.sleep(.3)
                  else:
                      self.stop()
                      self.time_out = True
                      if self.callback:
                          self.callback()
                      break
              else:
                  break
  
  