simple-module-feature-flags 0.0.3__tar.gz → 0.0.4__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 (23) hide show
  1. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/PKG-INFO +4 -4
  2. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/constants.py +1 -1
  3. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/module.py +1 -0
  4. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/pyproject.toml +4 -4
  5. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/tests/test_feature_flags_api.py +22 -22
  6. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/tests/test_feature_flags_service.py +5 -5
  7. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/.gitignore +0 -0
  8. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/LICENSE +0 -0
  9. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/README.md +0 -0
  10. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/__init__.py +0 -0
  11. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/contracts/__init__.py +0 -0
  12. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/contracts/schemas.py +0 -0
  13. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/deps.py +0 -0
  14. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/__init__.py +0 -0
  15. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/api.py +0 -0
  16. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/views.py +0 -0
  17. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/locales/en.json +0 -0
  18. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/models.py +0 -0
  19. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/pages/Browse.tsx +0 -0
  20. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/py.typed +0 -0
  21. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/feature_flags/service.py +0 -0
  22. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/package.json +0 -0
  23. {simple_module_feature_flags-0.0.3 → simple_module_feature_flags-0.0.4}/tsconfig.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_module_feature_flags
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Simple feature-flag module with per-tenant overrides and a consumer API for simple_module
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,9 +21,9 @@ 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.3
25
- Requires-Dist: simple-module-db==0.0.3
26
- Requires-Dist: simple-module-hosting==0.0.3
24
+ Requires-Dist: simple-module-core==0.0.4
25
+ Requires-Dist: simple-module-db==0.0.4
26
+ Requires-Dist: simple-module-hosting==0.0.4
27
27
  Description-Content-Type: text/markdown
28
28
 
29
29
  # simple_module_feature_flags
@@ -22,7 +22,7 @@ LOCALE_NAMESPACE = "feature_flags"
22
22
  MENU_LABEL = "Feature Flags"
23
23
  MENU_URL = "/feature_flags"
24
24
  MENU_ICON = "flag"
25
- MENU_ORDER = 45
25
+ MENU_ORDER = 110
26
26
 
27
27
  PAGE_BROWSE = "FeatureFlags/Browse"
28
28
 
@@ -43,6 +43,7 @@ class FeatureFlagsModule(ModuleBase):
43
43
  icon=MENU_ICON,
44
44
  order=MENU_ORDER,
45
45
  section=MenuSection.SIDEBAR,
46
+ group="Administration",
46
47
  )
47
48
  )
48
49
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "simple_module_feature_flags"
3
- version = "0.0.3"
3
+ version = "0.0.4"
4
4
  description = "Simple feature-flag module with per-tenant overrides and a consumer API for simple_module"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -21,9 +21,9 @@ classifiers = [
21
21
  "Typing :: Typed",
22
22
  ]
23
23
  dependencies = [
24
- "simple_module_core==0.0.3",
25
- "simple_module_db==0.0.3",
26
- "simple_module_hosting==0.0.3",
24
+ "simple_module_core==0.0.4",
25
+ "simple_module_db==0.0.4",
26
+ "simple_module_hosting==0.0.4",
27
27
  ]
28
28
 
29
29
  [project.entry-points.simple_module]
@@ -9,20 +9,20 @@ class TestFeatureFlagsAPI:
9
9
  async def test_list_flags_returns_registered_flags(
10
10
  self, authenticated_client: httpx.AsyncClient
11
11
  ):
12
- # Products module registers `products.bulk_import`
12
+ # file_storage module registers `file_storage.public_uploads`
13
13
  resp = await authenticated_client.get("/api/feature_flags/")
14
14
  assert resp.status_code == 200
15
15
  names = {f["name"] for f in resp.json()}
16
- assert "products.bulk_import" in names
16
+ assert "file_storage.public_uploads" in names
17
17
 
18
18
  async def test_set_override_flips_flag(self, authenticated_client: httpx.AsyncClient):
