simple-module-settings 0.0.38__tar.gz → 0.0.39__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 (122) hide show
  1. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/PKG-INFO +5 -5
  2. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/package.json +1 -1
  3. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/pyproject.toml +5 -5
  4. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_listing.py +2 -1
  5. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_managed_keys.py +2 -1
  6. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_unique_write.py +3 -1
  7. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/deps.py +2 -1
  8. simple_module_settings-0.0.39/settings/exceptions.py +5 -0
  9. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/service.py +4 -3
  10. simple_module_settings-0.0.39/tests/test_settings_domain_errors.py +10 -0
  11. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/.gitignore +0 -0
  12. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/LICENSE +0 -0
  13. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/README.md +0 -0
  14. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/__init__.py +0 -0
  15. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_announce.py +0 -0
  16. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_field_meta.py +0 -0
  17. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_module_settings.py +0 -0
  18. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_module_settings_props.py +0 -0
  19. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_row_masking.py +0 -0
  20. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/_secrets.py +0 -0
  21. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/browse_query.py +0 -0
  22. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/cli.py +0 -0
  23. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/constants.py +0 -0
  24. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/__init__.py +0 -0
  25. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/accessor.py +0 -0
  26. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/events.py +0 -0
  27. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/invalidation.py +0 -0
  28. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/registry.py +0 -0
  29. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/contracts/schemas.py +0 -0
  30. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/__init__.py +0 -0
  31. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/_create_form.py +0 -0
  32. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/api.py +0 -0
  33. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/module_api.py +0 -0
  34. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/tenant_api.py +0 -0
  35. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/endpoints/views.py +0 -0
  36. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/env_vars.py +0 -0
  37. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/errors.py +0 -0
  38. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/hydrate.py +0 -0
  39. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/known_keys.py +0 -0
  40. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/locales/de.json +0 -0
  41. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/locales/en.json +0 -0
  42. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/models.py +0 -0
  43. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/module.py +0 -0
  44. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/module_registry.py +0 -0
  45. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/Browse.tsx +0 -0
  46. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/Create.tsx +0 -0
  47. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/Edit.tsx +0 -0
  48. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/ModulesEdit.tsx +0 -0
  49. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/api.generated.ts +0 -0
  50. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/api.ts +0 -0
  51. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/FieldInput.tsx +0 -0
  52. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/FieldSource.tsx +0 -0
  53. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/JsonInput.tsx +0 -0
  54. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/KeyField.tsx +0 -0
  55. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/ModuleFieldRow.tsx +0 -0
  56. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/ModuleForm.tsx +0 -0
  57. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/ResolvedValue.tsx +0 -0
  58. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/ScopeTabs.tsx +0 -0
  59. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/StoreCards.tsx +0 -0
  60. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/StoreTable.tsx +0 -0
  61. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/TestConnectionButton.tsx +0 -0
  62. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/ValueInput.tsx +0 -0
  63. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/last-test.ts +0 -0
  64. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/validation-errors.test.ts +0 -0
  65. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/components/validation-errors.ts +0 -0
  66. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/routes.ts +0 -0
  67. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/pages/types.ts +0 -0
  68. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/py.typed +0 -0
  69. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/registration.py +0 -0
  70. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/reload.py +0 -0
  71. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/services.py +0 -0
  72. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/settings.py +0 -0
  73. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/store.py +0 -0
  74. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/tenant_scope.py +0 -0
  75. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/settings/tenant_view.py +0 -0
  76. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_clear_route_per_scope.py +0 -0
  77. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_cli_import.py +0 -0
  78. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_concurrent_overrides.py +0 -0
  79. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_duplicate_and_race.py +0 -0
  80. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_env_pinned.py +0 -0
  81. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_hydrate.py +0 -0
  82. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_hydrate_related_fields.py +0 -0
  83. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_known_keys_meta.py +0 -0
  84. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_lenient_related_fields_validators.py +0 -0
  85. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_api.py +0 -0
  86. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_api_json_fields.py +0 -0
  87. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_registry.py +0 -0
  88. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_settings.py +0 -0
  89. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_settings_render.py +0 -0
  90. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_module_settings_serialize.py +0 -0
  91. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_registration.py +0 -0
  92. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_reload.py +0 -0
  93. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_accessor.py +0 -0
  94. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_api.py +0 -0
  95. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_default_clears_override.py +0 -0
  96. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_env_unprefixed.py +0 -0
  97. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_events.py +0 -0
  98. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_field_sources.py +0 -0
  99. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_framework_reexports.py +0 -0
  100. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_group_metadata.py +0 -0
  101. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_host_restart_flags.py +0 -0
  102. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_module.py +0 -0
  103. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_schemas.py +0 -0
  104. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_secret_json_roundtrip.py +0 -0
  105. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_secret_masking.py +0 -0
  106. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_secret_urls.py +0 -0
  107. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_service.py +0 -0
  108. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_typed_secret_masking.py +0 -0
  109. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_settings_view_authz.py +0 -0
  110. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_store.py +0 -0
  111. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_store_filters.py +0 -0
  112. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_store_secret_masking.py +0 -0
  113. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_tenant_settings.py +0 -0
  114. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_testable_checks.py +0 -0
  115. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests/test_upload_key_delete.py +0 -0
  116. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/JsonFields.test.tsx +0 -0
  117. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/ModuleForm.test.tsx +0 -0
  118. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/ModulesEdit.test.tsx +0 -0
  119. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/RestartHint.test.tsx +0 -0
  120. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/ScopeTabs.test.tsx +0 -0
  121. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tests-js/settings_TestConnectionButton.test.tsx +0 -0
  122. {simple_module_settings-0.0.38 → simple_module_settings-0.0.39}/tsconfig.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simple_module_settings
