feat(client): add shade.api_base override support#29
Conversation
- Add config.py with Environment enum (MAINNET/TESTNET) exposing base_url and network_passphrase via stellar_sdk.Network constants - Add shade.api_base module-level attribute (backed by config.api_base) that routes all new clients to a custom host when set - Add api_base and environment parameters to Gateway; resolution order: explicit api_base > shade.api_base > legacy base_url > environment URL - Trailing slashes on any provided api_base are trimmed - Export ShadeClient as an alias for Gateway - Add tests covering all acceptance criteria
📝 WalkthroughWalkthroughAdds module-level API base override support, introduces ChangesAPI base override support
Sequence Diagram(s)sequenceDiagram
participant ClientCode as Client code
participant ShadeApiBase as shade.api_base
participant ConfigApiBase as shade.config.api_base
participant GatewayInit as Gateway.__init__
participant HttpClients as sync and async HTTP clients
ClientCode->>ShadeApiBase: set api_base
ShadeApiBase->>ConfigApiBase: store override value
ClientCode->>GatewayInit: create Gateway(api_base=...)
GatewayInit->>ConfigApiBase: read module-level api_base
GatewayInit->>GatewayInit: resolve api_base, _config.api_base, base_url, Environment.base_url
GatewayInit->>HttpClients: initialize with resolved _base_url
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Adds first-class support for overriding the Shade API base URL at both the module level (shade.api_base) and per-client level (Gateway(api_base=...)), while introducing an Environment enum to standardize default URLs and Stellar network passphrases.
Changes:
- Introduces
shade.config.Environmentand a module-levelconfig.api_baseoverride source of truth. - Updates
Gatewayto resolve its base URL via a defined precedence order and normalize trailing slashes. - Adds a comprehensive test suite for
api_basebehavior and exportsShadeClientas an alias forGateway.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/shade/config.py |
Adds Environment enum and global api_base override storage. |
src/shade/__init__.py |
Exposes shade.api_base as a settable module attribute; exports Environment and ShadeClient. |
src/shade/gateway.py |
Implements URL resolution precedence across api_base, module override, legacy base_url, and environment defaults. |
tests/test_api_base.py |
Adds tests covering override behavior, precedence, normalization, environment passphrases, and ShadeClient aliasing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def __init__( | ||
| self, | ||
| api_key: str = "", | ||
| environment: Environment = Environment.MAINNET, | ||
| api_base: Optional[str] = None, |
| class TestUrlResolutionPrecedence: | ||
| def test_environment_url_is_default(self): | ||
| gw = Gateway(api_key="test-key", environment=Environment.MAINNET) | ||
| assert gw._base_url == Environment.MAINNET.base_url | ||
|
|
||
| def test_module_level_beats_environment(self): | ||
| shade.api_base = "https://staging.shadeprotocol.io" | ||
| gw = Gateway(api_key="test-key", environment=Environment.MAINNET) | ||
| assert gw._base_url == "https://staging.shadeprotocol.io" | ||
|
|
||
| def test_per_client_beats_module_level(self): | ||
| shade.api_base = "https://staging.shadeprotocol.io" | ||
| gw = Gateway(api_key="test-key", api_base="http://localhost:8000") | ||
| assert gw._base_url == "http://localhost:8000" | ||
|
|
||
| def test_testnet_environment_url_used_by_default(self): | ||
| gw = Gateway(api_key="test-key", environment=Environment.TESTNET) | ||
| assert gw._base_url == Environment.TESTNET.base_url | ||
|
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/shade/gateway.py (1)
49-52: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConfirm intended precedence: global
shade.api_baseoverrides an explicitly-passed per-clientbase_url.In
api_base or _config.api_base or base_url or environment.base_url, a process-wideshade.api_baseoutranks a per-client legacybase_url=argument. A caller who explicitly passes the (deprecated but still supported)base_urlper client may be surprised to have it silently overridden by a global. If the intent is that any explicit per-client argument should win over the module-level global, consider ordering legacybase_urlahead of_config.api_base.♻️ Optional reordering so explicit per-client args beat the global
- resolved = api_base or _config.api_base or base_url or environment.base_url + resolved = api_base or base_url or _config.api_base or environment.base_urlConfirm the desired precedence between per-client
base_urland globalshade.api_base; current tests don't exercise this combination.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/shade/gateway.py` around lines 49 - 52, Confirm and enforce the intended URL precedence in Gateway initialization: the current resolution in Gateway.__init__ lets the module-level shade.api_base override an explicitly passed per-client base_url, which may be unintended. Update the ordering of resolved so the chosen precedence is explicit and consistent, then add or adjust tests covering the interaction between the deprecated base_url argument and _config.api_base to lock in the behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/shade/gateway.py`:
- Around line 49-52: Confirm and enforce the intended URL precedence in Gateway
initialization: the current resolution in Gateway.__init__ lets the module-level
shade.api_base override an explicitly passed per-client base_url, which may be
unintended. Update the ordering of resolved so the chosen precedence is explicit
and consistent, then add or adjust tests covering the interaction between the
deprecated base_url argument and _config.api_base to lock in the behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 70ae44dd-f123-413d-bc40-c6356f0c8509
📒 Files selected for processing (4)
src/shade/__init__.pysrc/shade/config.pysrc/shade/gateway.pytests/test_api_base.py
|
@Tijesunimi004 |
codebestia
left a comment
There was a problem hiding this comment.
LGTM!
Thank you for your contribution.
Closes #6
What changed
src/shade/config.py(new)Environmentenum withMAINNETandTESTNETvariants, each exposingbase_urlandnetwork_passphrase(sourced fromstellar_sdk.Networkconstants)api_base: Optional[str] = None— the single source of truth for the global overridesrc/shade/__init__.pyshade.api_baseis now a settable module-level attribute backed byconfig.api_basevia a module__class__override (standard Python pattern — no extra dependencies)EnvironmentandShadeClient(alias forGateway)src/shade/gateway.pyenvironment: Environment = Environment.MAINNETparameter; controls Stellar network passphrase and fallback URL independently ofapi_baseapi_base: Optional[str] = Noneparameter; takes precedence over the module-level value and environment URLapi_basearg >shade.api_base> legacybase_url>environment.base_urltests/test_api_base.py(new, 23 tests)EnvironmentURL and passphrase valuesShadeClientaliasAcceptance criteria
shade.api_base = "https://staging..."routes all requests thereconfig.api_base; Gateway reads it at init timeShadeClient(api_base="http://localhost:8000")routes locallyapi_baseparam beats module-level and environment URLapi_baseis setgateway.environmentis stored independently; only URL resolution usesapi_baseresolved.rstrip("/")applied to the winning valueSummary by CodeRabbit
New Features
ShadeClientalias for the main client interface.Bug Fixes