eventsourcing 9.4.0a6__py3-none-any.whl → 9.4.0a8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of eventsourcing might be problematic. Click here for more details.

@@ -10,10 +10,12 @@ from tempfile import NamedTemporaryFile
10
10
  from threading import Event, Thread, get_ident
11
11
  from time import sleep
12
12
  from timeit import timeit
13
- from typing import Any
13
+ from typing import TYPE_CHECKING, Any, Generic, cast
14
14
  from unittest import TestCase
15
15
  from uuid import UUID, uuid4
16
16
 
17
+ from typing_extensions import TypeVar
18
+
17
19
  from eventsourcing.cipher import AESCipher
18
20
  from eventsourcing.compressor import ZlibCompressor
19
21
  from eventsourcing.domain import DomainEvent
@@ -31,12 +33,18 @@ from eventsourcing.persistence import (
31
33
  StoredEvent,
32
34
  Tracking,
33
35
  TrackingRecorder,
36
+ Transcoder,
34
37
  Transcoding,
35
38
  UUIDAsHex,
36
39
  WaitInterruptedError,
37
40
  )
38
41
  from eventsourcing.utils import Environment, get_topic
39
42
 
43
+ if TYPE_CHECKING:
44
+ from collections.abc import Iterator
45
+
46
+ from typing_extensions import Never
47
+
40
48
 
41
49
  class AggregateRecorderTestCase(TestCase, ABC):
42
50
  INITIAL_VERSION = 1
@@ -207,12 +215,17 @@ class AggregateRecorderTestCase(TestCase, ABC):
207
215
  )
208
216
 
209
217
 
210
- class ApplicationRecorderTestCase(TestCase, ABC):
218
+ _TApplicationRecorder = TypeVar(
219
+ "_TApplicationRecorder", bound=ApplicationRecorder, default=ApplicationRecorder
220
+ )
221
+
222
+
223
+ class ApplicationRecorderTestCase(TestCase, ABC, Generic[_TApplicationRecorder]):
211
224
  INITIAL_VERSION = 1
212
225
  EXPECT_CONTIGUOUS_NOTIFICATION_IDS = True
213
226
 
214
227
  @abstractmethod
215
- def create_recorder(self) -> ApplicationRecorder:
228
+ def create_recorder(self) -> _TApplicationRecorder:
216
229
  """"""
217
230
 
218
231
  def test_insert_select(self) -> None:
@@ -535,24 +548,12 @@ class ApplicationRecorderTestCase(TestCase, ABC):
535
548
 
536
549
  errors_happened = Event()
537
550
 
538
- counts = {}
539
- threads: dict[int, int] = {}
540
- durations: dict[int, float] = {}
541
-
542
551
  # Match this to the batch page size in postgres insert for max throughput.
543
- num_events = 500
544
-
545
- started = datetime.now()
552
+ num_events_per_job = 500
553
+ num_jobs = 60
554
+ num_workers = 4
546
555
 
547
556
  def insert_events() -> None:
548
- thread_id = get_ident()
549
- if thread_id not in threads:
550
- threads[thread_id] = len(threads)
551
- if thread_id not in counts:
552
- counts[thread_id] = 0
553
- if thread_id not in durations:
554
- durations[thread_id] = 0
555
-
556
557
  originator_id = uuid4()
557
558
  stored_events = [
558
559
  StoredEvent(
@@ -561,7 +562,7 @@ class ApplicationRecorderTestCase(TestCase, ABC):
561
562
  topic="topic",
562
563
  state=b"state",
563
564
  )
564
- for i in range(num_events)
565
+ for i in range(num_events_per_job)
565
566
  ]
566
567
 
567
568
  try:
@@ -571,26 +572,29 @@ class ApplicationRecorderTestCase(TestCase, ABC):
571
572
  errors_happened.set()
572
573
  tb = traceback.format_exc()
573
574
  print(tb)
574
- finally:
575
- ended = datetime.now()
576
- duration = (ended - started).total_seconds()
577
- counts[thread_id] += 1
578
- durations[thread_id] = duration
579
575
 
