Skip to content

fix(loaders): handle self-referencing types to avoid infinite recursion#122

Open
Mxiansen wants to merge 1 commit into
TencentCloud:masterfrom
Mxiansen:fix/loaders-self-ref-infinite-recursion
Open

fix(loaders): handle self-referencing types to avoid infinite recursion#122
Mxiansen wants to merge 1 commit into
TencentCloud:masterfrom
Mxiansen:fix/loaders-self-ref-infinite-recursion

Conversation

@Mxiansen

Copy link
Copy Markdown

Related TAPD: https://tapd.woa.com/tapd_fe/10161711/story/detail/1010161711126433671

Background

Some APIs (e.g. billing/CreateGatherRule, billing/CreateAllocationRule, billing/ModifyAllocationRule) declare self-referencing request types, typically AllocationRuleExpression.Children: list<AllocationRuleExpression>.

The current expansion logic in tccli/loaders.py (_get_param_info, _generate_param_skeleton, _get_unfold_param_info) walks the type graph without any cycle detection or depth bound, recursing forever and ending with RecursionError, which breaks:

  • tccli <svc> <action> help
  • tccli <svc> <action> --generate-cli-skeleton
  • tccli <svc> <action> --cli-unfold-argument ...

优化内容

  • _get_param_info: introduce path-level visited frozenset + max_depth=20 fallback; on cycle hit, the node degenerates to a placeholder leaf (members becomes the type-name string/list).
  • _generate_param_skeleton: same protection; emits "RecursiveRef<TypeName>" placeholder so users know to pass the field as a whole JSON via --cli-input-json.
  • _get_unfold_param_info / _recur_get_unfold_param_info: same protection; registers current path as a leaf when a cycle is hit.
  • _filling_unfold_param_info: detects truncated leaves (members is a placeholder string/list rather than dict), marks them type=Object and appends a JSON-input hint to the document.
  • visited is path-scoped (visited | {member} derives a new frozenset on each descent), so sibling fields sharing the same plain struct are not mistakenly truncated.

Compatibility

  • Single-file change: tccli/loaders.py.
  • For non-recursive APIs (the vast majority), output is byte-identical before and after this patch (verified against cvm/RunInstances, cvm/DescribeInstances, billing/DescribeBillSummary, etc.).

Internal MR: https://git.woa.com/tencentcloud-internal/tencentcloud-cli/merge_requests/18

Some APIs (e.g. billing/CreateGatherRule, billing/CreateAllocationRule,
billing/ModifyAllocationRule) declare self-referencing request types,
typically AllocationRuleExpression.Children: list<AllocationRuleExpression>.

The current expansion logic in tccli/loaders.py walks the type graph
without any cycle detection or depth bound, recursing forever and ending
with RecursionError, breaking:
- tccli <svc> <action> help
- tccli <svc> <action> --generate-cli-skeleton
- tccli <svc> <action> --cli-unfold-argument ...

Fix: introduce a path-level visited frozenset plus max_depth=20 fallback
on all three DFS expansion paths. When a cycle is hit (or depth is
exceeded), the node is rendered as a placeholder leaf instead of
recursing further. visited is path-scoped (visited | {member}), so
sibling fields sharing a normal struct are not mistakenly truncated.

For non-recursive APIs the output is byte-identical before/after this
patch (verified against cvm/RunInstances, cvm/DescribeInstances,
billing/DescribeBillSummary).

Related TAPD: https://tapd.woa.com/tapd_fe/10161711/story/detail/1010161711126433671
Internal MR: https://git.woa.com/tencentcloud-internal/tencentcloud-cli/merge_requests/18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant