Skip to content

Commit e99b6b1

Browse files
committed
chore: update docs
1 parent 903c48e commit e99b6b1

11 files changed

Lines changed: 116 additions & 116 deletions

File tree

README.md

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ with Replane(
4141
sdk_key="rp_...",
4242
) as replane:
4343
# Get a simple config value
44-
rate_limit = replane.configs["rate-limit"]
44+
rate_limit = replane.configs["rate_limit"]
4545

4646
# Get with context for override evaluation
4747
user_client = replane.with_context({"user_id": user.id, "plan": user.plan})
48-
feature_enabled = user_client.configs["new-feature"]
48+
feature_enabled = user_client.configs["new_feature"]
4949

5050
# Get with fallback default
51-
timeout = replane.configs.get("request-timeout", 30)
51+
timeout = replane.configs.get("request_timeout", 30)
5252
```
5353

5454
### Asynchronous Client
@@ -63,7 +63,7 @@ async with AsyncReplane(
6363
sdk_key="rp_...",
6464
) as replane:
6565
# Access configs from local cache
66-
rate_limit = replane.configs["rate-limit"]
66+
rate_limit = replane.configs["rate_limit"]
6767

6868
# With context
6969
enabled = replane.with_context({"plan": "premium"}).configs["feature"]
@@ -89,9 +89,9 @@ replane.connect(
8989
)
9090

9191
# Use configs
92-
rate_limit = replane.configs["rate-limit"]
92+
rate_limit = replane.configs["rate_limit"]
9393
user_client = replane.with_context({"user_id": "123"})
94-
feature = user_client.configs["feature-flag"]
94+
feature = user_client.configs["feature_flag"]
9595

9696
# Don't forget to close when done
9797
replane.close()
@@ -111,23 +111,23 @@ with Replane[Configs](
111111
sdk_key="rp_...",
112112
) as replane:
113113
# Access configs with dictionary-style notation
114-
settings = replane.configs["app-settings"]
114+
settings = replane.configs["app_settings"]
115115

116116
# Full type safety - IDE knows the structure of settings
117117
print(settings["max_upload_size_mb"])
118118
print(settings["allowed_file_types"])
119119

120120
# Check if config exists
121-
if "feature-flag" in replane.configs:
122-
flag = replane.configs["feature-flag"]
121+
if "feature_flag" in replane.configs:
122+
flag = replane.configs["feature_flag"]
123123

124124
# Safe access with default
125125
timeout = replane.configs.get("timeout", 30)
126126
```
127127

128128
The `.configs` property provides:
129129

