File Replace-pytz-with-zoneinfo-datetime-timezone.patch of Package python-flask-restx

From 2c19169d2fc160cde80b217a574bdfbe6fc89185 Mon Sep 17 00:00:00 2001
From: nkrapp <nico.krapp@suse.com>
Date: Thu, 14 Nov 2024 14:30:29 +0100
Subject: [PATCH] Replace pytz with zoneinfo / datetime.timezone

---
 examples/zoo_app/requirements.txt |   1 -
 flask_restx/inputs.py             |  23 +-
 patch1.patch                      | 414 ++++++++++++++++++++++++++++++
 patch2.patch                      |  38 +++
 patch3.patch                      |  30 +++
 requirements/install.pip          |   1 -
 requirements/test.pip             |   2 +-
 tests/test_fields.py              |  24 +-
 tests/test_inputs.py              | 105 ++++----
 9 files changed, 563 insertions(+), 75 deletions(-)
 create mode 100644 patch1.patch
 create mode 100644 patch2.patch
 create mode 100644 patch3.patch

diff --git a/examples/zoo_app/requirements.txt b/examples/zoo_app/requirements.txt
index 4176fd5..77834eb 100644
--- a/examples/zoo_app/requirements.txt
+++ b/examples/zoo_app/requirements.txt
@@ -8,7 +8,6 @@ Jinja2==2.11.3
 jsonschema==3.2.0
 MarkupSafe==2.0.1
 pyrsistent==0.17.3
-pytz==2021.1
 six==1.16.0
 Werkzeug==2.2.3
 
diff --git a/flask_restx/inputs.py b/flask_restx/inputs.py
index 912ae16..e800a74 100644
--- a/flask_restx/inputs.py
+++ b/flask_restx/inputs.py
@@ -19,16 +19,15 @@ The last line allows you to document properly the type in the Swagger documentat
 import re
 import socket
 
-from datetime import datetime, time, timedelta
+from datetime import datetime, time, timedelta, timezone
 from email.utils import parsedate_tz, mktime_tz
 from urllib.parse import urlparse
 
 import aniso8601
-import pytz
 
 # Constants for upgrading date-based intervals to full datetimes.