580
- num_jobs = 60
576
+ # Warm up.
577
+ with ThreadPoolExecutor(max_workers=num_workers) as executor:
578
+ futures = []
579
+ for _ in range(num_workers):
580
+ future = executor.submit(insert_events)
581
+ futures.append(future)
582
+ for future in futures:
583
+ future.result()
581
584
 
582
- with ThreadPoolExecutor(max_workers=4) as executor:
585
+ # Run.
586
+ with ThreadPoolExecutor(max_workers=num_workers) as executor:
587
+ started = datetime.now()
583
588
  futures = []
584
589
  for _ in range(num_jobs):
585
590
  future = executor.submit(insert_events)
586
- # future.add_done_callback(self.close_db_connection)
587
591
  futures.append(future)
588
592
  for future in futures:
589
593
  future.result()
590
594
 
591
595
  self.assertFalse(errors_happened.is_set(), "There were errors (see above)")
592
596
  ended = datetime.now()
593
- rate = num_jobs * num_events / (ended - started).total_seconds()
597
+ rate = num_jobs * num_events_per_job / (ended - started).total_seconds()
594
598
  print(f"Rate: {rate:.0f} inserts per second")
595
599
 
596
600
  def optional_test_insert_subscribe(self) -> None:
@@ -696,7 +700,7 @@ class ApplicationRecorderTestCase(TestCase, ABC):
696
700
  with recorder.subscribe(gt=max_notification_id2) as subscription:
697
701
 
698
702
  # Receive events from the subscription.
699
- notifications: list[Notification] = []
703
+ notifications = []
700
704
  for notification in subscription:
701
705
  notifications.append(notification)
702
706
  if len(notifications) == 1:
@@ -752,10 +756,10 @@ class ApplicationRecorderTestCase(TestCase, ABC):
752
756
 
753
757
  class TrackingRecorderTestCase(TestCase, ABC):
754
758
  @abstractmethod
755
- def create_recorder(self) -> ProcessRecorder:
759
+ def create_recorder(self) -> TrackingRecorder:
756
760
  """"""
757
761
 
758
- def test_insert_tracking(self):
762
+ def test_insert_tracking(self) -> None:
759
763
  tracking_recorder = self.create_recorder()
760
764
 
761
765
  # Construct tracking objects.
@@ -787,7 +791,7 @@ class TrackingRecorderTestCase(TestCase, ABC):
787
791
  assert tracking_recorder.has_tracking_id("upstream2", 21)
788
792
  assert not tracking_recorder.has_tracking_id("upstream2", 22)
789
793
 
790
- def test_wait(self):
794
+ def test_wait(self) -> None:
791
795
  tracking_recorder = self.create_recorder()
792
796
  tracking1 = Tracking(notification_id=21, application_name="upstream1")
793
797
  tracking_recorder.insert_tracking(tracking=tracking1)
@@ -900,10 +904,11 @@ class ProcessRecorderTestCase(TestCase, ABC):
900
904
  2,
901
905
  )
902
906
 
903
- def test_has_tracking_id(self):
907
+ def test_has_tracking_id(self) -> None:
904
908
  # Construct the recorder.
905
909
  recorder = self.create_recorder()
906
910
 
911
+ self.assertTrue(recorder.has_tracking_id("upstream_app", None))
907
912
  self.assertFalse(recorder.has_tracking_id("upstream_app", 1))
908
913
  self.assertFalse(recorder.has_tracking_id("upstream_app", 2))
909
914
  self.assertFalse(recorder.has_tracking_id("upstream_app", 3))
@@ -975,7 +980,7 @@ class ProcessRecorderTestCase(TestCase, ABC):
975
980
  class NonInterleavingNotificationIDsBaseCase(ABC, TestCase):
976
981
  insert_num = 1000
977
982
 
978
- def test(self):
983
+ def test(self) -> None:
979
984
  recorder = self.create_recorder()
980
985
 
981
986
  max_notification_id = recorder.max_notification_id()
@@ -990,7 +995,7 @@ class NonInterleavingNotificationIDsBaseCase(ABC, TestCase):
990
995
 
991
996
  errors = []
992
997
 
993
- def insert_stack(stack):
998
+ def insert_stack(stack: list[StoredEvent]) -> None:
994
999
  try:
995
1000
  race_started.wait()
996
1001
  recorder.insert_events(stack)
@@ -1036,7 +1041,7 @@ class NonInterleavingNotificationIDsBaseCase(ABC, TestCase):
1036
1041
  else:
1037
1042
  self.assertGreater(min_id_for_sequence2, max_id_for_sequence1)
1038
1043
 
1039
- def create_stack(self, originator_id):
1044
+ def create_stack(self, originator_id: UUID) -> list[StoredEvent]:
1040
1045
  return [
1041
1046
  StoredEvent(
1042
1047
  originator_id=originator_id,
@@ -1052,45 +1057,52 @@ class NonInterleavingNotificationIDsBaseCase(ABC, TestCase):
1052
1057
  pass
1053
1058
 
1054
1059
 
1055
- class InfrastructureFactoryTestCase(ABC, TestCase):
1056
- env: Environment | None = None
1060
+ _TInfrastrutureFactory = TypeVar(
1061
+ "_TInfrastrutureFactory", bound=InfrastructureFactory[Any]
1062
+ )
1063
+
1064
+
1065
+ class InfrastructureFactoryTestCase(ABC, TestCase, Generic[_TInfrastrutureFactory]):
1066
+ env: Environment
1057
1067
 
1058
1068
  @abstractmethod
1059
- def expected_factory_class(self):
1069
+ def expected_factory_class(self) -> type[_TInfrastrutureFactory]:
1060
1070
  pass
1061
1071
 
1062
1072
  @abstractmethod
1063
- def expected_aggregate_recorder_class(self):
1073
+ def expected_aggregate_recorder_class(self) -> type[AggregateRecorder]:
1064
1074
  pass
1065
1075
 
1066
1076
  @abstractmethod
1067
- def expected_application_recorder_class(self):
1077
+ def expected_application_recorder_class(self) -> type[ApplicationRecorder]:
1068
1078
  pass
1069
1079
 
1070
1080
  @abstractmethod
1071
- def expected_tracking_recorder_class(self):
1081
+ def expected_tracking_recorder_class(self) -> type[TrackingRecorder]:
1072
1082
  pass
1073
1083
 
1074
1084
  @abstractmethod
1075
- def tracking_recorder_subclass(self):
1085
+ def tracking_recorder_subclass(self) -> type[TrackingRecorder]:
1076
1086
  pass
1077
1087
 
1078
1088
  @abstractmethod
1079
- def expected_process_recorder_class(self):
1089
+ def expected_process_recorder_class(self) -> type[ProcessRecorder]:
1080
1090
  pass
1081
1091
 
1082
1092
  def setUp(self) -> None:
1083
- self.factory = InfrastructureFactory.construct(self.env)
1093
+ self.factory = cast(
1094
+ _TInfrastrutureFactory, InfrastructureFactory.construct(self.env)
1095
+ )
1084
1096
  self.assertIsInstance(self.factory, self.expected_factory_class())
1085
1097
  self.transcoder = JSONTranscoder()
1086
1098
  self.transcoder.register(UUIDAsHex())
1087
1099
  self.transcoder.register(DecimalAsStr())
1088
1100
  self.transcoder.register(DatetimeAsISO())
1089
1101
 
1090
- def tearDown(self):
1102
+ def tearDown(self) -> None:
1091
1103
  self.factory.close()
1092
1104
 
1093
- def test_createmapper(self):
1105
+ def test_createmapper(self) -> None:
1094
1106
  # Want to construct:
1095
1107
  # - application recorder
1096
1108
  # - snapshot recorder
@@ -1126,7 +1138,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1126
1138
  self.assertIsNone(mapper.cipher)
1127
1139
  self.assertIsNone(mapper.compressor)
1128
1140
 
1129
- def test_createmapper_with_compressor(self):
1141
+ def test_createmapper_with_compressor(self) -> None:
1130
1142
  # Create mapper with compressor class as topic.
1131
1143
  self.env[self.factory.COMPRESSOR_TOPIC] = get_topic(ZlibCompressor)
1132
1144
  mapper = self.factory.mapper(transcoder=self.transcoder)
@@ -1141,7 +1153,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1141
1153
  self.assertEqual(mapper.compressor, zlib)
1142
1154
  self.assertIsNone(mapper.cipher)
1143
1155
 
1144
- def test_createmapper_with_cipher(self):
1156
+ def test_createmapper_with_cipher(self) -> None:
1145
1157
  # Check cipher needs a key.
1146
1158
  self.env[self.factory.CIPHER_TOPIC] = get_topic(AESCipher)
1147
1159
 
@@ -1162,7 +1174,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1162
1174
 
1163
1175
  def test_createmapper_with_cipher_and_compressor(
1164
1176
  self,
1165
- ):
1177
+ ) -> None:
1166
1178
  # Create mapper with cipher and compressor.
1167
1179
  self.env[self.factory.COMPRESSOR_TOPIC] = get_topic(ZlibCompressor)
1168
1180
 
@@ -1175,7 +1187,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1175
1187
  self.assertIsNotNone(mapper.cipher)
1176
1188
  self.assertIsNotNone(mapper.compressor)
1177
1189
 
1178
- def test_mapper_with_wrong_cipher_key(self):
1190
+ def test_mapper_with_wrong_cipher_key(self) -> None:
1179
1191
  self.env.name = "App1"
1180
1192
  self.env[self.factory.CIPHER_TOPIC] = get_topic(AESCipher)
1181
1193
  cipher_key1 = AESCipher.create_key(16)
@@ -1205,7 +1217,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1205
1217
  with self.assertRaises(ValueError):
1206
1218
  mapper2.to_domain_event(stored_event)
1207
1219
 
1208
- def test_create_aggregate_recorder(self):
1220
+ def test_create_aggregate_recorder(self) -> None:
1209
1221
  recorder = self.factory.aggregate_recorder()
1210
1222
  self.assertEqual(type(recorder), self.expected_aggregate_recorder_class())
1211
1223
 
@@ -1216,7 +1228,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1216
1228
  recorder = self.factory.aggregate_recorder()
1217
1229
  self.assertEqual(type(recorder), self.expected_aggregate_recorder_class())
1218
1230
 
1219
- def test_create_application_recorder(self):
1231
+ def test_create_application_recorder(self) -> None:
1220
1232
  recorder = self.factory.application_recorder()
1221
1233
  self.assertEqual(type(recorder), self.expected_application_recorder_class())
1222
1234
  self.assertIsInstance(recorder, ApplicationRecorder)
@@ -1226,7 +1238,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1226
1238
  recorder = self.factory.application_recorder()
1227
1239
  self.assertEqual(type(recorder), self.expected_application_recorder_class())
1228
1240
 
1229
- def test_create_tracking_recorder(self):
1241
+ def test_create_tracking_recorder(self) -> None:
1230
1242
  recorder = self.factory.tracking_recorder()
1231
1243
  self.assertEqual(type(recorder), self.expected_tracking_recorder_class())
1232
1244
  self.assertIsInstance(recorder, TrackingRecorder)
@@ -1246,7 +1258,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1246
1258
  recorder = self.factory.tracking_recorder()
1247
1259
  self.assertEqual(type(recorder), subclass)
1248
1260
 
1249
- def test_create_process_recorder(self):
1261
+ def test_create_process_recorder(self) -> None:
1250
1262
  recorder = self.factory.process_recorder()
1251
1263
  self.assertEqual(type(recorder), self.expected_process_recorder_class())
1252
1264
  self.assertIsInstance(recorder, ProcessRecorder)
@@ -1257,7 +1269,7 @@ class InfrastructureFactoryTestCase(ABC, TestCase):
1257
1269
  self.assertEqual(type(recorder), self.expected_process_recorder_class())
1258
1270
 
1259
1271
 
1260
- def tmpfile_uris():
1272
+ def tmpfile_uris() -> Iterator[str]:
1261
1273
  tmp_files = []
1262
1274
  ram_disk_path = "/Volumes/RAM DISK/"
1263
1275
  prefix = None
@@ -1273,7 +1285,7 @@ class CustomType1:
1273
1285
  def __init__(self, value: UUID):
1274
1286
  self.value = value
1275
1287
 
1276
- def __eq__(self, other: CustomType1):
1288
+ def __eq__(self, other: object) -> bool:
1277
1289
  return type(self) is type(other) and self.__dict__ == other.__dict__
1278
1290
 
1279
1291
 
@@ -1281,39 +1293,46 @@ class CustomType2:
1281
1293
  def __init__(self, value: CustomType1):
1282
1294
  self.value = value
1283
1295
 
1284
- def __eq__(self, other: CustomType2):
1296
+ def __eq__(self, other: object) -> bool:
1285
1297
  return type(self) is type(other) and self.__dict__ == other.__dict__
1286
1298
 
1287
1299
 
1288
- class Mydict(dict):
1289
- def __repr__(self):
1300
+ _KT = TypeVar("_KT")
1301
+ _VT = TypeVar("_VT")
1302
+
1303
+
1304
+ class Mydict(dict[_KT, _VT]):
1305
+ def __repr__(self) -> str:
1290
1306
  return f"{type(self).__name__}({super().__repr__()})"
1291
1307
 
1292
- def __eq__(self, other):
1308
+ def __eq__(self, other: object) -> bool:
1293
1309
  return type(self) is type(other) and super().__eq__(other)
1294
1310
 
1295
1311
 
1296
- class MyList(list):
1297
- def __repr__(self):
1312
+ _T = TypeVar("_T")
1313
+
1314
+
1315
+ class MyList(list[_T]):
1316
+ def __repr__(self) -> str:
1298
1317
  return f"{type(self).__name__}({super().__repr__()})"
1299
1318
 
1300
- def __eq__(self, other):
1319
+ def __eq__(self, other: object) -> bool:
1301
1320
  return type(self) is type(other) and super().__eq__(other)
1302
1321
 
1303
1322
 
1304
1323
  class MyStr(str):
1305
- def __repr__(self):
1324
+ def __repr__(self) -> str:
1306
1325
  return f"{type(self).__name__}({super().__repr__()})"
1307
1326
 
1308
- def __eq__(self, other):
1327
+ def __eq__(self, other: object) -> bool:
1309
1328
  return type(self) is type(other) and super().__eq__(other)
1310
1329
 
1311
1330
 
1312
1331
  class MyInt(int):
1313
- def __repr__(self):
1332
+ def __repr__(self) -> str:
1314
1333
  return f"{type(self).__name__}({super().__repr__()})"
1315
1334
 
1316
- def __eq__(self, other):
1335
+ def __eq__(self, other: object) -> bool:
1317
1336
  return type(self) is type(other) and super().__eq__(other)
1318
1337
 
1319
1338
 
@@ -1349,10 +1368,10 @@ class TranscoderTestCase(TestCase):
1349
1368
  def setUp(self) -> None:
1350
1369
  self.transcoder = self.construct_transcoder()
1351
1370
 
1352
- def construct_transcoder(self):
1371
+ def construct_transcoder(self) -> Transcoder:
1353
1372
  raise NotImplementedError
1354
1373
 
1355
- def test_str(self):
1374
+ def test_str(self) -> None:
1356
1375
  obj = "a"
1357
1376
  data = self.transcoder.encode(obj)
1358
1377
  self.assertEqual(data, b'"a"')
@@ -1384,48 +1403,48 @@ class TranscoderTestCase(TestCase):
1384
1403
  obj, self.transcoder.decode(legacy_encoding_with_ensure_ascii_true)
1385
1404
  )