3
- Version: 0.0.38
3
+ Version: 0.0.39
4
4
  Summary: Runtime settings UI — modules plug their own settings panels into a shared admin view
5
5
  Project-URL: Homepage, https://github.com/antosubash/simple_module_python
6
6
  Project-URL: Repository, https://github.com/antosubash/simple_module_python
@@ -21,10 +21,10 @@ Classifier: Topic :: Internet :: WWW/HTTP
21
21
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
22
  Classifier: Typing :: Typed
23
23
  Requires-Python: >=3.12
24
- Requires-Dist: simple-module-core==0.0.38
25
- Requires-Dist: simple-module-db==0.0.38
26
- Requires-Dist: simple-module-hosting==0.0.38
27
- Requires-Dist: typer>=0.12
24
+ Requires-Dist: simple-module-core==0.0.39
25
+ Requires-Dist: simple-module-db==0.0.39
26
+ Requires-Dist: simple-module-hosting==0.0.39
27
+ Requires-Dist: typer<0.28,>=0.12
28
28
  Description-Content-Type: text/markdown
29
29
 
30
30
  # simple_module_settings
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simple-module-py/settings",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "private": true,
5
5
  "description": "Frontend assets for the Settings module",
6
6
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "simple_module_settings"
3
- version = "0.0.38"
3
+ version = "0.0.39"
4
4
  description = "Runtime settings UI — modules plug their own settings panels into a shared admin view"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -21,10 +21,10 @@ classifiers = [
21
21
  "Typing :: Typed",
22
22
  ]
23
23
  dependencies = [
24
- "simple_module_core==0.0.38",
25
- "simple_module_db==0.0.38",
26
- "simple_module_hosting==0.0.38",
27
- "typer>=0.12",
24
+ "simple_module_core==0.0.39",
25
+ "simple_module_db==0.0.39",
26
+ "simple_module_hosting==0.0.39",
27
+ "typer>=0.12,<0.28",
28
28
  ]
29
29
 
30
30
  [project.entry-points.simple_module]
@@ -6,6 +6,7 @@ from simple_module_db import LIKE_ESCAPE_CHAR, like_contains_pattern
6
6
  from simple_module_db.stored_settings import SYSTEM_SCOPE_ID, Setting
7
7
  from sqlalchemy import func, select
8
8
  from sqlalchemy.ext.asyncio import AsyncSession
9
+ from sqlmodel import col
9
10
 
10
11
  from settings._row_masking import out
11
12
  from settings.constants import ALL_SCOPES, DEFAULT_PER_PAGE, SCOPE_ALL
@@ -111,6 +112,6 @@ class SettingListing:
111
112
  def _scope_stmt(scope: SettingScope, scope_id: str):
