Repository: encode/django-rest-framework

Issue:
TypeError: '>' not supported between instances of 'float' and 'NoneType'
## Checklist

- [x] I have verified that that issue exists against the `master` branch of Django REST framework.
- [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [x] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [x] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](https://www.django-rest-framework.org/community/third-party-packages/#about-third-party-packages) where possible.)
- [x] I have reduced the issue to the simplest possible case.
- [x] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

## Steps to reproduce

On Python 3.

This is a regression from https://github.com/encode/django-rest-framework/commit/afb678433b7dc068213e6e8a359ad1f6fff05b0d, when running a config-change scenario as described in https://github.com/encode/django-rest-framework/issues/1438

## Expected behavior

Not raise an exception

## Actual behavior

Raising `TypeError: '>' not supported between instances of 'float' and 'NoneType'`


Discussion:

Resolving patch:
diff --git a/rest_framework/views.py b/rest_framework/views.py
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -356,7 +356,15 @@ def check_throttles(self, request):
                 throttle_durations.append(throttle.wait())
 
         if throttle_durations:
-            self.throttled(request, max(throttle_durations))
+            # Filter out `None` values which may happen in case of config / rate
+            # changes, see #1438
+            durations = [
+                duration for duration in throttle_durations
+                if duration is not None
+            ]
+
+            duration = max(durations, default=None)
+            self.throttled(request, duration)
 
     def determine_version(self, request, *args, **kwargs):
         """


Test patch:
diff --git a/tests/test_throttling.py b/tests/test_throttling.py
--- a/tests/test_throttling.py
+++ b/tests/test_throttling.py
@@ -159,6 +159,27 @@ def test_request_throttling_multiple_throttles(self):
         assert response.status_code == 429
         assert int(response['retry-after']) == 58
 
+    def test_throttle_rate_change_negative(self):
+        self.set_throttle_timer(MockView_DoubleThrottling, 0)
+        request = self.factory.get('/')
+        for dummy in range(24):
+            response = MockView_DoubleThrottling.as_view()(request)
+        assert response.status_code == 429
+        assert int(response['retry-after']) == 60
+
+        previous_rate = User3SecRateThrottle.rate
+        try:
+            User3SecRateThrottle.rate = '1/sec'
+
+            for dummy in range(24):
+                response = MockView_DoubleThrottling.as_view()(request)
+
+            assert response.status_code == 429
+            assert int(response['retry-after']) == 60
+        finally:
+            # reset
+            User3SecRateThrottle.rate = previous_rate
+
     def ensure_response_header_contains_proper_throttle_field(self, view, expected_headers):
         """
         Ensure the response returns an Retry-After field with status and next attributes