vortexpy 6.1.1__tar.gz → 6.2.0__tar.gz

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.
Files changed (160) hide show
  1. vortexpy-6.2.0/LICENSE +22 -0
  2. {vortexpy-6.1.1 → vortexpy-6.2.0}/PKG-INFO +1 -1
  3. {vortexpy-6.1.1 → vortexpy-6.2.0}/pyproject.toml +1 -1
  4. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/Tuple.py +25 -0
  5. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleBson.py +7 -25
  6. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleBson_test.py +27 -0
  7. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/__init__.py +1 -1
  8. vortexpy-6.2.0/vortex/handler/TupleDataOfflineObserverService.py +743 -0
  9. vortexpy-6.2.0/vortex/handler/TupleDataOfflineObserverService_test.py +567 -0
  10. vortexpy-6.2.0/vortex/handler/TupleDataSecureOfflineObserverService.py +146 -0
  11. vortexpy-6.2.0/vortex/handler/TupleDataSecureOfflineObserverService_test.py +314 -0
  12. vortexpy-6.2.0/vortex/storage/TupleOfflineStorageNameService.py +20 -0
  13. vortexpy-6.2.0/vortex/storage/TupleOfflineStorageService.py +112 -0
  14. vortexpy-6.2.0/vortex/storage/TupleStorageServiceABC.py +179 -0
  15. vortexpy-6.2.0/vortex/storage/TupleStorageSqliteService.py +307 -0
  16. vortexpy-6.2.0/vortex/storage/TupleStorageSqliteService_test.py +255 -0
  17. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/PKG-INFO +1 -1
  18. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/SOURCES.txt +10 -0
  19. {vortexpy-6.1.1 → vortexpy-6.2.0}/README.md +0 -0
  20. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/TwistedDeferredTimeout.py +0 -0
  21. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/__init__.py +0 -0
  22. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_http_upgraded_websocket_ping_client.py +0 -0
  23. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_http_upgraded_websocket_ping_server.py +0 -0
  24. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_http_upgraded_websocket_rpc_test_client.py +0 -0
  25. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_http_upgraded_websocket_rpc_test_server.py +0 -0
  26. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_websocket_rpc_test_client.py +0 -0
  27. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/run_websocket_rpc_test_server.py +0 -0
  28. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/setup_example_logging.py +0 -0
  29. {vortexpy-6.1.1 → vortexpy-6.2.0}/example/store_and_load_json.py +0 -0
  30. {vortexpy-6.1.1 → vortexpy-6.2.0}/setup.cfg +0 -0
  31. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/DataWrapTuple.py +0 -0
  32. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/DeferUtil.py +0 -0
  33. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/DeferUtil_test.py +0 -0
  34. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/Jsonable.py +0 -0
  35. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/MtlsAuthorizedClientRegistry.py +0 -0
  36. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/MtlsAuthorizedClientRegistry_test.py +0 -0
  37. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/MtlsServerSslOptions.py +0 -0
  38. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/Payload.py +0 -0
  39. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadEndpoint.py +0 -0
  40. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadEndpointTest.py +0 -0
  41. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadEnvelope.py +0 -0
  42. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadFilterKeys.py +0 -0
  43. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadIO.py +0 -0
  44. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadPriority.py +0 -0
  45. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadResponse.py +0 -0
  46. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadResponseTest.py +0 -0
  47. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadResponse_test.py +0 -0
  48. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PayloadTest.py +0 -0
  49. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/PerformTestActionTuple.py +0 -0
  50. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/SerialiseUtil.py +0 -0
  51. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/SerialiseUtil_test.py +0 -0
  52. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TestTuple.py +0 -0
  53. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleAction.py +0 -0
  54. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleDataForTest.py +0 -0
  55. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleDocumentConverter.py +0 -0
  56. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TuplePerfTest.py +0 -0
  57. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TuplePolymorphicTupleTypeFieldArgTest.py +0 -0
  58. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleRestful.py +0 -0
  59. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleRestful_test.py +0 -0
  60. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleSelector.py +0 -0
  61. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/TupleTest.py +0 -0
  62. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexABC.py +0 -0
  63. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexAccessControlContextABC.py +0 -0
  64. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexAuthenticatorABC.py +0 -0
  65. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexClientHttp.py +0 -0
  66. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexClientHttpTest.py +0 -0
  67. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexClientTcp.py +0 -0
  68. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexClientWebsocketFactory.py +0 -0
  69. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexConnectionABC.py +0 -0
  70. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexEndpointPermission.py +0 -0
  71. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexFactory.py +0 -0
  72. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexFactory_test.py +0 -0
  73. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexPayloadProtocol.py +0 -0
  74. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexPermission.py +0 -0
  75. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexPermissionError.py +0 -0
  76. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServer.py +0 -0
  77. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerConnection.py +0 -0
  78. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerConnection_test.py +0 -0
  79. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerHttpResource.py +0 -0
  80. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerTcp.py +0 -0
  81. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerTcp_test.py +0 -0
  82. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerWebsocket.py +0 -0
  83. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServerWebsocket_test.py +0 -0
  84. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexServer_test.py +0 -0
  85. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexSession.py +0 -0
  86. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexSession_test.py +0 -0
  87. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexTcpMemoryLeakPayloadTest.py +0 -0
  88. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexTcpMemoryLeakRawTest.py +0 -0
  89. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexTest.py +0 -0
  90. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexUserDetailsABC.py +0 -0
  91. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexUtil.py +0 -0
  92. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexWritePushProducer.py +0 -0
  93. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/VortexWritePushProducer_test.py +0 -0
  94. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLiveLockManager.py +0 -0
  95. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLiveLockManager_test.py +0 -0
  96. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLoader.py +0 -0
  97. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLoaderDelegate.py +0 -0
  98. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLoaderTupleABC.py +0 -0
  99. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/TupleDataLoaderTuples.py +0 -0
  100. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/data_loader/__init__.py +0 -0
  101. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/event_bus/TupleChangeEventABC.py +0 -0
  102. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/event_bus/TupleChangeEventBus.py +0 -0
  103. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/event_bus/TupleChangeEventBusObserverABC.py +0 -0
  104. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/event_bus/__init__.py +0 -0
  105. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionProcessor.py +0 -0
  106. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionProcessorProxy.py +0 -0
  107. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionProcessorTestHandler.py +0 -0
  108. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionProcessor_shutdown_test.py +0 -0
  109. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionProcessor_test.py +0 -0
  110. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionPushOffline.py +0 -0
  111. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleActionPushOffline_test.py +0 -0
  112. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataAccessGranterABC.py +0 -0
  113. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataActionClient.py +0 -0
  114. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataActionClient_test.py +0 -0
  115. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableCache.py +0 -0
  116. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableCache_test.py +0 -0
  117. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableHandler.py +0 -0
  118. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableHandler_test.py +0 -0
  119. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableProxyHandler.py +0 -0
  120. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableProxyHandler_test.py +0 -0
  121. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObservableTestHandler.py +0 -0
  122. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataObserverClient.py +0 -0
  123. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/TupleDataProviderABC.py +0 -0
  124. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/VortexJSTupleLoaderTestHandler.py +0 -0
  125. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/handler/__init__.py +0 -0
  126. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/mypy_plugin.py +0 -0
  127. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/payload_many_tuples_benchmark_test.py +0 -0
  128. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/py.typed +0 -0
  129. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/GzippedDataHttpClient.py +0 -0
  130. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/GzippedDataHttpClientTest.py +0 -0
  131. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/GzippedPayloadHttpClient.py +0 -0
  132. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/RestfulHttpClient.py +0 -0
  133. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/RestfulResource.py +0 -0
  134. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/__init__.py +0 -0
  135. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/restful_http_client_test.py +0 -0
  136. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/restful/restful_resource_test.py +0 -0
  137. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/rpc/RPC.py +0 -0
  138. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/rpc/RPCTest.py +0 -0
  139. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/rpc/RPC_test.py +0 -0
  140. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/rpc/__init__.py +0 -0
  141. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/sqla_orm/OrmCrudHandler.py +0 -0
  142. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/sqla_orm/TupleProviderForDb.py +0 -0
  143. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/sqla_orm/VortexTupleJson.py +0 -0
  144. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/sqla_orm/__init__.py +0 -0
  145. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/storage/TupleActionStorageSqlite.py +0 -0
  146. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/storage/TupleStorageSqlite.py +0 -0
  147. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/storage/__init__.py +0 -0
  148. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/__init__.py +0 -0
  149. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/constants.py +0 -0
  150. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/json_schema_node_tuple.py +0 -0
  151. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/tuple_json_schema_builder.py +0 -0
  152. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/tuple_json_schema_test.py +0 -0
  153. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_json_schema/tuple_json_schema_test_tuples.py +0 -0
  154. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/tuple_test_fixtures.py +0 -0
  155. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/twisted_runtime_metrics.py +0 -0
  156. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortex/twisted_runtime_metrics_test.py +0 -0
  157. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/dependency_links.txt +0 -0
  158. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/entry_points.txt +0 -0
  159. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/requires.txt +0 -0
  160. {vortexpy-6.1.1 → vortexpy-6.2.0}/vortexpy.egg-info/top_level.txt +0 -0
