nodes: 0, module; 1, function_definition; 2, function_name:rate_limited; 3, parameters; 4, block; 5, identifier:max_per_second; 6, expression_statement; 7, import_statement; 8, expression_statement; 9, expression_statement; 10, function_definition; 11, return_statement; 12, comment:""" Sort of based off of an answer about
          rate limiting on Stack Overflow.
  
          Definitely **not** thread safe, so
          don't even think about it, buddy.
      """; 13, dotted_name; 14, assignment; 15, assignment; 16, function_name:decorate; 17, parameters; 18, block; 19, identifier:decorate; 20, identifier:datetime; 21, identifier:min_request_time; 22, call; 23, identifier:last_time_called; 24, list; 25, identifier:func; 26, function_definition; 27, return_statement; 28, attribute; 29, argument_list; 30, None; 31, function_name:rate_limited_function; 32, parameters; 33, block; 34, call; 35, identifier:datetime; 36, identifier:timedelta; 37, keyword_argument; 38, list_splat_pattern; 39, dictionary_splat_pattern; 40, if_statement; 41, expression_statement; 42, expression_statement; 43, return_statement; 44, attribute; 45, argument_list; 46, identifier:seconds; 47, identifier:max_per_second; 48, identifier:args; 49, identifier:kwargs; 50, subscript; 51, block; 52, assignment; 53, assignment; 54, identifier:ret; 55, identifier:functools; 56, identifier:update_wrapper; 57, identifier:rate_limited_function; 58, identifier:func; 59, identifier:last_time_called; 60, integer:0; 61, expression_statement; 62, if_statement; 63, identifier:ret; 64, call; 65, subscript; 66, call; 67, assignment; 68, comparison_operator:delta < datetime.timedelta.min; 69, block; 70, elif_clause; 71, identifier:func; 72, argument_list; 73, identifier:last_time_called; 74, integer:0; 75, attribute; 76, argument_list; 77, identifier:delta; 78, binary_operator:datetime.datetime.now() - last_time_called[0]; 79, identifier:delta; 80, attribute; 81, raise_statement; 82, comparison_operator:delta < min_request_time; 83, block; 84, list_splat; 85, dictionary_splat; 86, attribute; 87, identifier:now; 88, call; 89, subscript; 90, attribute; 91, identifier:min; 92, expression_list; 93, identifier:delta; 94, identifier:min_request_time; 95, expression_statement; 96, raise_statement; 97, identifier:args; 98, identifier:kwargs; 99, identifier:datetime; 100, identifier:datetime; 101, attribute; 102, argument_list; 103, identifier:last_time_called; 104, integer:0; 105, identifier:datetime; 106, identifier:timedelta; 107, attribute; 108, string:"Call the Doc!"; 109, assignment; 110, expression_list; 111, attribute; 112, identifier:now; 113, attribute; 114, identifier:TimeIsBackToFront; 115, identifier:msg; 116, call; 117, attribute; 118, identifier:msg; 119, identifier:datetime; 120, identifier:datetime; 121, identifier:chrw; 122, identifier:exceptions; 123, attribute; 124, argument_list; 125, attribute; 126, identifier:RequestRateTooHigh; 127, string:"Last request was {0}, should be at least {1}"; 128, identifier:format; 129, identifier:delta; 130, identifier:min_request_time; 131, identifier:chrw; 132, identifier:exceptions
code: def rate_limited(max_per_second):
      """ Sort of based off of an answer about
          rate limiting on Stack Overflow.
  
          Definitely **not** thread safe, so
          don't even think about it, buddy.
      """
      import datetime
      min_request_time = datetime.timedelta(seconds=max_per_second)
      last_time_called = [None]
      def decorate(func):
          def rate_limited_function(*args, **kwargs):
              if last_time_called[0]:
                  delta = datetime.datetime.now() - last_time_called[0]
                  if delta < datetime.timedelta.min:
                      raise chrw.exceptions.TimeIsBackToFront, "Call the Doc!"
                  elif delta < min_request_time:
                      msg = "Last request was {0}, should be at least {1}".format(
                          delta, min_request_time
                      )
                      raise chrw.exceptions.RequestRateTooHigh, msg
              ret = func(*args, **kwargs)
              last_time_called[0] = datetime.datetime.now()
              return ret
          return functools.update_wrapper(rate_limited_function, func)
      return decorate