simple-module-feature-flags 0.0.2__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.
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/.gitignore +4 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/PKG-INFO +4 -4
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/constants.py +1 -1
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/module.py +1 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/pyproject.toml +4 -4
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/tests/test_feature_flags_api.py +22 -22
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/tests/test_feature_flags_service.py +5 -5
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/LICENSE +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/README.md +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/__init__.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/contracts/__init__.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/contracts/schemas.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/deps.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/__init__.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/api.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/endpoints/views.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/locales/en.json +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/models.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/pages/Browse.tsx +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/py.typed +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/service.py +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/package.json +0 -0
- {simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/tsconfig.json +0 -0
|
@@ -36,6 +36,10 @@ uploads/
|
|
|
36
36
|
# Vite
|
|
37
37
|
host/static/dist/
|
|
38
38
|
|
|
39
|
+
# VitePress (docs)
|
|
40
|
+
docs/.vitepress/cache/
|
|
41
|
+
docs/.vitepress/dist/
|
|
42
|
+
|
|
39
43
|
# Auto-generated frontend module manifest (regenerated by the host at boot
|
|
40
44
|
# or via `make gen-pages`).
|
|
41
45
|
host/client_app/modules.manifest.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simple_module_feature_flags
|
|
3
|
-
Version: 0.0.
|
|
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.
|
|
25
|
-
Requires-Dist: simple-module-db==0.0.
|
|
26
|
-
Requires-Dist: simple-module-hosting==0.0.
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "simple_module_feature_flags"
|
|
3
|
-
version = "0.0.
|
|
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.
|
|
25
|
-
"simple_module_db==0.0.
|
|
26
|
-
"simple_module_hosting==0.0.
|
|
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
|
-
#
|
|
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 "
|
|
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/
|
|
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"] == "
|
|
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/
|
|
38
|
+
"/api/feature_flags/file_storage.public_uploads",
|
|
39
39
|
json={"enabled": True},
|
|
40
40
|
)
|
|
41
|
-
resp = await authenticated_client.delete("/api/feature_flags/
|
|
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/
|
|
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/
|
|
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/
|
|
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"] == "
|
|
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/
|
|
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"] == "
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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"] == "
|
|
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/
|
|
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/
|
|
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/
|
|
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"] == "
|
|
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/
|
|
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="
|
|
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="
|
|
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("
|
|
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("
|
|
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("
|
|
211
|
+
assert sm.feature_flags.is_enabled("file_storage.public_uploads", tenant_id="other") is True
|
|
File without changes
|
|
File without changes
|
{simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/deps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/models.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/py.typed
RENAMED
|
File without changes
|
{simple_module_feature_flags-0.0.2 → simple_module_feature_flags-0.0.4}/feature_flags/service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|