vortexpy-6.2.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016-2026 Flying Ion Pty Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vortexpy
3
- Version: 6.1.1
3
+ Version: 6.2.0
4
4
  Summary: Flying Ion's observable, routable, data serialisation and transport code.
5
5
  Author-email: Flying Ion Pty Ltd <contact@flyingion.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vortexpy"
7
- version = "6.1.1"
7
+ version = "6.2.0"
8
8
  license = {text = "MIT"}
9
9
  authors = [{name = "Flying Ion Pty Ltd", email = "contact@flyingion.com"}]
10
10
  description = "Flying Ion's observable, routable, data serialisation and transport code."
@@ -29,6 +29,9 @@ from .SerialiseUtil import ISO8601
29
29
  from .SerialiseUtil import T_RAPUI_TUPLE
30
30
  from .SerialiseUtil import WKBElement
31
31
  from .SerialiseUtil import convertFromWkbElement
32
+ from .SerialiseUtil import datetimeToBson
33
+ from .SerialiseUtil import datetimeToBsonMicroseconds
34
+ from .SerialiseUtil import requireAwareDatetime
32
35
 
33
36
  logger = logging.getLogger(__name__)
34
37
 
@@ -319,6 +322,28 @@ class TupleField:
319
322
  self.jsonExclude = jsonExclude
