py-app-runner 0.7.2__tar.gz → 0.7.3__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 (141) hide show
  1. py_app_runner-0.7.3/.version +1 -0
  2. {py_app_runner-0.7.2/src/py_app_runner.egg-info → py_app_runner-0.7.3}/PKG-INFO +1 -1
  3. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/audit.py +13 -2
  4. {py_app_runner-0.7.2 → py_app_runner-0.7.3/src/py_app_runner.egg-info}/PKG-INFO +1 -1
  5. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_audit_store.py +18 -0
  6. py_app_runner-0.7.2/.version +0 -1
  7. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/LICENSE +0 -0
  8. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/MANIFEST.in +0 -0
  9. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/README.md +0 -0
  10. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/pyproject.toml +0 -0
  11. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/setup.cfg +0 -0
  12. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/__init__.py +0 -0
  13. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/__init__.py +0 -0
  14. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/_service.py +0 -0
  15. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/_service_args.py +0 -0
  16. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/abilities.py +0 -0
  17. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/commands.py +0 -0
  18. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/files/install.pgsql.sql +0 -0
  19. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/keys.py +0 -0
  20. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/api_keys/model.py +0 -0
  21. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/__init__.py +0 -0
  22. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/_service.py +0 -0
  23. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/_service_args.py +0 -0
  24. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/commands.py +0 -0
  25. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/diff.py +0 -0
  26. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/errors.py +0 -0
  27. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/event.py +0 -0
  28. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/files/install.pgsql.sql +0 -0
  29. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/audit/store.py +0 -0
  30. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/__init__.py +0 -0
  31. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/_service.py +0 -0
  32. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/_service_args.py +0 -0
  33. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/api.py +0 -0
  34. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/encoders/__init__.py +0 -0
  35. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/encoders/base.py +0 -0
  36. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/encoders/json_encoder.py +0 -0
  37. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/encoders/msgpack_encoder.py +0 -0
  38. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/web_app.py +0 -0
  39. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/bridge/websocket.py +0 -0
  40. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/colors.py +0 -0
  41. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/config.py +0 -0
  42. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/__init__.py +0 -0
  43. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/_service.py +0 -0
  44. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/_service_args.py +0 -0
  45. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/commands.py +0 -0
  46. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/execute.py +0 -0
  47. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/cron/schedule.py +0 -0
  48. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/__init__.py +0 -0
  49. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/_service.py +0 -0
  50. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/_service_args.py +0 -0
  51. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/commands.py +0 -0
  52. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/envelope.py +0 -0
  53. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/errors.py +0 -0
  54. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/fields.py +0 -0
  55. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/crypto/passwords.py +0 -0
  56. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/db_pools.py +0 -0
  57. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/file_lock.py +0 -0
  58. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/http_exception.py +0 -0
  59. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/logger_handlers.py +0 -0
  60. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/__init__.py +0 -0
  61. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/_service.py +0 -0
  62. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/_service_args.py +0 -0
  63. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/commands.py +0 -0
  64. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/discovery.py +0 -0
  65. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/states.py +0 -0
  66. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/tracker.py +0 -0
  67. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/migrations/tracker_sqlite.py +0 -0
  68. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/py.typed +0 -0
  69. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/pybridge.py +0 -0
  70. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/__init__.py +0 -0
  71. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/_service.py +0 -0
  72. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/_service_args.py +0 -0
  73. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/commands.py +0 -0
  74. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/driver_pg.py +0 -0
  75. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/driver_redis.py +0 -0
  76. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/files/install.pgsql.sql +0 -0
  77. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/handler.py +0 -0
  78. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/interface.py +0 -0
  79. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/job.py +0 -0
  80. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/queue/worker.py +0 -0
  81. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/registry.py +0 -0
  82. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/__init__.py +0 -0
  83. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/auth_service.py +0 -0
  84. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/client_ip.py +0 -0
  85. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/decorators.py +0 -0
  86. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/handlers.py +0 -0
  87. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/request_handler/pagination.py +0 -0
  88. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/return_model.py +0 -0
  89. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/runner.py +0 -0
  90. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/throttle/__init__.py +0 -0
  91. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/throttle/throttle.py +0 -0
  92. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/tick_service.py +0 -0
  93. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/timer.py +0 -0
  94. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/utils.py +0 -0
  95. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/wbcm/__init__.py +0 -0
  96. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/wbcm/device_connections.py +0 -0
  97. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/wbcm/factory.py +0 -0
  98. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/wbcm/wb_connection_manager.py +0 -0
  99. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner/wbcm/ws_interface.py +0 -0
  100. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner.egg-info/SOURCES.txt +0 -0
  101. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner.egg-info/dependency_links.txt +0 -0
  102. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner.egg-info/requires.txt +0 -0
  103. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/src/py_app_runner.egg-info/top_level.txt +0 -0
  104. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_api_handler.py +0 -0
  105. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_api_key_bridge.py +0 -0
  106. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_api_key_cli.py +0 -0
  107. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_api_key_helpers.py +0 -0
  108. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_api_keys.py +0 -0
  109. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_audit_diff.py +0 -0
  110. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_bridge_backends.py +0 -0
  111. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_config.py +0 -0
  112. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_cron_execute.py +0 -0
  113. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_cron_schedule.py +0 -0
  114. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_cron_service.py +0 -0
  115. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_crypto_commands.py +0 -0
  116. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_crypto_envelope.py +0 -0
  117. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_crypto_fields.py +0 -0
  118. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_crypto_passwords.py +0 -0
  119. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_decorators.py +0 -0
  120. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_decorators_sqlite.py +0 -0
  121. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_error_envelope.py +0 -0
  122. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_example.py +0 -0
  123. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_logger_handlers.py +0 -0
  124. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_commands.py +0 -0
  125. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_discovery.py +0 -0
  126. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_pg_harness.py +0 -0
  127. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_service.py +0 -0
  128. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_sqlite.py +0 -0
  129. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_states.py +0 -0
  130. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_migrations_tracker.py +0 -0
  131. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_optional_extras.py +0 -0
  132. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_pybridge.py +0 -0
  133. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_queue_contract.py +0 -0
  134. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_queue_driver.py +0 -0
  135. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_queue_driver_redis.py +0 -0
  136. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_queue_worker.py +0 -0
  137. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_throttle.py +0 -0
  138. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_utils.py +0 -0
  139. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_wbcm.py +0 -0
  140. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_websocket_auth.py +0 -0
  141. {py_app_runner-0.7.2 → py_app_runner-0.7.3}/tests/test_websocket_messages.py +0 -0
@@ -0,0 +1 @@
1
+ 0.7.3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py_app_runner
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: Async service framework: Tornado HTTP/WS bridge, service loader, Redis WS connection manager
5
5
  Author-email: Gints Murans <gm@gm.lv>
6
6
  License-Expression: MIT
@@ -13,6 +13,7 @@ without hand-written before-fetches at every call site.
13
13
  """
14
14
 
15
15
  import logging
16
+ from collections.abc import Mapping
16
17
  from dataclasses import replace
17
18
  from typing import Any
18
19
 
@@ -190,7 +191,7 @@ class Audit:
190
191
 
191
192
  await cur.execute(statement, tuple(data[c] for c in columns))
192
193
  returned = await cur.fetchone()
193
- new_id = returned[0] if returned else None
194
+ new_id = _as_dict([self.id_key], returned)[self.id_key] if returned else None
194
195
 
195
196
  _, new_values = diff.between(None, data)
196
197
 
@@ -329,7 +330,7 @@ class Audit:
329
330
  return []
330
331
 
331
332
  names = [d.name for d in cur.description]
332
- return [dict(zip(names, row, strict=True)) for row in await cur.fetchall()]
333
+ return [_as_dict(names, row) for row in await cur.fetchall()]
333
334
 
334
335
  def _row_id(self, row: dict[str, Any]) -> str:
335
336
  value = row.get(self.id_key)
@@ -351,6 +352,16 @@ class Audit:
351
352
  )
352
353
 
353
354
 
355
+ def _as_dict(names: list[str], row: Any) -> dict[str, Any]:
356
+ """The caller's cursor decides the row shape: a sequence by default, a mapping under
357
+ psycopg's `dict_row`."""
358
+
359
+ if isinstance(row, Mapping):
360
+ return dict(row)
361
+
362
+ return dict(zip(names, row, strict=True))
363
+
364
+
354
365
  def _table_key(table: str) -> TableKey:
355
366
  schema, _, name = table.lower().rpartition(".")
356
367
  return (schema or None, name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py_app_runner
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: Async service framework: Tornado HTTP/WS bridge, service loader, Redis WS connection manager
5
5
  Author-email: Gints Murans <gm@gm.lv>
6
6
  License-Expression: MIT
@@ -5,6 +5,7 @@ import pathlib
5
5
  import psycopg
6
6
  import pytest
7
7
  import pytest_asyncio
8
+ from psycopg.rows import dict_row
8
9
 
9
10
  from py_app_runner.audit import Actor, Audit, AuditError, AuditEvent, request_context
10
11
  from py_app_runner.audit.commands import cmd_install, cmd_prune
@@ -75,6 +76,23 @@ class TestInsert:
75
76
  assert (await trail(conn))[0]["entity_id"] == str(new_id)
76
77
 
77
78
 
79
+ class TestDictRowCursor:
80
+ async def test_a_dict_row_cursor_records_the_same_trail(self, conn):
81
+ audit = Audit()
82
+
83
+ async with conn.cursor(row_factory=dict_row) as cur:
84
+ new_id = await audit.insert(cur, "people", {"name": "Anna", "status": "new"})
85
+ await audit.update(cur, "people", {"status": "active"}, {"id": new_id})
86
+ await audit.delete(cur, "people", {"id": new_id})
87
+
88
+ created, updated, deleted = await trail(conn)
89
+ assert isinstance(new_id, int)
90
+ assert {row["entity_id"] for row in (created, updated, deleted)} == {str(new_id)}
91
+ assert updated["old_values"] == {"status": "new"}
92
+ assert updated["new_values"] == {"status": "active"}
93
+ assert deleted["old_values"]["name"] == "Anna"
94
+
95
+
78
96
  class TestUpdate:
79
97
  async def test_records_the_before_values_without_a_hand_written_fetch(self, conn):
80
98
  audit = Audit()
@@ -1 +0,0 @@
1
- 0.7.2
File without changes
File without changes
File without changes
File without changes