Fixed ResourceType handling and other small improvements#16
Conversation
saksham-nexla
left a comment
There was a problem hiding this comment.
Review Summary
This PR does several things well: the ResourceType enum-based normalization is a clean approach to preventing singular/plural typos in URL path segments, the AliasChoices upgrade to FlowLogsMeta correctly handles multiple live API response shapes, and the normalize_live_logs_shape validator elegantly flattens the nested logs.data / logs.meta payload without breaking the existing flat-list response shape.
Key Concerns
[blocker] get_run_status is a silent breaking change.
The old signature get_run_status(resource_type, resource_id, run_id) is replaced by get_run_status(flow_id, run_id). A caller passing the old three-argument form gets no TypeError — "data_sources" is silently treated as flow_id. This needs either a deprecation shim or an explicit breaking-change notice in the PR description and changelog.
[major] FlowLogEntry.timestamp + mock integer timestamps will silently produce wrong datetimes.
The mock builder now emits 1_700_000_000_000 (a millisecond epoch integer) for timestamp, but the Pydantic v2 field is Optional[datetime], which coerces integers as seconds — yielding a date around year 55843. No test ever asserts on the parsed timestamp value, so the bug is invisible in CI. A @field_validator is needed to divide by 1000 when the value looks like a ms integer, or the mock should revert to ISO-format strings. (See inline comments on responses.py:28 and mock_builders.py:509.)
[major] ResourceType(resource_type).value is copy-pasted across 9+ methods.
Factoring it into a single _resolve_resource_type() helper would centralise the validation logic and allow a friendlier error message than the raw enum ValueError. (See inline comment on flows.py:102.)
Smaller Items
FlowLogsMetagainsorg_idandrun_idfields with no documentation or tests.- The
"pages_count"alias (a third spelling forpage_count) is unexplained — a one-line comment noting it comes from the live API response would prevent future confusion. test_flows.pyhas no test that invalid resource-type strings are rejected before an HTTP call is made (covered intest_metrics.pybut not mirrored here).- The
metaprecedence rule innormalize_live_logs_shapeis correct but deserves a one-line comment to make the intent clear.
Verdict: Request Changes — the get_run_status breaking change and the timestamp type mismatch both need to be resolved before merging.
Generated by Claude Code
|
@saksham-nexla thanks for the review. Addressed the comments. Key changes:
|
saksham-nexla
left a comment
There was a problem hiding this comment.
Review Summary
What's done well
The core fix is solid. Routing ResourceType enum values through _resolve_enum_value gives a single, tested validation point that rejects singular strings ("data_source") and accepts both enum members and canonical string values. The FlowLogsResponse model-validator approach to flatten the live logs.data / logs.meta shape is clean and backward-compatible. The AliasChoices usage in FlowLogsMeta correctly handles the camelCase / snake_case / live-API spelling variations without duplicating logic. Test coverage for the new enum paths and the live logs shape is well-structured.
Key concerns
Blocker — raise DeprecationWarning(...) in get_run_status
DeprecationWarning is a Warning subclass, not an Exception. Raising it directly makes it propagate as an unhandled exception instead of participating in Python's standard warning-filter machinery. The test reinforces this wrong behavior by using pytest.raises. This needs to become warnings.warn(..., DeprecationWarning, stacklevel=2) followed by a TypeError to hard-stop the call; the test needs to become pytest.warns(DeprecationWarning). See inline comment on line 509.
Major — Hard breaking change with no migration period
get_run_status completely replaces its public signature and immediately fails callers using the old three-argument form. For a published SDK, the conventional approach is to warn-but-work for one minor release, then hard-fail in the next. If the Nexla API has already removed the old endpoint, document that in a CHANGELOG entry and couple it with a semver bump.
Major — _resolve_resource_type in BaseResource creates unnecessary coupling
BaseResource is the root of every SDK resource, yet this method imports and references ResourceType from the metrics/flows domain. The generic _resolve_enum_value belongs in the base; the domain-specific wrapper should live in FlowsResource, MetricsResource, and OrganizationsResource.
Minor / nit issues
FlowLogsResponse.normalize_live_logs_shape: preferlogs.get("data", [])overlogs.get("data") or []for clarity.coerce_ms_timestamp: the1e10threshold should have a brief comment explaining the year-2286 invariant; add a test for seconds-based integer timestamps passing through unchanged.- Bare
except Exceptioninget_logs/get_metricssilently swallows PydanticValidationErrors — add alogger.debugcall so model drift is visible. mdx_textin the docs generator escapes braces inside code examples in docstrings; scope the escaping to prose-only lines.- Mock
flow_log_entrybuilder dropsrun_idanddetailsfields that are still declaredOptionalon the model, reducing incidental test coverage.
Verdict
Request changes — the raise DeprecationWarning bug is a correctness issue that will break callers in a confusing way and should be fixed before merging. The breaking-change governance question is worth an explicit decision before shipping.
Generated by Claude Code
ameyitis
left a comment
There was a problem hiding this comment.
Deep audit follow-up. The existing review threads cover most of the larger issues (DeprecationWarning misuse, breaking-change framing, ms-timestamp validator, helper placement). Filing six additional inline points that aren't yet covered — most are minor refinements; the type-lie in get_run_status and the duplicated log/message fields are the most concrete.
[question] One additional point that doesn't anchor cleanly on a changed line: nexla_sdk/resources/metrics.py:134 (get_flow_metrics_summary) still uses path = f"/data_flows/metrics/{period}". Every other /data_flows/... URL in this PR was rewritten to live under /{resource_type}/{resource_id}/flow/.... Is this endpoint intentionally a real survivor, or was it missed during the audit? If it's genuine, a one-line comment there would prevent future cleanup attempts; if it's a miss, this PR should fix it too — otherwise we'll ship inconsistent path conventions for the same conceptual area.
|
Thanks @saksham-nexla @ameyitis. I addressed the latest review pass:
Validation run: ruff, focused unit tests, full unit suite, docs build, live smoke checks for flow logs/metrics. |
Summary
data_source-style inputs and normalize resource-type path segments through the canonical enum values.FlowLogsResponseto parse the live nestedlogs.data/logs.metapayload shape and map live log fields onto the SDK model.Testing