diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 239df13..8ca5f30 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.5.0
+    rev: v5.0.0
     hooks:
       - id: trailing-whitespace
       # Replaces or checks mixed line ending
@@ -19,13 +19,18 @@ repos:
       - id: check-yaml
         files: .*\.(yaml|yml)$
   - repo: https://opendev.org/openstack/hacking
-    rev: 6.1.0
+    rev: 7.0.0
     hooks:
       - id: hacking
         additional_dependencies: []
         exclude: '^(doc|releasenotes|tools)/.*$'
   - repo: https://github.com/PyCQA/bandit
-    rev: 1.7.6
+    rev: 1.7.10
     hooks:
       - id: bandit
         args: ['-x', 'tests', '--skip', 'B411']
+  - repo: https://github.com/asottile/pyupgrade
+    rev: v3.18.0
+    hooks:
+      - id: pyupgrade
+        args: [--py3-only]
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 81f14e3..f464a29 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # Copyright (C) 2020 Red Hat, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/oslo_serialization/jsonutils.py b/oslo_serialization/jsonutils.py
index 89b6862..637e430 100644
--- a/oslo_serialization/jsonutils.py
+++ b/oslo_serialization/jsonutils.py
@@ -181,7 +181,7 @@ def to_primitive(value, convert_instances=False, convert_datetime=True,
         return fallback(value)
 
     if orig_fallback is None:
-        raise ValueError("Cannot convert %r to primitive" % (value,))
+        raise ValueError("Cannot convert {!r} to primitive".format(value))
 
     return orig_fallback(value)
 
diff --git a/oslo_serialization/msgpackutils.py b/oslo_serialization/msgpackutils.py
index eb9cb31..a6cdb3a 100644
--- a/oslo_serialization/msgpackutils.py
+++ b/oslo_serialization/msgpackutils.py
@@ -42,7 +42,7 @@ from oslo_utils import importutils
 netaddr = importutils.try_import("netaddr")
 
 
-class Interval(object):
+class Interval:
     """Small and/or simple immutable integer/float interval class.
 
     Interval checking is **inclusive** of the min/max boundaries.
@@ -68,7 +68,7 @@ class Interval(object):
         return value >= self.min_value and value <= self.max_value
 
     def __repr__(self):
-        return 'Interval(%s, %s)' % (self._min_value, self._max_value)
+        return 'Interval({}, {})'.format(self._min_value, self._max_value)
 
 
 # Expose these so that users don't have to import msgpack to gain these.
@@ -77,7 +77,7 @@ PackException = msgpack.PackException
 UnpackException = msgpack.UnpackException
 
 
-class HandlerRegistry(object):
+class HandlerRegistry:
     """Registry of *type* specific msgpack handlers extensions.
 
     See: https://github.com/msgpack/msgpack/blob/master/spec.md#formats-ext
@@ -127,8 +127,7 @@ class HandlerRegistry(object):
     def __iter__(self):
         """Iterates over **all** registered handlers."""
         for handlers in self._handlers.values():
-            for h in handlers:
-                yield h
+            yield from handlers
 
     def register(self, handler, reserved=False, override=False):
         """Register a extension handler to handle its associated type."""
@@ -203,7 +202,7 @@ class HandlerRegistry(object):
         return None
 
 
-class UUIDHandler(object):
+class UUIDHandler:
     identity = 0
     handles = (uuid.UUID,)
 
@@ -216,7 +215,7 @@ class UUIDHandler(object):
         return uuid.UUID(hex=str(data, encoding='ascii'))
 
 
-class DateTimeHandler(object):
+class DateTimeHandler:
     identity = 1
     handles = (datetime.datetime,)
 
@@ -252,7 +251,7 @@ class DateTimeHandler(object):
             # But for python3, we have some backward compability
             # to take care in case of the payload have been produced
             # by python2 and now read by python3
-            dct = dict((k.decode("ascii"), v) for k, v in dct.items())
+            dct = {k.decode("ascii"): v for k, v in dct.items()}
             if 'tz' in dct:
                 dct['tz'] = dct['tz'].decode("ascii")
 
@@ -268,7 +267,7 @@ class DateTimeHandler(object):
         return dt
 
 
-class CountHandler(object):
+class CountHandler:
     identity = 2
     handles = (itertools.count,)
 
@@ -296,7 +295,7 @@ class CountHandler(object):
 
 
 if netaddr is not None:
-    class NetAddrIPHandler(object):
+    class NetAddrIPHandler:
         identity = 3
         handles = (netaddr.IPAddress,)
 
@@ -311,7 +310,7 @@ else:
     NetAddrIPHandler = None
 
 
-class SetHandler(object):
+class SetHandler:
     identity = 4
     handles = (set,)
 
@@ -333,7 +332,7 @@ class FrozenSetHandler(SetHandler):
     handles = (frozenset,)
 
 
-class XMLRPCDateTimeHandler(object):
+class XMLRPCDateTimeHandler:
     handles = (xmlrpclib.DateTime,)
     identity = 6
 
@@ -352,7 +351,7 @@ class XMLRPCDateTimeHandler(object):
         return xmlrpclib.DateTime(dt.timetuple())
 
 
-class DateHandler(object):
+class DateHandler:
     identity = 7
     handles = (datetime.date,)
 
@@ -374,7 +373,7 @@ class DateHandler(object):
         dct = loads(blob, registry=self._registry)
         if b"day" in dct:
             # NOTE(sileht): see DateTimeHandler.deserialize()
-            dct = dict((k.decode("ascii"), v) for k, v in dct.items())
+            dct = {k.decode("ascii"): v for k, v in dct.items()}
 
         return datetime.date(year=dct['year'],
                              month=dct['month'],
diff --git a/oslo_serialization/serializer/base_serializer.py b/oslo_serialization/serializer/base_serializer.py
index 2950d8e..90a5936 100644
--- a/oslo_serialization/serializer/base_serializer.py
+++ b/oslo_serialization/serializer/base_serializer.py
@@ -20,7 +20,7 @@ Unified and simplified API for oslo.serialization's serializers.
 import abc
 
 
-class BaseSerializer(object, metaclass=abc.ABCMeta):
+class BaseSerializer(metaclass=abc.ABCMeta):
     """Generic (de-)serialization definition abstract base class."""
 
     @abc.abstractmethod
diff --git a/oslo_serialization/tests/test_jsonutils.py b/oslo_serialization/tests/test_jsonutils.py
index d68b22c..452e76d 100644
--- a/oslo_serialization/tests/test_jsonutils.py
+++ b/oslo_serialization/tests/test_jsonutils.py
@@ -31,17 +31,17 @@ from oslotest import base as test_base
 from oslo_serialization import jsonutils
 
 
-class ReprObject(object):
+class ReprObject:
     def __repr__(self):
         return 'repr'
 
 
-class JSONUtilsTestMixin(object):
+class JSONUtilsTestMixin:
 
     json_impl = None
 
     def setUp(self):
-        super(JSONUtilsTestMixin, self).setUp()
+        super().setUp()
         self.json_patcher = mock.patch.multiple(
             jsonutils, json=self.json_impl,
         )
@@ -49,7 +49,7 @@ class JSONUtilsTestMixin(object):
 
     def tearDown(self):
         self.json_patcher.stop()
-        super(JSONUtilsTestMixin, self).tearDown()
+        super().tearDown()
 
     def test_dumps(self):
         self.assertEqual('{"a": "b"}', jsonutils.dumps({'a': 'b'}))
@@ -128,7 +128,7 @@ class JSONUtilsTestJson(JSONUtilsTestMixin, test_base.BaseTestCase):
 
 class ToPrimitiveTestCase(test_base.BaseTestCase):
     def setUp(self):
-        super(ToPrimitiveTestCase, self).setUp()
+        super().setUp()
         self.trans_fixture = self.useFixture(fixture.Translation())
 
     def test_bytes(self):
@@ -175,7 +175,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
                          jsonutils.to_primitive(x))
 
     def test_iter(self):
-        class IterClass(object):
+        class IterClass:
             def __init__(self):
                 self.data = [1, 2, 3, 4, 5]
                 self.index = 0
@@ -194,7 +194,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         self.assertEqual([1, 2, 3, 4, 5], jsonutils.to_primitive(x))
 
     def test_iteritems(self):
-        class IterItemsClass(object):
+        class IterItemsClass:
             def __init__(self):
                 self.data = dict(a=1, b=2, c=3).items()
                 self.index = 0
@@ -207,7 +207,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         self.assertEqual({'a': 1, 'b': 2, 'c': 3}, p)
 
     def test_iteritems_with_cycle(self):
-        class IterItemsClass(object):
+        class IterItemsClass:
             def __init__(self):
                 self.data = dict(a=1, b=2, c=3)
                 self.index = 0
@@ -226,7 +226,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
 
     def test_items(self):
         # Use items() when iteritems() is not available.
-        class ItemsClass(object):
+        class ItemsClass:
             def __init__(self):
                 self.data = dict(a=1, b=2, c=3)
 
@@ -238,7 +238,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         self.assertEqual({'a': 1, 'b': 2, 'c': 3}, p)
 
     def test_precedence_items_iteritems(self):
-        class ItemsIterItemsClass(object):
+        class ItemsIterItemsClass:
             def items(self):
                 return {'items': 'items'}
 
@@ -271,7 +271,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         self.assertEqual({'a': 1, 'b': 2, 'c': 3}, p)
 
     def test_instance(self):
-        class MysteryClass(object):
+        class MysteryClass:
             a = 10
 
             def __init__(self):
@@ -285,7 +285,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
 
     def test_typeerror(self):
         x = bytearray  # Class, not instance
-        self.assertEqual(u"<class 'bytearray'>", jsonutils.to_primitive(x))
+        self.assertEqual("<class 'bytearray'>", jsonutils.to_primitive(x))
 
     def test_nasties(self):
         def foo():
@@ -293,15 +293,15 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         x = [datetime, foo, dir]
         ret = jsonutils.to_primitive(x)
         self.assertEqual(3, len(ret))
-        self.assertTrue(ret[0].startswith(u"<module 'datetime' from ") or
-                        ret[0].startswith(u"<module 'datetime' (built-in)"))
+        self.assertTrue(ret[0].startswith("<module 'datetime' from ") or
+                        ret[0].startswith("<module 'datetime' (built-in)"))
         self.assertTrue(ret[1].startswith(
             '<function ToPrimitiveTestCase.test_nasties.<locals>.foo at 0x'
         ))
         self.assertEqual('<built-in function dir>', ret[2])
 
     def test_depth(self):
-        class LevelsGenerator(object):
+        class LevelsGenerator:
             def __init__(self, levels):
                 self._levels = levels
 
@@ -395,7 +395,7 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
         self.assertEqual("type:int", ret)
 
     def test_fallback_typeerror(self):
-        class NotIterable(object):
+        class NotIterable:
             # __iter__ is not callable, cause a TypeError in to_primitive()
             __iter__ = None
 
diff --git a/oslo_serialization/tests/test_msgpackutils.py b/oslo_serialization/tests/test_msgpackutils.py
index 7558532..f47efb9 100644
--- a/oslo_serialization/tests/test_msgpackutils.py
+++ b/oslo_serialization/tests/test_msgpackutils.py
@@ -33,14 +33,14 @@ from oslo_utils import uuidutils
 _TZ_FMT = '%Y-%m-%d %H:%M:%S %Z%z'
 
 
-class Color(object):
+class Color:
     def __init__(self, r, g, b):
         self.r = r
         self.g = g
         self.b = b
 
 
-class ColorHandler(object):
+class ColorHandler:
     handles = (Color,)
     identity = (
         msgpackutils.HandlerRegistry.non_reserved_extension_range.min_value + 1
@@ -48,7 +48,7 @@ class ColorHandler(object):
 
     @staticmethod
     def serialize(obj):
-        blob = '%s, %s, %s' % (obj.r, obj.g, obj.b)
+        blob = '{}, {}, {}'.format(obj.r, obj.g, obj.b)
         blob = blob.encode('ascii')
         return blob
 
@@ -58,7 +58,7 @@ class ColorHandler(object):
         return Color(chunks[0], chunks[1], chunks[2])
 
 
-class MySpecialSetHandler(object):
+class MySpecialSetHandler:
     handles = (set,)
     identity = msgpackutils.SetHandler.identity
 
@@ -97,7 +97,7 @@ class MsgPackUtilsTest(test_base.BaseTestCase):
             'a': 1,
             'b': 2.0,
             'c': [],
-            'd': set([1, 2, 3]),
+            'd': {1, 2, 3},
             'zzz': uuidutils.generate_uuid(),
             'yyy': 'yyy',
             'ddd': b'bbb',
@@ -122,10 +122,10 @@ class MsgPackUtilsTest(test_base.BaseTestCase):
         self.assertEqual(next(it), next(it2))
 
     def test_set(self):
-        self.assertEqual(set([1, 2]), _dumps_loads(set([1, 2])))
+        self.assertEqual({1, 2}, _dumps_loads({1, 2}))
 
     def test_empty_set(self):
-        self.assertEqual(set([]), _dumps_loads(set([])))
+        self.assertEqual(set(), _dumps_loads(set()))
 
     def test_frozenset(self):
         self.assertEqual(frozenset([1, 2]), _dumps_loads(frozenset([1, 2])))
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index 294d1e1..53321ba 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # Copyright (C) 2020 Red Hat, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");