130-
- **Dictionary-style access** with `replane.configs["config-name"]`
130+
- **Dictionary-style access** with `replane.configs["config_name"]`
131131
- **Type inference** when using generated TypedDict types
132132
- **Override evaluation** using the default context
133133
- **Familiar dict methods**: `.get()`, `.keys()`, `in` operator
@@ -146,12 +146,12 @@ replane = Replane(
146146

147147
# Default values used if server is unavailable during init
148148
defaults={
149-
"rate-limit": 100,
150-
"feature-enabled": False,
149+
"rate_limit": 100,
150+
"feature_enabled": False,
151151
},
152152

153153
# Configs that must exist (raises error if missing)
154-
required=["rate-limit", "feature-enabled"],
154+
required=["rate_limit", "feature_enabled"],
155155

156156
# Timeouts in milliseconds
157157
request_timeout_ms=2000,
@@ -181,7 +181,7 @@ context = {
181181
}
182182

183183
# Overrides are evaluated locally using with_context()
184-
value = replane.with_context(context).configs["feature-flag"]
184+
value = replane.with_context(context).configs["feature_flag"]
185185
```
186186

187187
### Scoped Clients with `with_context()`
@@ -200,8 +200,8 @@ with Replane(
200200
})
201201

202202
# All operations use the merged context
203-
rate_limit = user_client.configs["rate-limit"]
204-
settings = user_client.configs["app-settings"]
203+
rate_limit = user_client.configs["rate_limit"]
204+
settings = user_client.configs["app_settings"]
205205

206206
# Can be chained for additional context
207207
request_client = user_client.with_context({"region": request.region})
@@ -221,15 +221,15 @@ with Replane(
221221
# Create a client with fallback defaults
222222
safe_client = replane.with_defaults({
223223
"timeout": 30,
224-
"max-retries": 3,
224+
"max_retries": 3,
225225
})
226226

227227
# Returns the default if config doesn't exist
228228
timeout = safe_client.configs["timeout"] # 30 if not configured
229229

230230
# Chain with with_context() for both features
231231
user_client = replane.with_context({"plan": "premium"}).with_defaults({
232-
"rate-limit": 1000,
232+
"rate_limit": 1000,
233233
})
234234
```
235235

@@ -242,20 +242,20 @@ Explicit defaults in `.configs.get()` take precedence over scoped defaults.
242242
```python
243243
# Server config has 10% rollout based on user_id
244244
# Same user always gets same result (deterministic hashing)
245-
enabled = replane.with_context({"user_id": user.id}).configs["new-checkout"]
245+
enabled = replane.with_context({"user_id": user.id}).configs["new_checkout"]
246246
```
247247

248248
**Plan-based features**:
249249

250250
```python
251-
max_items = replane.with_context({"plan": user.plan}).configs["max-items"]
251+
max_items = replane.with_context({"plan": user.plan}).configs["max_items"]
252252
# Returns different values for free/pro/enterprise plans
253253
```
254254

255255
**Geographic targeting**:
256256

257257
```python
258-
content = replane.with_context({"country": request.country}).configs["homepage-banner"]
258+
content = replane.with_context({"country": request.country}).configs["homepage_banner"]
259259
```
260260

261261
## Subscribing to Changes
@@ -273,7 +273,7 @@ unsubscribe = replane.subscribe(on_any_change)
273273
def on_feature_change(config):
274274
update_feature_state(config.value)
275275

276-
unsubscribe_feature = replane.subscribe_config("my-feature", on_feature_change)
276+
unsubscribe_feature = replane.subscribe_config("my_feature", on_feature_change)
277277

278278
# Later: stop receiving updates
279279
unsubscribe()
@@ -301,7 +301,7 @@ from replane import (
301301
)
302302

303303
try:
304-
value = replane.configs["my-config"]
304+
value = replane.configs["my_config"]
305305
except KeyError as e:
306306
print(f"Config not found: {e}")
307307
except TimeoutError as e:
@@ -321,11 +321,11 @@ from replane.testing import create_test_client, InMemoryReplaneClient
321321

322322
# Simple usage
323323
replane = create_test_client({
324-
"feature-enabled": True,
325-
"rate-limit": 100,
324+
"feature_enabled": True,
325+
"rate_limit": 100,
326326
})
327327

328-
assert replane.configs["feature-enabled"] is True
328+
assert replane.configs["feature_enabled"] is True
329329

330330
# With overrides
331331
replane = InMemoryReplaneClient()
@@ -354,13 +354,13 @@ from replane.testing import create_test_client
354354
@pytest.fixture
355355
def replane_client():
356356
return create_test_client({
357-
"feature-flags": {"dark-mode": True, "new-ui": False},
358-
"rate-limits": {"default": 100, "premium": 1000},
357+
"feature_flags": {"dark_mode": True, "new-ui": False},
358+
"rate_limits": {"default": 100, "premium": 1000},
359359
})
360360

361361
def test_feature_flag(replane_client):
362-
flags = replane_client.configs["feature-flags"]
363-
assert flags["dark-mode"] is True
362+
flags = replane_client.configs["feature_flags"]
363+
assert flags["dark_mode"] is True
364364
```
365365

366366
## Manual Lifecycle Management
@@ -420,7 +420,7 @@ Replane = Annotated[AsyncReplane, Depends(get_replane)]
420420

421421
@app.get("/items")
422422
async def get_items(replane: Replane):
423-
max_items = replane.with_context({"plan": "free"}).configs["max-items"]
423+
max_items = replane.with_context({"plan": "free"}).configs["max_items"]
424424
return {"max_items": max_items}
425425
```
426426

@@ -444,7 +444,7 @@ def init_replane():
444444

445445
@app.route("/items")
446446
def get_items():
447-
max_items = _replane.configs["max-items"]
447+
max_items = _replane.configs["max_items"]
448448
return {"max_items": max_items}
449449
```
450450

docs/source/configuration.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ replane = Replane(
1616

1717
# Optional
1818
context={"environment": "production"},
19-
defaults={"rate-limit": 100, "feature-enabled": False},
20-
required=["rate-limit", "feature-enabled"],
19+
defaults={"rate_limit": 100, "feature_enabled": False},
20+
required=["rate_limit", "feature_enabled"],
2121
request_timeout_ms=2000,
2222
initialization_timeout_ms=5000,
2323
retry_delay_ms=200,
@@ -80,11 +80,11 @@ replane = Replane(
8080
)
8181

8282
# This uses the default context
83-
value = replane.configs["config-name"]
83+
value = replane.configs["config_name"]
8484

8585
# This merges with default context using with_context()
8686
user_client = replane.with_context({"user_id": "123"})
87-
value = user_client.configs["config-name"]
87+
value = user_client.configs["config_name"]
8888
# Effective context: {"environment": "production", "region": "us-east", "user_id": "123"}
8989
```
9090

@@ -99,8 +99,8 @@ Default values used when configs can't be loaded from the server. This is useful
9999
replane = Replane(
100100
...,
101101
defaults={
102-
"rate-limit": 100,
103-
"feature-enabled": False,
102+
"rate_limit": 100,
103+
"feature_enabled": False,
104104
"max-connections": 10,
105105
},
106106
)
@@ -121,7 +121,7 @@ List of config names that must be present after initialization. If any required
121121
```python
122122
replane = Replane(
123123
...,
124-
required=["rate-limit", "feature-enabled"],
124+
required=["rate_limit", "feature_enabled"],
125125
)
126126
# Raises ConfigNotFoundError if either config is missing
127127
```
@@ -218,7 +218,7 @@ Example output:
218218
2024-01-15 10:30:00 [DEBUG] replane: Connecting to SSE: host=cloud.replane.dev, port=443, https=True
219219
2024-01-15 10:30:00 [DEBUG] replane: Response status: 200 OK
220220
2024-01-15 10:30:00 [DEBUG] replane: SSE event received: type=init
221-
2024-01-15 10:30:00 [DEBUG] replane: Loaded config: rate-limit (value=100, overrides=2)
221+
2024-01-15 10:30:00 [DEBUG] replane: Loaded config: rate_limit (value=100, overrides=2)
222222
2024-01-15 10:30:00 [DEBUG] replane: Initialization complete: 5 configs loaded
223223
```
224224

docs/source/errors.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ try:
5252
base_url="https://cloud.replane.dev",
5353
sdk_key="rp_...",
5454
) as replane:
55-
value = replane.configs["my-config"]
55+
value = replane.configs["my_config"]
5656
except KeyError as e:
5757
print(f"Config not found: {e}")
5858
except TimeoutError as e:
@@ -91,7 +91,7 @@ Accessing a missing config via bracket notation raises a standard `KeyError`:
9191

9292
```python
9393
try:
94-
value = replane.configs["nonexistent-config"]
94+
value = replane.configs["nonexistent_config"]
9595
except KeyError as e:
9696
print(f"Config not found: {e}")
9797
value = "default"
@@ -124,7 +124,7 @@ from replane import Replane, ConfigNotFoundError
124124
try:
125125
with Replane(
126126
...,
127-
required=["critical-config-1", "critical-config-2"],
127+
required=["critical_config-1", "critical_config-2"],
128128
) as replane:
129129
pass
130130
except ConfigNotFoundError as e:
@@ -280,7 +280,7 @@ except ReplaneError as e:
280280
```python
281281
# Good: specific handling
282282
try:
283-
value = replane.configs["critical-config"]
283+
value = replane.configs["critical_config"]
284284
except KeyError:
285285
logger.error("Critical config missing!")
286286
raise # Re-raise for critical configs

docs/source/frameworks.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Replane = Annotated[AsyncReplane, Depends(get_replane)]
4242

4343
@app.get("/items")
4444
async def get_items(replane: Replane):
45-
max_items = replane.configs["max-items-per-page"]
45+
max_items = replane.configs["max_items_per_page"]
4646
return {"max_items": max_items}
4747
```
4848

@@ -60,8 +60,8 @@ async def get_features(request: Request, replane: Replane):
6060
})
6161