1386
1405
 
1387
- def test_dict(self):
1406
+ def test_dict(self) -> None:
1388
1407
  # Empty dict.
1389
- obj = {}
1390
- data = self.transcoder.encode(obj)
1408
+ obj1: dict[Never, Never] = {}
1409
+ data = self.transcoder.encode(obj1)
1391
1410
  self.assertEqual(data, b"{}")
1392
- self.assertEqual(obj, self.transcoder.decode(data))
1411
+ self.assertEqual(obj1, self.transcoder.decode(data))
1393
1412
 
1394
1413
  # dict with single key.
1395
- obj = {"a": 1}
1396
- data = self.transcoder.encode(obj)
1414
+ obj2 = {"a": 1}
1415
+ data = self.transcoder.encode(obj2)
1397
1416
  self.assertEqual(data, b'{"a":1}')
1398
- self.assertEqual(obj, self.transcoder.decode(data))
1417
+ self.assertEqual(obj2, self.transcoder.decode(data))
1399
1418
 
1400
1419
  # dict with many keys.
1401
- obj = {"a": 1, "b": 2}
1402
- data = self.transcoder.encode(obj)
1420
+ obj3 = {"a": 1, "b": 2}
1421
+ data = self.transcoder.encode(obj3)
1403
1422
  self.assertEqual(data, b'{"a":1,"b":2}')
