Visitar URL original
feat(cbc): add CBC (Central Business Configuration) client module by soumyadey · Pull Request #333 · SAP/cloud-sdk-python · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c211dde
feat(cbc): add CBC (Central Business Configuration) client module
soumyadey Sep 13, 2026
a88e841
feat(cbc): support PEM cert values via env vars and cert_path/key_pat…
soumyadey Sep 14, 2026
e240597
fix(cbc): address CI failures — ruff format, ty errors, telemetry cou…
soumyadey Sep 14, 2026
dfe418e
fix(cbc): clean up DefaultClient docstring and gitignore
soumyadey Sep 16, 2026
dd784da
refactor(cbc): remove local-mode auto-detection
soumyadey Sep 18, 2026
006aefd
fix(cbc): bump telemetry module count to 17 after upstream addition
soumyadey Sep 18, 2026
dff43ae
feat(cbc): move tenant_context to client level
soumyadey Sep 18, 2026
3902ada
refactor(cbc): two-layer client contract — thin core + platform adapter
soumyadey Oct 3, 2026
a684ad1
perf(cbc): resolve base_url once per get_configuration call
soumyadey Oct 3, 2026
ef6832d
fix(cbc): wrap destination errors as CBCConfigError in adapter
soumyadey Oct 3, 2026
a615ed2
feat(cbc): reload rotated mTLS certificate on TLS handshake failure
soumyadey Oct 4, 2026
520864f
test(cbc): fix ty type errors in rotation and adapter tests
soumyadey Oct 4, 2026
3c6688a
feat(cbc): add CBCDestinationConfig for the platform adapter
soumyadey Oct 4, 2026
3254907
refactor(cbc): rename EntityContent/EntityData → EntityData/ConfigEntity
soumyadey Oct 6, 2026
12ff0de
fix(cbc): align with confirmed API contract for entity data response
soumyadey Oct 6, 2026
cf446e4
chore(cbc): fix ty annotation after ConfigEntity rename; bump version…
soumyadey Oct 6, 2026
86a8c2c
feat(cbc): add get_entity_data for targeted single-entity fetch
soumyadey Oct 7, 2026
0546be7
test(cbc): fix GUIDELINES violations found in code review
soumyadey Oct 7, 2026
07e74c2
feat(cbc): adapt resolve_base_url to direct fragment lookup after PR #82
soumyadey Oct 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(cbc): align with confirmed API contract for entity data response
REST API team confirmed:
- metadata.entityId is the correct field name (was entityName)
- content.item / content.items struct is correct (already was)
- ?appTenantId= query param is correct (already was)

Since metadata.entityId equals the entity_id already known from the URL
path, drop the metadata read entirely — entity_id is used directly.
Remove the now-redundant resolved_id fallback and the deleted
test_falls_back_to_path_entity_id_without_metadata test. Strip stale
metadata fields from remaining mock response bodies.
  • Loading branch information
soumyadey committed Oct 7, 2026
commit 12ff0de69a6e82980dedffffab85582e91db022c
4 changes: 1 addition & 3 deletions src/sap_cloud_sdk/cbc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ def _fetch_entity_data(
)
body = self._request("GET", url).json()

api_meta = body.get("metadata", {}) if isinstance(body, dict) else {}
content = body.get("content", {}) if isinstance(body, dict) else {}
shape = body.get("contentShape") if isinstance(body, dict) else None
if shape == "OBJECT":
Expand All @@ -357,8 +356,7 @@ def _fetch_entity_data(
# ARRAY / UNSPECIFIED / absent — items may be absent or empty.
raw_data = content.get("items", [])

resolved_id = api_meta.get("entityName") or entity_id
return ConfigEntity(entity_id=resolved_id, data=EntityData(raw_data))
return ConfigEntity(entity_id=entity_id, data=EntityData(raw_data))

def _configurations_url(self, base_url: str, path: str = "") -> str:
base = base_url.rstrip("/")
Expand Down
25 changes: 1 addition & 24 deletions tests/cbc/unit/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,6 @@ def test_reads_array_content_items(self):
client, mock_http = _make_client()
mock_http.request.return_value = _mock_response(
json_body={
"metadata": {
"entityName": "tax-category",
"configurationObjectId": "tax-config",
},
"contentShape": "ARRAY",
"content": {"items": [{"code": "STD"}], "adaptedKeys": []},
}
Expand All @@ -208,10 +204,6 @@ def test_reads_object_content_item(self):
client, mock_http = _make_client()
mock_http.request.return_value = _mock_response(
json_body={
"metadata": {
"entityName": "globalSettings",
"configurationObjectId": "pmc-settings",
},
"contentShape": "OBJECT",
"content": {"item": {"maxRetries": 3, "timeoutSeconds": 30}},
}
Expand All @@ -229,7 +221,7 @@ def test_reads_object_content_item(self):
def test_defaults_to_empty_list_when_content_absent(self):
client, mock_http = _make_client()
mock_http.request.return_value = _mock_response(
json_body={"metadata": {"entityName": "policy"}, "contentShape": "ARRAY"}
json_body={"contentShape": "ARRAY"}
)
result = client._fetch_entity_data(
"https://cbc.example.ondemand.com",
Expand All @@ -240,20 +232,6 @@ def test_defaults_to_empty_list_when_content_absent(self):
)
assert result.data.as_list() == []

def test_falls_back_to_path_entity_id_without_metadata(self):
client, mock_http = _make_client()
mock_http.request.return_value = _mock_response(
json_body={"contentShape": "ARRAY", "content": {"items": []}}
)
result = client._fetch_entity_data(
"https://cbc.example.ondemand.com",
"app-tenant",
"cv1",
"tax-config",
"tax-rate",
)
assert result.entity_id == "tax-rate"


# ---------------------------------------------------------------------------
# DefaultClient — get_configuration
Expand Down Expand Up @@ -292,7 +270,6 @@ def test_uses_explicit_consumption_version(self):
)
data_response = _mock_response(
json_body={
"metadata": {"entityName": "payment-mode"},
"contentShape": "ARRAY",
"content": {"items": [{"k": "v"}]},
}
Expand Down