19
19
  resp = await authenticated_client.put(
20
- "/api/feature_flags/products.bulk_import",
20
+ "/api/feature_flags/file_storage.public_uploads",
21
21
  json={"enabled": True},
22
22
  )
23
23
  assert resp.status_code == 200
24
24
  body = resp.json()
25
- assert body["name"] == "products.bulk_import"
25
+ assert body["name"] == "file_storage.public_uploads"
26
26
  assert body["enabled"] is True
27
27
  assert body["overridden"] is True
28
28
 
@@ -35,25 +35,25 @@ class TestFeatureFlagsAPI:
35
35
 
36
36
  async def test_clear_override_reverts_to_default(self, authenticated_client: httpx.AsyncClient):
37
37
  await authenticated_client.put(
38
- "/api/feature_flags/products.bulk_import",
38
+ "/api/feature_flags/file_storage.public_uploads",
39
39
  json={"enabled": True},
40
40
  )
41
- resp = await authenticated_client.delete("/api/feature_flags/products.bulk_import")
41
+ resp = await authenticated_client.delete("/api/feature_flags/file_storage.public_uploads")
42
42
  assert resp.status_code == 204
43
43
 
44
- follow = await authenticated_client.get("/api/feature_flags/products.bulk_import")
44
+ follow = await authenticated_client.get("/api/feature_flags/file_storage.public_uploads")
45
45
  assert follow.status_code == 200
46
46
  assert follow.json()["overridden"] is False
47
47
 
48
48
  async def test_clear_override_without_any_404s(self, authenticated_client: httpx.AsyncClient):
49
- resp = await authenticated_client.delete("/api/feature_flags/products.bulk_import")
49
+ resp = await authenticated_client.delete("/api/feature_flags/file_storage.public_uploads")
50
50
  assert resp.status_code == 404
51
51
 
52
52
  async def test_get_flag_returns_view(self, authenticated_client: httpx.AsyncClient):
53
- resp = await authenticated_client.get("/api/feature_flags/products.bulk_import")
53
+ resp = await authenticated_client.get("/api/feature_flags/file_storage.public_uploads")
54
54
  assert resp.status_code == 200
55
55
  body = resp.json()
56
- assert body["name"] == "products.bulk_import"
56
+ assert body["name"] == "file_storage.public_uploads"
57
57
  assert "default_enabled" in body
58
58
  assert "overridden" in body
59
59
 
@@ -63,12 +63,12 @@ class TestFeatureFlagsTenantAPI:
63
63
  self, authenticated_client: httpx.AsyncClient
64
64
  ):
65
65
  resp = await authenticated_client.put(
66
- "/api/feature_flags/tenant/acme/products.bulk_import",
66
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads",
67
67
  json={"enabled": True},
68
68
  )
69
69
  assert resp.status_code == 200
70
70
  body = resp.json()
71
- assert body["name"] == "products.bulk_import"
71
+ assert body["name"] == "file_storage.public_uploads"
72
72
  assert body["enabled"] is True
73
73
  assert body["overridden"] is True # acme has its own row
74
74
 
@@ -76,10 +76,10 @@ class TestFeatureFlagsTenantAPI:
76
76
  self, authenticated_client: httpx.AsyncClient
77
77
  ):
78
78
  await authenticated_client.put(
79
- "/api/feature_flags/tenant/acme/products.bulk_import",
79
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads",
80
80
  json={"enabled": True},
81
81
  )
82
- resp = await authenticated_client.get("/api/feature_flags/products.bulk_import")
82
+ resp = await authenticated_client.get("/api/feature_flags/file_storage.public_uploads")
83
83
  assert resp.status_code == 200
84
84
  # System view: no tenant_id → tenant override is invisible
85
85
  assert resp.json()["overridden"] is False
@@ -89,16 +89,16 @@ class TestFeatureFlagsTenantAPI:
89
89
  ):
90
90
  # System on, tenant off → tenant view should report enabled=False