1404
- self.assertEqual(obj, self.transcoder.decode(data))
1423
+ self.assertEqual(obj3, self.transcoder.decode(data))
1405
1424
 
1406
1425
  # Empty dict in dict.
1407
- obj = {"a": {}}
1408
- data = self.transcoder.encode(obj)
1426
+ obj4: dict[str, dict[Never, Never]] = {"a": {}}
1427
+ data = self.transcoder.encode(obj4)
1409
1428
  self.assertEqual(data, b'{"a":{}}')
1410
- self.assertEqual(obj, self.transcoder.decode(data))
1429
+ self.assertEqual(obj4, self.transcoder.decode(data))
1411
1430
 
1412
1431
  # Empty dicts in dict.
1413
- obj = {"a": {}, "b": {}}
1414
- data = self.transcoder.encode(obj)
1432
+ obj5: dict[str, dict[Never, Never]] = {"a": {}, "b": {}}
1433
+ data = self.transcoder.encode(obj5)
1415
1434
  self.assertEqual(data, b'{"a":{},"b":{}}')
1416
- self.assertEqual(obj, self.transcoder.decode(data))
1435
+ self.assertEqual(obj5, self.transcoder.decode(data))
1417
1436
 
1418
1437
  # Empty dict in dict in dict.
1419
- obj = {"a": {"b": {}}}
1420
- data = self.transcoder.encode(obj)
1438
+ obj6: dict[str, dict[str, dict[Never, Never]]] = {"a": {"b": {}}}
1439
+ data = self.transcoder.encode(obj6)
1421
1440
  self.assertEqual(data, b'{"a":{"b":{}}}')