112
113
  return (
113
114
  select(Setting)
114
- .where(Setting.scope == scope.value, Setting.scope_id == scope_id) # ty: ignore[invalid-argument-type]
115
+ .where(col(Setting.scope) == scope.value, col(Setting.scope_id) == scope_id)
115
116
  .order_by(Setting.key)
116
117
  )
@@ -25,11 +25,12 @@ from collections.abc import Awaitable, Callable
25
25
  from settings.constants import ERR_MANAGED_KEY_DELETE
26
26
  from settings.contracts.registry import SettingsRegistry, clear_route
27
27
  from settings.contracts.schemas import SettingScope
28
+ from settings.exceptions import SettingsError
28
29
 
29
30
  TenantIsLive = Callable[[str], Awaitable[bool]]
30
31
 
31
32
 
32
- class ManagedKeyError(Exception):
33
+ class ManagedKeyError(SettingsError):
33
34
  """The key is cleared through ``clear_via``, not by deleting its row."""
34
35
 
35
36
  def __init__(self, key: str, clear_via: str) -> None:
@@ -12,8 +12,10 @@ from simple_module_db.stored_settings import Setting
12
12
  from sqlalchemy.exc import IntegrityError
13
13
  from sqlalchemy.ext.asyncio import AsyncSession
14
14
 
15
+ from settings.exceptions import SettingsError
15
16
 
16
- class DuplicateSettingError(Exception):
17
+
18
+ class DuplicateSettingError(SettingsError):
17
19
  """A row with this (scope, scope_id, key) already exists."""
18
20
 
19
21
 
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
  from typing import Annotated
12
12
 
13
13
  from fastapi import Depends, Request
14
+ from simple_module_core.app_state import get_services
14
15
  from simple_module_db.deps import get_db
15
16
  from sqlalchemy.ext.asyncio import AsyncSession
16
17
 
@@ -25,7 +26,7 @@ async def get_setting_service(
25
26
  request: Request,
26
27
  db: AsyncSession = Depends(get_db),
27
28
  ) -> SettingService:
28
- bus = getattr(getattr(request.app.state, "sm", None), "invalidation", None)
29
+ bus = getattr(get_services(request.app), "invalidation", None)
29
30
 
30
31
  async def tenant_is_live(tenant_id: str) -> bool:
31
32
  return await is_known_tenant(request, tenant_id)
@@ -0,0 +1,5 @@
1
+ """Transport-independent settings business failures."""
2
+
3
+
4
+ class SettingsError(Exception):
5
+ """Base for errors raised by settings services."""
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING
7
7
  from simple_module_db.stored_settings import SYSTEM_SCOPE_ID, VALUE_TYPE_STRING, Setting
8
8
  from sqlalchemy import select
9
9
  from sqlalchemy.ext.asyncio import AsyncSession
10
+ from sqlmodel import col
10
11
 
11
12
  from settings._announce import announce
12
13
  from settings._listing import SettingListing
@@ -204,9 +205,9 @@ class SettingService(SettingListing):
204
205
 
205
206
  async def _find(self, scope: SettingScope, scope_id: str, key: str) -> Setting | None:
206
207
  stmt = select(Setting).where(
207
- Setting.scope == scope.value, # ty: ignore[invalid-argument-type]
208
- Setting.scope_id == scope_id, # ty: ignore[invalid-argument-type]
209
- Setting.key == key, # ty: ignore[invalid-argument-type]
208
+ col(Setting.scope) == scope.value,
209
+ col(Setting.scope_id) == scope_id,
210
+ col(Setting.key) == key,
210
211
  )
211
212
  result = await self.db.execute(stmt)
212
213
  return result.scalar_one_or_none()
@@ -0,0 +1,10 @@
1
+ """Settings business failures share a transport-independent base."""
2
+
3
+
4
+ def test_settings_errors_share_a_module_base():
5
+ from settings._managed_keys import ManagedKeyError
6
+ from settings._unique_write import DuplicateSettingError
7
+ from settings.exceptions import SettingsError
8
+
9
+ assert isinstance(ManagedKeyError("key", "/clear"), SettingsError)
10
+ assert isinstance(DuplicateSettingError("key"), SettingsError)