91
91
  await authenticated_client.put(
92
- "/api/feature_flags/products.bulk_import",
92
+ "/api/feature_flags/file_storage.public_uploads",
93
93
  json={"enabled": True},
94
94
  )
95
95
  await authenticated_client.put(
96
- "/api/feature_flags/tenant/acme/products.bulk_import",
96
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads",
97
97
  json={"enabled": False},
98
98
  )
99
99
  resp = await authenticated_client.get("/api/feature_flags/tenant/acme")
100
100
  assert resp.status_code == 200
101
- flag = next(f for f in resp.json() if f["name"] == "products.bulk_import")
101
+ flag = next(f for f in resp.json() if f["name"] == "file_storage.public_uploads")
102
102
  assert flag["enabled"] is False
103
103
  assert flag["overridden"] is True
104
104
  assert flag["system_enabled"] is True
@@ -107,20 +107,20 @@ class TestFeatureFlagsTenantAPI:
107
107
  self, authenticated_client: httpx.AsyncClient
108
108
  ):
109
109
  await authenticated_client.put(
110
- "/api/feature_flags/products.bulk_import",
110
+ "/api/feature_flags/file_storage.public_uploads",
111
111
  json={"enabled": True},
112
112
  )
113
113
  await authenticated_client.put(
114
- "/api/feature_flags/tenant/acme/products.bulk_import",
114
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads",
115
115
  json={"enabled": False},
116
116
  )
117
117
  resp = await authenticated_client.delete(
118
- "/api/feature_flags/tenant/acme/products.bulk_import"
118
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads"
119
119
  )
120
120
  assert resp.status_code == 204
121
121
 
122
122
  follow = await authenticated_client.get("/api/feature_flags/tenant/acme")
123
- flag = next(f for f in follow.json() if f["name"] == "products.bulk_import")
123
+ flag = next(f for f in follow.json() if f["name"] == "file_storage.public_uploads")
124
124
  assert flag["enabled"] is True # back to system value
125
125
  assert flag["overridden"] is False
126
126
 
@@ -128,7 +128,7 @@ class TestFeatureFlagsTenantAPI:
128
128
  self, authenticated_client: httpx.AsyncClient
129
129
  ):
130
130
  resp = await authenticated_client.delete(
131
- "/api/feature_flags/tenant/acme/products.bulk_import"
131
+ "/api/feature_flags/tenant/acme/file_storage.public_uploads"
132
132
  )
133
133
  assert resp.status_code == 404
134
134
 
@@ -185,7 +185,7 @@ class TestFeatureFlagsModuleLifecycle:
185
185
  FeatureFlagOverride(
186
186
  scope="system",
187
187
  scope_id="",
188
- name="products.bulk_import",
188
+ name="file_storage.public_uploads",
189
189
  enabled=True,
190
190
  )
191
191
  )
@@ -193,7 +193,7 @@ class TestFeatureFlagsModuleLifecycle:
193
193
  FeatureFlagOverride(
194
194
  scope="tenant",
195
195
  scope_id="acme",
196
- name="products.bulk_import",
196
+ name="file_storage.public_uploads",
197
197
  enabled=False,
198
198
  )
199
199
  )
@@ -204,8 +204,8 @@ class TestFeatureFlagsModuleLifecycle:
204
204
  await FeatureFlagsModule().on_startup(app)
205
205
 
206
206
  # System: enabled
207
- assert sm.feature_flags.is_enabled("products.bulk_import") is True
207
+ assert sm.feature_flags.is_enabled("file_storage.public_uploads") is True
208
208
  # acme tenant: disabled (tenant beats system)
209
- assert sm.feature_flags.is_enabled("products.bulk_import", tenant_id="acme") is False
209
+ assert sm.feature_flags.is_enabled("file_storage.public_uploads", tenant_id="acme") is False
210
210
  # other tenant: still inherits system
211
- assert sm.feature_flags.is_enabled("products.bulk_import", tenant_id="other") is True
211
+ assert sm.feature_flags.is_enabled("file_storage.public_uploads", tenant_id="other") is True