1422
- self.assertEqual(obj, self.transcoder.decode(data))
1441
+ self.assertEqual(obj6, self.transcoder.decode(data))
1423
1442
 
1424
1443
  # Int in dict in dict in dict.
1425
- obj = {"a": {"b": {"c": 1}}}
1426
- data = self.transcoder.encode(obj)
1444
+ obj7 = {"a": {"b": {"c": 1}}}
1445
+ data = self.transcoder.encode(obj7)
1427
1446
  self.assertEqual(data, b'{"a":{"b":{"c":1}}}')
1428
- self.assertEqual(obj, self.transcoder.decode(data))
1447
+ self.assertEqual(obj7, self.transcoder.decode(data))
1429
1448
 
1430
1449
  # TODO: Int keys?
1431
1450
  # obj = {1: "a"}
@@ -1433,115 +1452,115 @@ class TranscoderTestCase(TestCase):
1433
1452
  # self.assertEqual(data, b'{1:{"a"}')
1434
1453
  # self.assertEqual(obj, self.transcoder.decode(data))
1435
1454
 
1436
- def test_dict_with_len_2_and__data_(self):
1455
+ def test_dict_with_len_2_and__data_(self) -> None:
1437
1456
  obj = {"_data_": 1, "something_else": 2}
1438
1457
  data = self.transcoder.encode(obj)
1439
1458
  self.assertEqual(obj, self.transcoder.decode(data))
1440
1459
 
1441
- def test_dict_with_len_2_and__type_(self):
1460
+ def test_dict_with_len_2_and__type_(self) -> None:
1442
1461
  obj = {"_type_": 1, "something_else": 2}
1443
1462
  data = self.transcoder.encode(obj)
1444
1463
  self.assertEqual(obj, self.transcoder.decode(data))
1445
1464
 
1446
- def test_dict_subclass(self):
1465
+ def test_dict_subclass(self) -> None:
1447
1466
  my_dict = Mydict({"a": 1})