320
323
  self.bsonDatetimeFormat = bsonDatetimeFormat
321
324
 
325
+ def toBson(self, value: Any) -> Any:
326
+ """Convert a datetime to this field's BSON storage format.
327
+
328
+ Non-datetime values pass through unchanged, so every Mongo
329
+ filter value can be wrapped uniformly. Naive datetimes raise
330
+ ``TypeError``.
331
+ """
332
+ if not isinstance(value, datetime):
333
+ return value
334
+ aware = requireAwareDatetime(value)
335
+ if self.bsonDatetimeFormat is None:
336
+ return datetimeToBson(aware)
337
+ if self.bsonDatetimeFormat is BsonDatetimeFormatE.standardMsIntEpoch:
338
+ return datetimeToBson(aware)
339
+ if self.bsonDatetimeFormat is BsonDatetimeFormatE.standardUsIntEpoch:
340
+ return datetimeToBsonMicroseconds(aware)
341
+ if self.bsonDatetimeFormat is BsonDatetimeFormatE.standardMsBsonDate:
342
+ return aware
343
+ raise NotImplementedError(
344
+ f"Unsupported BsonDatetimeFormatE {self.bsonDatetimeFormat!r}"
345
+ )
346
+
322
347
 
323
348
  class PolymorphicTupleTypeFieldArg:
324
349
  def __init__(self, fieldName: str):
@@ -43,7 +43,6 @@ from .SerialiseUtil import WKBElement
43
43
  from .SerialiseUtil import convertFromWkbElement
44
44
  from .SerialiseUtil import datetimeFromBson
45
45
  from .SerialiseUtil import datetimeToBson
46
- from .SerialiseUtil import datetimeToBsonMicroseconds
47
46
  from .SerialiseUtil import requireAwareDatetime
48
47
  from .Tuple import BsonDatetimeFormatE
49
48
  from .Tuple import TupleField
@@ -65,24 +64,6 @@ class TupleBsonConverter(TupleDocumentConverterBase):
65
64
  return tupleField.bsonDatetimeFormat
66
65
  return None
67
66
 