6262
return {
63-
"dark_mode": user_client.configs["dark-mode-enabled"],
64-
"beta_features": user_client.configs["beta-features"],
63+
"dark_mode": user_client.configs["dark_mode_enabled"],
64+
"beta_features": user_client.configs["beta_features"],
6565
}
6666
```
6767

@@ -88,7 +88,7 @@ ReplaneWithContext = Annotated[ContextualAsyncReplane, Depends(get_replane_with_
8888
@app.get("/dashboard")
8989
async def dashboard(replane: ReplaneWithContext):
9090
# Context is automatically included
91-
show_analytics = replane.configs["show-analytics"]
91+
show_analytics = replane.configs["show_analytics"]
9292
return {"show_analytics": show_analytics}
9393
```
9494

@@ -120,7 +120,7 @@ def get_replane() -> Replane:
120120
@app.route("/items")
121121
def get_items():
122122
replane = get_replane()
123-
max_items = replane.configs["max-items-per-page"]
123+
max_items = replane.configs["max_items_per_page"]
124124
return {"max_items": max_items}
125125
```
126126

@@ -151,7 +151,7 @@ def create_app():
151151
@app.route("/features")
152152
def features():
153153
replane = current_app.replane
154-
return {"enabled": replane.configs["feature-enabled"]}
154+
return {"enabled": replane.configs["feature_enabled"]}
155155
```
156156

157157
### Flask Extension Pattern

0 commit comments

Comments
 (0)