1448
1467
  data = self.transcoder.encode(my_dict)
1449
1468
  self.assertEqual(b'{"_type_":"mydict","_data_":{"a":1}}', data)
1450
1469
  copy = self.transcoder.decode(data)
1451
1470
  self.assertEqual(my_dict, copy)
1452
1471
 
1453
- def test_list_subclass(self):
1472
+ def test_list_subclass(self) -> None:
1454
1473
  my_list = MyList((("a", 1),))
1455
1474
  data = self.transcoder.encode(my_list)
1456
1475
  copy = self.transcoder.decode(data)
1457
1476
  self.assertEqual(my_list, copy)
1458
1477
 
1459
- def test_str_subclass(self):
1478
+ def test_str_subclass(self) -> None:
1460
1479
  my_str = MyStr("a")
1461
1480
  data = self.transcoder.encode(my_str)
1462
1481
  copy = self.transcoder.decode(data)
1463
1482
  self.assertEqual(my_str, copy)
1464
1483
 
1465
- def test_int_subclass(self):
1484
+ def test_int_subclass(self) -> None:
1466
1485
  my_int = MyInt(3)
1467
1486
  data = self.transcoder.encode(my_int)
1468
1487
  copy = self.transcoder.decode(data)
1469
1488
  self.assertEqual(my_int, copy)
1470
1489
 
1471
- def test_tuple(self):
1490
+ def test_tuple(self) -> None:
1472
1491
  # Empty tuple.
1473
- obj = ()
1474
- data = self.transcoder.encode(obj)
1492
+ obj1 = ()
1493
+ data = self.transcoder.encode(obj1)
1475
1494
  self.assertEqual(data, b'{"_type_":"tuple_as_list","_data_":[]}')
1476
- self.assertEqual(obj, self.transcoder.decode(data))
1495
+ self.assertEqual(obj1, self.transcoder.decode(data))
1477
1496
 
1478
1497
  # Empty tuple in a tuple.
1479
- obj = ((),)
1480
- data = self.transcoder.encode(obj)
1481
- self.assertEqual(obj, self.transcoder.decode(data))
1498
+ obj2 = ((),)
1499
+ data = self.transcoder.encode(obj2)
1500
+ self.assertEqual(obj2, self.transcoder.decode(data))
1482
1501
 
1483
1502
  # Int in tuple in a tuple.
1484
- obj = ((1, 2),)
1485
- data = self.transcoder.encode(obj)
1486
- self.assertEqual(obj, self.transcoder.decode(data))
1503
+ obj3 = ((1, 2),)
1504
+ data = self.transcoder.encode(obj3)
1505
+ self.assertEqual(obj3, self.transcoder.decode(data))
1487
1506
 
1488
1507
  # Str in tuple in a tuple.
1489
- obj = (("a", "b"),)
1490
- data = self.transcoder.encode(obj)
1491
- self.assertEqual(obj, self.transcoder.decode(data))
1508
+ obj4 = (("a", "b"),)
1509
+ data = self.transcoder.encode(obj4)
1510
+ self.assertEqual(obj4, self.transcoder.decode(data))
1492
1511
 
1493
1512
  # Int and str in tuple in a tuple.
1494
- obj = ((1, "a"),)
1495
- data = self.transcoder.encode(obj)
1496
- self.assertEqual(obj, self.transcoder.decode(data))
1513
+ obj5 = ((1, "a"),)
1514
+ data = self.transcoder.encode(obj5)
1515
+ self.assertEqual(obj5, self.transcoder.decode(data))
1497
1516
 
1498
- def test_list(self):
1517
+ def test_list(self) -> None:
1499
1518
  # Empty list.
1500
- obj = []
1501
- data = self.transcoder.encode(obj)
1502
- self.assertEqual(obj, self.transcoder.decode(data))
1519
+ obj1: list[Never] = []
1520
+ data = self.transcoder.encode(obj1)
1521
+ self.assertEqual(obj1, self.transcoder.decode(data))
1503
1522
 
1504
1523
  # Empty list in a list.