-START_OF_DAY = time(0, 0, 0, tzinfo=pytz.UTC)
-END_OF_DAY = time(23, 59, 59, 999999, tzinfo=pytz.UTC)
+START_OF_DAY = time(0, 0, 0, tzinfo=timezone.utc)
+END_OF_DAY = time(23, 59, 59, 999999, tzinfo=timezone.utc)
 
 
 netloc_regex = re.compile(
@@ -338,11 +337,11 @@ def _normalize_interval(start, end, value):
         end = datetime.combine(end, START_OF_DAY)
 
     if start.tzinfo is None:
-        start = pytz.UTC.localize(start)
-        end = pytz.UTC.localize(end)
+        start = start.replace(tzinfo=timezone.utc)
+        end = end.replace(tzinfo=timezone.utc)
     else:
-        start = start.astimezone(pytz.UTC)
-        end = end.astimezone(pytz.UTC)
+        start = start.astimezone(timezone.utc)
+        end = end.astimezone(timezone.utc)
 
     return start, end
 
@@ -424,11 +423,11 @@ def iso8601interval(value, argument="argument"):
 
         start, end = _normalize_interval(start, end, value)
 
-    except ValueError:
+    except ValueError as e:
         msg = (
             "Invalid {arg}: {value}. {arg} must be a valid ISO8601 date/time interval."
         )
-        raise ValueError(msg.format(arg=argument, value=value))
+        raise ValueError(msg.format(arg=argument, value=value)) from e
 
     return start, end
 
@@ -559,9 +558,9 @@ def datetime_from_rfc822(value):
         timetuple = parsedate_tz(value)
         timestamp = mktime_tz(timetuple)
         if timetuple[-1] is None:
-            return datetime.fromtimestamp(timestamp).replace(tzinfo=pytz.utc)
+            return datetime.fromtimestamp(timestamp).replace(tzinfo=timezone.utc)
         else:
-            return datetime.fromtimestamp(timestamp, pytz.utc)
+            return datetime.fromtimestamp(timestamp, timezone.utc)
     except Exception:
         raise ValueError('Invalid date literal "{0}"'.format(raw))
 
diff --git a/patch1.patch b/patch1.patch
new file mode 100644
index 0000000..9bcdf2c
--- /dev/null
+++ b/patch1.patch
@@ -0,0 +1,414 @@
+From 687583ce84affc6e82c5e34c9e33676d634afa46 Mon Sep 17 00:00:00 2001
+From: jelmert <info@jelmert.nl>
+Date: Mon, 7 Oct 2024 12:06:19 +0200
+Subject: [PATCH] Replace pytz with zoneinfo / datetime.timezone
+
+---
+ examples/zoo_app/requirements.txt |  1 -
+ flask_restx/inputs.py             | 23 ++++---
+ requirements/install.pip          |  1 -
+ tests/test_fields.py              | 20 +++----
+ tests/test_inputs.py              | 99 +++++++++++++++----------------
+ 5 files changed, 70 insertions(+), 74 deletions(-)
+
+diff --git a/examples/zoo_app/requirements.txt b/examples/zoo_app/requirements.txt
+index 4176fd55..77834eb2 100644
+--- a/examples/zoo_app/requirements.txt
++++ b/examples/zoo_app/requirements.txt
+@@ -8,7 +8,6 @@ Jinja2==2.11.3
+ jsonschema==3.2.0
+ MarkupSafe==2.0.1
+ pyrsistent==0.17.3
+-pytz==2021.1
+ six==1.16.0
+ Werkzeug==2.2.3
+
+diff --git a/flask_restx/inputs.py b/flask_restx/inputs.py
+index 912ae164..e800a749 100644
+--- a/flask_restx/inputs.py
++++ b/flask_restx/inputs.py
+@@ -19,16 +19,15 @@ def my_type(value):
+ import re
+ import socket
+
+-from datetime import datetime, time, timedelta
++from datetime import datetime, time, timedelta, timezone
+ from email.utils import parsedate_tz, mktime_tz
+ from urllib.parse import urlparse
+
+ import aniso8601
+-import pytz
+
+ # Constants for upgrading date-based intervals to full datetimes.
+-START_OF_DAY = time(0, 0, 0, tzinfo=pytz.UTC)
+-END_OF_DAY = time(23, 59, 59, 999999, tzinfo=pytz.UTC)
++START_OF_DAY = time(0, 0, 0, tzinfo=timezone.utc)
++END_OF_DAY = time(23, 59, 59, 999999, tzinfo=timezone.utc)
+
+
+ netloc_regex = re.compile(
+@@ -338,11 +337,11 @@ def _normalize_interval(start, end, value):
+         end = datetime.combine(end, START_OF_DAY)
+
+     if start.tzinfo is None:
+-        start = pytz.UTC.localize(start)
+-        end = pytz.UTC.localize(end)
++        start = start.replace(tzinfo=timezone.utc)
++        end = end.replace(tzinfo=timezone.utc)
+     else:
+-        start = start.astimezone(pytz.UTC)
+-        end = end.astimezone(pytz.UTC)
++        start = start.astimezone(timezone.utc)
++        end = end.astimezone(timezone.utc)
+
+     return start, end
+
+@@ -424,11 +423,11 @@ def iso8601interval(value, argument="argument"):
+
+         start, end = _normalize_interval(start, end, value)
+
+-    except ValueError:
++    except ValueError as e:
+         msg = (
+             "Invalid {arg}: {value}. {arg} must be a valid ISO8601 date/time interval."
+         )
+-        raise ValueError(msg.format(arg=argument, value=value))
++        raise ValueError(msg.format(arg=argument, value=value)) from e
+
+     return start, end
+
+@@ -559,9 +558,9 @@ def datetime_from_rfc822(value):
+         timetuple = parsedate_tz(value)
+         timestamp = mktime_tz(timetuple)
+         if timetuple[-1] is None:
+-            return datetime.fromtimestamp(timestamp).replace(tzinfo=pytz.utc)
++            return datetime.fromtimestamp(timestamp).replace(tzinfo=timezone.utc)
+         else:
+-            return datetime.fromtimestamp(timestamp, pytz.utc)
++            return datetime.fromtimestamp(timestamp, timezone.utc)
+     except Exception:
+         raise ValueError('Invalid date literal "{0}"'.format(raw))
+
+diff --git a/requirements/install.pip b/requirements/install.pip
+index 76415edb..d4de41a8 100644
+--- a/requirements/install.pip
++++ b/requirements/install.pip
+@@ -2,5 +2,4 @@ aniso8601>=0.82
+ jsonschema
+ Flask>=0.8, !=2.0.0
+ werkzeug!=2.0.0
+-pytz
+ importlib_resources
+diff --git a/tests/test_fields.py b/tests/test_fields.py
+index 8b449887..8db0157f 100644
+--- a/tests/test_fields.py
++++ b/tests/test_fields.py
+@@ -1,9 +1,9 @@
++import zoneinfo
+ from collections import OrderedDict
+-from datetime import date, datetime
++from datetime import date, datetime, timezone
+ from decimal import Decimal
+ from functools import partial
+
+-import pytz
+ import pytest
+
+ from flask import Blueprint
+@@ -538,11 +538,11 @@ def test_max_exclusive(self):
+             (datetime(2011, 1, 1), "Sat, 01 Jan 2011 00:00:00 -0000"),
+             (datetime(2011, 1, 1, 23, 59, 59), "Sat, 01 Jan 2011 23:59:59 -0000"),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
+                 "Sat, 01 Jan 2011 23:59:59 -0000",
+             ),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
+                 "Sat, 01 Jan 2011 22:59:59 -0000",
+             ),
+         ],
+@@ -558,15 +558,15 @@ def test_rfc822_value(self, value, expected):
+             (datetime(2011, 1, 1, 23, 59, 59), "2011-01-01T23:59:59"),
+             (datetime(2011, 1, 1, 23, 59, 59, 1000), "2011-01-01T23:59:59.001000"),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
+                 "2011-01-01T23:59:59+00:00",
+             ),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc),
+                 "2011-01-01T23:59:59.001000+00:00",
+             ),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
+                 "2011-01-01T23:59:59+01:00",
+             ),
+         ],
+@@ -673,10 +673,10 @@ def test_max_exclusive(self):
+             (datetime(2011, 1, 1), "2011-01-01"),
+             (datetime(2011, 1, 1, 23, 59, 59), "2011-01-01"),
+             (datetime(2011, 1, 1, 23, 59, 59, 1000), "2011-01-01"),
+-            (datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc), "2011-01-01"),
+-            (datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc), "2011-01-01"),
++            (datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc), "2011-01-01"),
++            (datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc), "2011-01-01"),
+             (
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
+                 "2011-01-01",
+             ),
+         ],
+diff --git a/tests/test_inputs.py b/tests/test_inputs.py
+index eeac7e69..105976e8 100644
+--- a/tests/test_inputs.py
++++ b/tests/test_inputs.py
+@@ -1,8 +1,7 @@
+ import re
+-import pytz
+ import pytest
+
+-from datetime import date, datetime
++from datetime import date, datetime, timezone
+
+ from flask_restx import inputs
+
+@@ -37,18 +36,18 @@ class Iso8601DatetimeTest(object):
+         "value,expected",
+         [
+             ("2011-01-01", datetime(2011, 1, 1)),
+-            ("2011-01-01T00:00:00+00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
++            ("2011-01-01T00:00:00+00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+             (
+                 "2011-01-01T23:59:59+00:00",
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
+             ),
+             (
+                 "2011-01-01T23:59:59.001000+00:00",
+-                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc),
+             ),
+             (
+                 "2011-01-01T23:59:59+02:00",
+-                datetime(2011, 1, 1, 21, 59, 59, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 21, 59, 59, tzinfo=timezone.utc),
+             ),
+         ],
+     )
+@@ -70,22 +69,22 @@ class Rfc822DatetimeTest(object):
+     @pytest.mark.parametrize(
+         "value,expected",
+         [
+-            ("Sat, 01 Jan 2011", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+-            ("Sat, 01 Jan 2011 00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+-            ("Sat, 01 Jan 2011 00:00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+-            ("Sat, 01 Jan 2011 00:00:00 +0000", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+-            ("Sat, 01 Jan 2011 00:00:00 -0000", datetime(2011, 1, 1, tzinfo=pytz.utc)),
++            ("Sat, 01 Jan 2011", datetime(2011, 1, 1, tzinfo=timezone.utc)),
++            ("Sat, 01 Jan 2011 00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
++            ("Sat, 01 Jan 2011 00:00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
++            ("Sat, 01 Jan 2011 00:00:00 +0000", datetime(2011, 1, 1, tzinfo=timezone.utc)),
++            ("Sat, 01 Jan 2011 00:00:00 -0000", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+             (
+                 "Sat, 01 Jan 2011 23:59:59 -0000",
+-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
+             ),
+             (
+                 "Sat, 01 Jan 2011 21:00:00 +0200",
+-                datetime(2011, 1, 1, 19, 0, 0, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 19, 0, 0, tzinfo=timezone.utc),
+             ),
+             (
+                 "Sat, 01 Jan 2011 21:00:00 -0200",
+-                datetime(2011, 1, 1, 23, 0, 0, tzinfo=pytz.utc),
++                datetime(2011, 1, 1, 23, 0, 0, tzinfo=timezone.utc),
+             ),
+         ],
+     )
+@@ -985,136 +984,136 @@ def test_schema(self):
+         # Full precision with explicit UTC.
+         "2013-01-01T12:30:00Z/P1Y2M3DT4H5M6S",
+         (
+-            datetime(2013, 1, 1, 12, 30, 0, tzinfo=pytz.utc),
+-            datetime(2014, 3, 5, 16, 35, 6, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, 0, tzinfo=timezone.utc),
++            datetime(2014, 3, 5, 16, 35, 6, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Full precision with alternate UTC indication
+         "2013-01-01T12:30+00:00/P2D",
+         (
+-            datetime(2013, 1, 1, 12, 30, 0, tzinfo=pytz.utc),
+-            datetime(2013, 1, 3, 12, 30, 0, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, 0, tzinfo=timezone.utc),
++            datetime(2013, 1, 3, 12, 30, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Implicit UTC with time
+         "2013-01-01T15:00/P1M",
+         (
+-            datetime(2013, 1, 1, 15, 0, 0, tzinfo=pytz.utc),
+-            datetime(2013, 1, 31, 15, 0, 0, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 15, 0, 0, tzinfo=timezone.utc),
++            datetime(2013, 1, 31, 15, 0, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # TZ conversion
+         "2013-01-01T17:00-05:00/P2W",
+         (
+-            datetime(2013, 1, 1, 22, 0, 0, tzinfo=pytz.utc),
+-            datetime(2013, 1, 15, 22, 0, 0, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 22, 0, 0, tzinfo=timezone.utc),
++            datetime(2013, 1, 15, 22, 0, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Date upgrade to midnight-midnight period
+         "2013-01-01/P3D",
+         (
+-            datetime(2013, 1, 1, 0, 0, 0, tzinfo=pytz.utc),
+-            datetime(2013, 1, 4, 0, 0, 0, 0, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
++            datetime(2013, 1, 4, 0, 0, 0, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Start/end with UTC
+         "2013-01-01T12:00:00Z/2013-02-01T12:00:00Z",
+         (
+-            datetime(2013, 1, 1, 12, 0, 0, tzinfo=pytz.utc),
+-            datetime(2013, 2, 1, 12, 0, 0, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
++            datetime(2013, 2, 1, 12, 0, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Start/end with time upgrade
+         "2013-01-01/2013-06-30",
+         (
+-            datetime(2013, 1, 1, tzinfo=pytz.utc),
+-            datetime(2013, 6, 30, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, tzinfo=timezone.utc),
++            datetime(2013, 6, 30, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Start/end with TZ conversion
+         "2013-02-17T12:00:00-07:00/2013-02-28T15:00:00-07:00",
+         (
+-            datetime(2013, 2, 17, 19, 0, 0, tzinfo=pytz.utc),
+-            datetime(2013, 2, 28, 22, 0, 0, tzinfo=pytz.utc),
++            datetime(2013, 2, 17, 19, 0, 0, tzinfo=timezone.utc),
++            datetime(2013, 2, 28, 22, 0, 0, tzinfo=timezone.utc),
+         ),
+     ),
+     (  # Resolution expansion for single date(time)
+         # Second with UTC
+         "2013-01-01T12:30:45Z",
+         (
+-            datetime(2013, 1, 1, 12, 30, 45, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 12, 30, 46, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, 45, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 12, 30, 46, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Second with tz conversion
+         "2013-01-01T12:30:45+02:00",
+         (
+-            datetime(2013, 1, 1, 10, 30, 45, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 10, 30, 46, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 10, 30, 45, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 10, 30, 46, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Second with implicit UTC
+         "2013-01-01T12:30:45",
+         (
+-            datetime(2013, 1, 1, 12, 30, 45, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 12, 30, 46, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, 45, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 12, 30, 46, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Minute with UTC
+         "2013-01-01T12:30+00:00",
+         (
+-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 12, 31, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 12, 31, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Minute with conversion
+         "2013-01-01T12:30+04:00",
+         (
+-            datetime(2013, 1, 1, 8, 30, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 8, 31, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 8, 30, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 8, 31, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Minute with implicit UTC
+         "2013-01-01T12:30",
+         (
+-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 12, 31, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 12, 31, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Hour, explicit UTC
+         "2013-01-01T12Z",
+         (
+-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 13, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 13, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Hour with offset
+         "2013-01-01T12-07:00",
+         (
+-            datetime(2013, 1, 1, 19, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 20, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 19, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 20, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+         # Hour with implicit UTC
+         "2013-01-01T12",
+         (
+-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 13, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 13, tzinfo=timezone.utc),
+         ),
+     ),
+     (
+@@ -1122,8 +1121,8 @@ def test_schema(self):
+         # be accepted.
+         "2013-01-01T12:00:00.0/2013-01-01T12:30:00.000000",
+         (
+-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
+-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
++            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
++            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
+         ),
+     ),
+ ]
diff --git a/patch2.patch b/patch2.patch
new file mode 100644
index 0000000..c3a66bd
--- /dev/null
+++ b/patch2.patch
@@ -0,0 +1,38 @@
+From f1ffea2e08e3bb88c5bc261550309c97f5bf9ba3 Mon Sep 17 00:00:00 2001
+From: jelmert <info@jelmert.nl>
+Date: Mon, 7 Oct 2024 12:42:43 +0200
+Subject: [PATCH] Remove tzlocal from test requirements since it is unsued, add
+ backports.zoneinfo for python 3.8
+
+---
+ requirements/test.pip | 2 +-
+ tests/test_fields.py  | 6 +++++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/requirements/test.pip b/requirements/test.pip
+index e4d58140..6ce09332 100644
+--- a/requirements/test.pip
++++ b/requirements/test.pip
+@@ -7,7 +7,7 @@ pytest-cov==4.0.0
+ pytest-flask==1.3.0
+ pytest-mock==3.6.1
+ pytest-profiling==1.7.0
+-tzlocal
+ invoke==2.2.0
+ twine==3.8.0
+ setuptools
++backports.zoneinfo;python_version<"3.9"
+diff --git a/tests/test_fields.py b/tests/test_fields.py
+index 8db0157f..7b0333a4 100644
+--- a/tests/test_fields.py
++++ b/tests/test_fields.py
+@@ -1,4 +1,8 @@
+-import zoneinfo
++try:
++    import zoneinfo
++except ImportError:
++    from backports import zoneinfo
++
+ from collections import OrderedDict
+ from datetime import date, datetime, timezone
+ from decimal import Decimal
diff --git a/patch3.patch b/patch3.patch
new file mode 100644
index 0000000..a712e09
--- /dev/null
+++ b/patch3.patch
@@ -0,0 +1,30 @@
+From d99ec571e68a71864b2ae16d0d451899c0f3f117 Mon Sep 17 00:00:00 2001
+From: jelmert <info@jelmert.nl>
+Date: Mon, 7 Oct 2024 12:43:30 +0200
+Subject: [PATCH] Fix formatting
+
+---
+ tests/test_inputs.py | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/tests/test_inputs.py b/tests/test_inputs.py
+index 105976e8..73ae6425 100644
+--- a/tests/test_inputs.py
++++ b/tests/test_inputs.py
+@@ -72,8 +72,14 @@ class Rfc822DatetimeTest(object):
+             ("Sat, 01 Jan 2011", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+             ("Sat, 01 Jan 2011 00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+             ("Sat, 01 Jan 2011 00:00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+-            ("Sat, 01 Jan 2011 00:00:00 +0000", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+-            ("Sat, 01 Jan 2011 00:00:00 -0000", datetime(2011, 1, 1, tzinfo=timezone.utc)),
++            (
++                "Sat, 01 Jan 2011 00:00:00 +0000",
++                datetime(2011, 1, 1, tzinfo=timezone.utc),
++            ),
++            (
++                "Sat, 01 Jan 2011 00:00:00 -0000",
++                datetime(2011, 1, 1, tzinfo=timezone.utc),
++            ),
+             (
+                 "Sat, 01 Jan 2011 23:59:59 -0000",
+                 datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
diff --git a/requirements/install.pip b/requirements/install.pip
index 76415ed..d4de41a 100644
--- a/requirements/install.pip
+++ b/requirements/install.pip
@@ -2,5 +2,4 @@ aniso8601>=0.82
 jsonschema
 Flask>=0.8, !=2.0.0
 werkzeug!=2.0.0
-pytz
 importlib_resources
diff --git a/requirements/test.pip b/requirements/test.pip
index e4d5814..6ce0933 100644
--- a/requirements/test.pip
+++ b/requirements/test.pip
@@ -7,7 +7,7 @@ pytest-cov==4.0.0
 pytest-flask==1.3.0
 pytest-mock==3.6.1
 pytest-profiling==1.7.0
-tzlocal
 invoke==2.2.0
 twine==3.8.0
 setuptools
+backports.zoneinfo;python_version<"3.9"
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 8b44988..7b0333a 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -1,9 +1,13 @@
+try:
+    import zoneinfo
+except ImportError:
+    from backports import zoneinfo
+
 from collections import OrderedDict
-from datetime import date, datetime
+from datetime import date, datetime, timezone
 from decimal import Decimal
 from functools import partial
 
-import pytz
 import pytest
 
 from flask import Blueprint
@@ -538,11 +542,11 @@ class DatetimeFieldTest(BaseFieldTestMixin, FieldTestCase):
             (datetime(2011, 1, 1), "Sat, 01 Jan 2011 00:00:00 -0000"),
             (datetime(2011, 1, 1, 23, 59, 59), "Sat, 01 Jan 2011 23:59:59 -0000"),
             (
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
                 "Sat, 01 Jan 2011 23:59:59 -0000",
             ),
             (
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
                 "Sat, 01 Jan 2011 22:59:59 -0000",
             ),
         ],
@@ -558,15 +562,15 @@ class DatetimeFieldTest(BaseFieldTestMixin, FieldTestCase):
             (datetime(2011, 1, 1, 23, 59, 59), "2011-01-01T23:59:59"),
             (datetime(2011, 1, 1, 23, 59, 59, 1000), "2011-01-01T23:59:59.001000"),
             (
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
                 "2011-01-01T23:59:59+00:00",
             ),
             (
-                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc),
                 "2011-01-01T23:59:59.001000+00:00",
             ),
             (
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
                 "2011-01-01T23:59:59+01:00",
             ),
         ],
@@ -673,10 +677,10 @@ class DateFieldTest(BaseFieldTestMixin, FieldTestCase):
             (datetime(2011, 1, 1), "2011-01-01"),
             (datetime(2011, 1, 1, 23, 59, 59), "2011-01-01"),
             (datetime(2011, 1, 1, 23, 59, 59, 1000), "2011-01-01"),
-            (datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc), "2011-01-01"),
-            (datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc), "2011-01-01"),
+            (datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc), "2011-01-01"),
+            (datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc), "2011-01-01"),
             (
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone("CET")),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=zoneinfo.ZoneInfo("CET")),
                 "2011-01-01",
             ),
         ],
diff --git a/tests/test_inputs.py b/tests/test_inputs.py
index eeac7e6..73ae642 100644
--- a/tests/test_inputs.py
+++ b/tests/test_inputs.py
@@ -1,8 +1,7 @@
 import re
-import pytz
 import pytest
 
-from datetime import date, datetime
+from datetime import date, datetime, timezone
 
 from flask_restx import inputs
 
@@ -37,18 +36,18 @@ class Iso8601DatetimeTest(object):
         "value,expected",
         [
             ("2011-01-01", datetime(2011, 1, 1)),
-            ("2011-01-01T00:00:00+00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+            ("2011-01-01T00:00:00+00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
             (
                 "2011-01-01T23:59:59+00:00",
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
             ),
             (
                 "2011-01-01T23:59:59.001000+00:00",
-                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=timezone.utc),
             ),
             (
                 "2011-01-01T23:59:59+02:00",
-                datetime(2011, 1, 1, 21, 59, 59, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 21, 59, 59, tzinfo=timezone.utc),
             ),
         ],
     )
@@ -70,22 +69,28 @@ class Rfc822DatetimeTest(object):
     @pytest.mark.parametrize(
         "value,expected",
         [
-            ("Sat, 01 Jan 2011", datetime(2011, 1, 1, tzinfo=pytz.utc)),
-            ("Sat, 01 Jan 2011 00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
-            ("Sat, 01 Jan 2011 00:00:00", datetime(2011, 1, 1, tzinfo=pytz.utc)),
-            ("Sat, 01 Jan 2011 00:00:00 +0000", datetime(2011, 1, 1, tzinfo=pytz.utc)),
-            ("Sat, 01 Jan 2011 00:00:00 -0000", datetime(2011, 1, 1, tzinfo=pytz.utc)),
+            ("Sat, 01 Jan 2011", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+            ("Sat, 01 Jan 2011 00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+            ("Sat, 01 Jan 2011 00:00:00", datetime(2011, 1, 1, tzinfo=timezone.utc)),
+            (
+                "Sat, 01 Jan 2011 00:00:00 +0000",
+                datetime(2011, 1, 1, tzinfo=timezone.utc),
+            ),
+            (
+                "Sat, 01 Jan 2011 00:00:00 -0000",
+                datetime(2011, 1, 1, tzinfo=timezone.utc),
+            ),
             (
                 "Sat, 01 Jan 2011 23:59:59 -0000",
-                datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 59, 59, tzinfo=timezone.utc),
             ),
             (
                 "Sat, 01 Jan 2011 21:00:00 +0200",
-                datetime(2011, 1, 1, 19, 0, 0, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 19, 0, 0, tzinfo=timezone.utc),
             ),
             (
                 "Sat, 01 Jan 2011 21:00:00 -0200",
-                datetime(2011, 1, 1, 23, 0, 0, tzinfo=pytz.utc),
+                datetime(2011, 1, 1, 23, 0, 0, tzinfo=timezone.utc),
             ),
         ],
     )
@@ -985,136 +990,136 @@ interval_test_values = [
         # Full precision with explicit UTC.
         "2013-01-01T12:30:00Z/P1Y2M3DT4H5M6S",
         (
-            datetime(2013, 1, 1, 12, 30, 0, tzinfo=pytz.utc),
-            datetime(2014, 3, 5, 16, 35, 6, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, 0, tzinfo=timezone.utc),
+            datetime(2014, 3, 5, 16, 35, 6, tzinfo=timezone.utc),
         ),
     ),
     (
         # Full precision with alternate UTC indication
         "2013-01-01T12:30+00:00/P2D",
         (
-            datetime(2013, 1, 1, 12, 30, 0, tzinfo=pytz.utc),
-            datetime(2013, 1, 3, 12, 30, 0, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, 0, tzinfo=timezone.utc),
+            datetime(2013, 1, 3, 12, 30, 0, tzinfo=timezone.utc),
         ),
     ),
     (
         # Implicit UTC with time
         "2013-01-01T15:00/P1M",
         (
-            datetime(2013, 1, 1, 15, 0, 0, tzinfo=pytz.utc),
-            datetime(2013, 1, 31, 15, 0, 0, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 15, 0, 0, tzinfo=timezone.utc),
+            datetime(2013, 1, 31, 15, 0, 0, tzinfo=timezone.utc),
         ),
     ),
     (
         # TZ conversion
         "2013-01-01T17:00-05:00/P2W",
         (
-            datetime(2013, 1, 1, 22, 0, 0, tzinfo=pytz.utc),
-            datetime(2013, 1, 15, 22, 0, 0, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 22, 0, 0, tzinfo=timezone.utc),
+            datetime(2013, 1, 15, 22, 0, 0, tzinfo=timezone.utc),
         ),
     ),
     (
         # Date upgrade to midnight-midnight period
         "2013-01-01/P3D",
         (
-            datetime(2013, 1, 1, 0, 0, 0, tzinfo=pytz.utc),
-            datetime(2013, 1, 4, 0, 0, 0, 0, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+            datetime(2013, 1, 4, 0, 0, 0, 0, tzinfo=timezone.utc),
         ),
     ),
     (
         # Start/end with UTC
         "2013-01-01T12:00:00Z/2013-02-01T12:00:00Z",
         (
-            datetime(2013, 1, 1, 12, 0, 0, tzinfo=pytz.utc),
-            datetime(2013, 2, 1, 12, 0, 0, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
+            datetime(2013, 2, 1, 12, 0, 0, tzinfo=timezone.utc),
         ),
     ),
     (
         # Start/end with time upgrade
         "2013-01-01/2013-06-30",
         (
-            datetime(2013, 1, 1, tzinfo=pytz.utc),
-            datetime(2013, 6, 30, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, tzinfo=timezone.utc),
+            datetime(2013, 6, 30, tzinfo=timezone.utc),
         ),
     ),
     (
         # Start/end with TZ conversion
         "2013-02-17T12:00:00-07:00/2013-02-28T15:00:00-07:00",
         (
-            datetime(2013, 2, 17, 19, 0, 0, tzinfo=pytz.utc),
-            datetime(2013, 2, 28, 22, 0, 0, tzinfo=pytz.utc),
+            datetime(2013, 2, 17, 19, 0, 0, tzinfo=timezone.utc),
+            datetime(2013, 2, 28, 22, 0, 0, tzinfo=timezone.utc),
         ),
     ),
     (  # Resolution expansion for single date(time)
         # Second with UTC
         "2013-01-01T12:30:45Z",
         (
-            datetime(2013, 1, 1, 12, 30, 45, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 12, 30, 46, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, 45, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 12, 30, 46, tzinfo=timezone.utc),
         ),
     ),
     (
         # Second with tz conversion
         "2013-01-01T12:30:45+02:00",
         (
-            datetime(2013, 1, 1, 10, 30, 45, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 10, 30, 46, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 10, 30, 45, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 10, 30, 46, tzinfo=timezone.utc),
         ),
     ),
     (
         # Second with implicit UTC
         "2013-01-01T12:30:45",
         (
-            datetime(2013, 1, 1, 12, 30, 45, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 12, 30, 46, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, 45, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 12, 30, 46, tzinfo=timezone.utc),
         ),
     ),
     (
         # Minute with UTC
         "2013-01-01T12:30+00:00",
         (
-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 12, 31, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 12, 31, tzinfo=timezone.utc),
         ),
     ),
     (
         # Minute with conversion
         "2013-01-01T12:30+04:00",
         (
-            datetime(2013, 1, 1, 8, 30, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 8, 31, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 8, 30, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 8, 31, tzinfo=timezone.utc),
         ),
     ),
     (
         # Minute with implicit UTC
         "2013-01-01T12:30",
         (
-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 12, 31, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 12, 31, tzinfo=timezone.utc),
         ),
     ),
     (
         # Hour, explicit UTC
         "2013-01-01T12Z",
         (
-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 13, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 13, tzinfo=timezone.utc),
         ),
     ),
     (
         # Hour with offset
         "2013-01-01T12-07:00",
         (
-            datetime(2013, 1, 1, 19, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 20, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 19, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 20, tzinfo=timezone.utc),
         ),
     ),
     (
         # Hour with implicit UTC
         "2013-01-01T12",
         (
-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 13, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 13, tzinfo=timezone.utc),
         ),
     ),
     (
@@ -1122,8 +1127,8 @@ interval_test_values = [
         # be accepted.
         "2013-01-01T12:00:00.0/2013-01-01T12:30:00.000000",
         (
-            datetime(2013, 1, 1, 12, tzinfo=pytz.utc),
-            datetime(2013, 1, 1, 12, 30, tzinfo=pytz.utc),
+            datetime(2013, 1, 1, 12, tzinfo=timezone.utc),
+            datetime(2013, 1, 1, 12, 30, tzinfo=timezone.utc),
         ),
     ),
 ]
-- 
2.47.0

openSUSE Build Service is sponsored by