68
- @classmethod
69
- def _utilDatetimeToBsonStorageValue(
70
- cls,
71
- value: datetime,
72
- bsonDatetimeFormat: BsonDatetimeFormatE | None,
73
- ) -> datetime | int:
74
- if bsonDatetimeFormat is None:
75
- return datetimeToBson(value)
76
- if bsonDatetimeFormat is BsonDatetimeFormatE.standardMsIntEpoch:
77
- return datetimeToBson(value)
78
- if bsonDatetimeFormat is BsonDatetimeFormatE.standardUsIntEpoch:
79
- return datetimeToBsonMicroseconds(value)
80
- if bsonDatetimeFormat is BsonDatetimeFormatE.standardMsBsonDate:
81
- return requireAwareDatetime(value)
82
- raise NotImplementedError(
83
- f"Unsupported BsonDatetimeFormatE {bsonDatetimeFormat!r}"
84
- )
85
-
86
67
  @classmethod
87
68
  def _utilCoerceIntOrFloatEpochToDatetime(
88
69
  cls,
@@ -145,7 +126,7 @@ class TupleBsonConverter(TupleDocumentConverterBase):
145
126
 
146
127
  def convert(
147
128
  value: Any,
148
- bsonDatetimeFormat: BsonDatetimeFormatE | None = None,
129
+ tupleField: TupleField | None = None,
149
130
  ) -> Any:
150
131
  if isinstance(value, list):
151
132
  return [convert(item) for item in value]
@@ -165,17 +146,18 @@ class TupleBsonConverter(TupleDocumentConverterBase):
165
146
  return None
166
147
 
167
148
  if isinstance(value, datetime):
168
- return cls._utilDatetimeToBsonStorageValue(value, bsonDatetimeFormat)
149
+ if tupleField is None:
150
+ return datetimeToBson(value)
151
+ return tupleField.toBson(value)
169
152
 
170
153
  return value
171
154
 
172
155
  for shortName, normalName in tuple_.__shortFieldNamesMap__.items():
173
156
  tupleField = getattr(type(tuple_), normalName, None)
174
- fieldFormat: BsonDatetimeFormatE | None = None
175
- if isinstance(tupleField, TupleField):
176
- fieldFormat = tupleField.bsonDatetimeFormat
157
+ if not isinstance(tupleField, TupleField):
158
+ tupleField = None
177
159
 
178
- value = convert(getattr(tuple_, normalName), fieldFormat)
160
+ value = convert(getattr(tuple_, normalName), tupleField)
179
161
  if value is None and not includeNones:
180
162
  continue
181
163
  if value is False and not includeFalse:
@@ -250,6 +250,33 @@ class TupleBsonTest(unittest.TestCase):
250
250
  )
251
251
  self.assertEqual(deserialisedTuple.at, aware)
252
252
 
253
+ def testTupleFieldToBsonConvertsDatetimePerFormat(self) -> None:
254
+ aware = datetime(2020, 1, 2, 3, 4, 5, 678000, tzinfo=UTC)
255
+ self.assertEqual(
256
+ BsonDatetimeFormatTestTuple.defaultMsDate.toBson(aware),
257
+ datetimeToBson(aware),
258
+ )
259
+ self.assertEqual(
260
+ BsonDatetimeFormatTestTuple.microsecondDate.toBson(aware),
261
+ datetimeToBsonMicroseconds(aware),
262
+ )
263
+ self.assertEqual(
264
+ BsonDatetimeFormatTestTuple.bsonDateField.toBson(aware),
265
+ aware,
266
+ )
267
+
268
+ def testTupleFieldToBsonPassesThroughNonDatetimeValues(self) -> None:
269
+ field = BsonDatetimeFormatTestTuple.defaultMsDate
270
+ self.assertEqual(field.toBson("2026-10-23"), "2026-10-23")
271
+ self.assertEqual(field.toBson(1577934245678), 1577934245678)
272
+ self.assertIs(field.toBson(True), True)
273
+ self.assertIsNone(field.toBson(None))
274
+
275
+ def testTupleFieldToBsonRejectsNaiveDatetime(self) -> None:
276
+ naive = datetime(2020, 1, 2, 3, 4, 5, 678000)
277
+ with self.assertRaises(TypeError):
278
+ BsonDatetimeFormatTestTuple.defaultMsDate.toBson(naive)
279
+
253
280
 
254
281
  class TupleBsonCollectingTest(unittest.TestCase):
255
282
  def testSingleBadScalarCollectsErrorAndPopulatesOtherFields(self) -> None:
@@ -6,4 +6,4 @@
6
6
  # Website : https://flyingion.com
7
7
  # Support : contact@flyingion.com
8
8
 
9
- __version__ = '6.1.1'
9
+ __version__ = '6.2.0'