1505
- obj = [[]]
1506
- data = self.transcoder.encode(obj)
1507
- self.assertEqual(obj, self.transcoder.decode(data))
1524
+ obj2: list[list[Never]] = [[]]
1525
+ data = self.transcoder.encode(obj2)
1526
+ self.assertEqual(obj2, self.transcoder.decode(data))
1508
1527
 
1509
1528
  # Int in list in a list.
1510
- obj = [[1, 2]]
1511
- data = self.transcoder.encode(obj)
1512
- self.assertEqual(obj, self.transcoder.decode(data))
1529
+ obj3 = [[1, 2]]
1530
+ data = self.transcoder.encode(obj3)
1531
+ self.assertEqual(obj3, self.transcoder.decode(data))
1513
1532
 
1514
1533
  # Str in list in a list.
1515
- obj = [["a", "b"]]
1516
- data = self.transcoder.encode(obj)
1517
- self.assertEqual(obj, self.transcoder.decode(data))
1534
+ obj4 = [["a", "b"]]
1535
+ data = self.transcoder.encode(obj4)
1536
+ self.assertEqual(obj4, self.transcoder.decode(data))
1518
1537
 
1519
1538
  # Int and str in list in a list.
1520
- obj = [[1, "a"]]
1521
- data = self.transcoder.encode(obj)
1522
- self.assertEqual(obj, self.transcoder.decode(data))
1539
+ obj5 = [[1, "a"]]
1540
+ data = self.transcoder.encode(obj5)
1541
+ self.assertEqual(obj5, self.transcoder.decode(data))
1523
1542
 
1524
- def test_mixed(self):
1525
- obj = [(1, "a"), {"b": 2}]
1526
- data = self.transcoder.encode(obj)
1527
- self.assertEqual(obj, self.transcoder.decode(data))
1543
+ def test_mixed(self) -> None:
1544
+ obj1 = [(1, "a"), {"b": 2}]
1545
+ data = self.transcoder.encode(obj1)
1546
+ self.assertEqual(obj1, self.transcoder.decode(data))
1528
1547
 
1529
- obj = ([1, "a"], {"b": 2})
1530
- data = self.transcoder.encode(obj)
1531
- self.assertEqual(obj, self.transcoder.decode(data))
1548
+ obj2 = ([1, "a"], {"b": 2})
1549
+ data = self.transcoder.encode(obj2)
1550
+ self.assertEqual(obj2, self.transcoder.decode(data))
1532
1551
 
1533
- obj = {"a": (1, 2), "b": [3, 4]}
1534
- data = self.transcoder.encode(obj)
1535
- self.assertEqual(obj, self.transcoder.decode(data))
1552
+ obj3 = {"a": (1, 2), "b": [3, 4]}
1553
+ data = self.transcoder.encode(obj3)
1554
+ self.assertEqual(obj3, self.transcoder.decode(data))
1536
1555
 
1537
- def test_custom_type_in_dict(self):
1556
+ def test_custom_type_in_dict(self) -> None:
1538
1557
  # Int in dict in dict in dict.
1539
1558
  obj = {"a": CustomType2(CustomType1(UUID("b2723fe2c01a40d2875ea3aac6a09ff5")))}
1540
1559
  data = self.transcoder.encode(obj)
1541
1560
  decoded_obj = self.transcoder.decode(data)
1542
1561
  self.assertEqual(obj, decoded_obj)
1543
1562
 
1544
- def test_nested_custom_type(self):
1563
+ def test_nested_custom_type(self) -> None:
1545
1564
  obj = CustomType2(CustomType1(UUID("b2723fe2c01a40d2875ea3aac6a09ff5")))
1546
1565
  data = self.transcoder.encode(obj)
1547
1566
  expect = (
@@ -1557,7 +1576,7 @@ class TranscoderTestCase(TestCase):
1557
1576
  self.assertIsInstance(copy.value.value, UUID)
1558
1577
  self.assertEqual(copy.value.value, obj.value.value)
1559
1578
 
1560
- def test_custom_type_error(self):
1579
+ def test_custom_type_error(self) -> None:
1561
1580
  # Expect a TypeError when encoding because transcoding not registered.
1562
1581
  with self.assertRaises(TypeError) as cm:
1563
1582
  self.transcoder.encode(MyClass())