Skip to content

sdk/python: use typing.List in classes that define a list method - #1477

Open
dwin-gharibi wants to merge 1 commit into
TencentCloud:masterfrom
dwin-gharibi:sdk-python-template-list-shadows-builtin
Open

sdk/python: use typing.List in classes that define a list method#1477
dwin-gharibi wants to merge 1 commit into
TencentCloud:masterfrom
dwin-gharibi:sdk-python-template-list-shadows-builtin

Conversation

@dwin-gharibi

Copy link
Copy Markdown
Contributor

Closes #1476.

Motivation

Template, Sandbox, Volume and Filesystem each define a method named list. Inside a class body the
name list binds to that method, so an annotation written list[TemplateInfo] in the same class refers to
the method, not the builtin. mypy reports Function "...list" is not valid as a type and, more importantly,
stops type-checking those parameters — 10 annotations across two files were effectively Any.

What this changes

Replaces list[...] with typing.List[...] in the four affected modules and adds List to each
from typing import ... line:

file annotations rewritten
cubesandbox/_template.py 11
cubesandbox/sandbox.py 6
cubesandbox/_volume.py 4
cubesandbox/_filesystem.py 2

typing.List is not shadowed by anything, so the annotations resolve for static analysers as well as at
runtime. The public API — including the list method names — is unchanged.

I fixed all four rather than only the two mypy currently flags: _volume.py and _filesystem.py have the
same construct and would start producing the same errors as soon as anything about their annotations
changed.

No comment changes.

Correcting the original report

The issue I filed first claimed this broke typing.get_type_hints at runtime. That was wrong, and I
verified it rather than leaving it in:

MASTER get_type_hints(Template.build) -> OK
MASTER get_type_hints(Template.list)  -> OK
MASTER get_type_hints(Sandbox.list)   -> OK

All four modules use from __future__ import annotations, and get_type_hints evaluates against module
globals rather than the class namespace, so list resolves to the builtin at runtime. The defect is
static-analysis only, and the issue text has been corrected to say so. That also lowers the severity from
what I first suggested.

Testing

The evidence is the mypy count, since the defect is a type-resolution one:

MASTER 'not valid as a type' count: 10
BRANCH 'not valid as a type' count:  0

No behavioural change, so no new tests. Existing suite and lint are unaffected:

$ python3 -m pytest tests -q
225 passed in 0.38s

$ ruff check --select F,E9 cubesandbox
Found 2 errors.        # both pre-existing F401 on master, identical count

CI gates checked locally:

  • pytest — 225 passed (sdk-test-check).
  • ruff — no new findings (the two F401 unused-import errors are present on master too and are not
    touched here).

…shadows builtin

Signed-off-by: Dwin Gharibi <dwin.gharibi@email.kntu.ac.ir>
Copilot AI lite review requested due to automatic review settings August 21, 2026 11:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

created_at: str = ""
finished_at: str = ""
logs: list[str] = field(default_factory=list)
logs: List[str] = field(default_factory=list)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rewrite isn't needed: TemplateBuild (like TemplateInfo) doesn't define a list method, so list[str] here already resolves to the builtin for both mypy and runtime. Only annotations lexically inside Template (which defines list) were affected by the shadowing — the same applies to replicas (line 83) and builds (line 87), which could stay list[...].

Reverting these three keeps the diff focused on the actual defect and consistent with the PEP-585 list[...] style used elsewhere in the same files (_models.py, _commands.py). It also avoids introducing typing.List in scopes where the builtin isn't shadowed, which ruff's UP006 (enabled via select = ["E", "F", "I", "UP"] in sdk/python/pyproject.toml) would flag if a full ruff check is ever run. (Not blocking — the changes are harmless.)



def _serialize_volume_mounts(mounts: VolumeMountsArg) -> list[dict[str, object]]:
def _serialize_volume_mounts(mounts: VolumeMountsArg) -> List[dict[str, object]]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_serialize_volume_mounts is a module-level function, so list[dict[str, object]] here (and the serialized local on line 203) was never affected by the Volume.list shadowing — mypy resolves list to the builtin at module scope. The only annotation in this file that actually needed the fix is the return type of Volume.list (line 379). Consider reverting lines 201 and 203 to list[...] to keep the diff minimal and consistent with the surrounding PEP-585 style.

@cubesandboxbot

Copy link
Copy Markdown

Review: sdk/python: use typing.List in classes that define a list method (#1477)

AI-generated review. Verdict: approve with suggestions — the core fix is correct; a few rewrites are broader than the bug requires.

Summary

The PR fixes a genuine static-analysis defect. In Template, Sandbox, Volume and Filesystem, the class defines a method named list, so mypy resolves the name list in annotations inside that class body to the method rather than the builtin, emitting Function "...list" is not valid as a type and silently degrading those annotations to Any. All four affected modules use from __future__ import annotations, so this is purely a static-analysis problem (as the author correctly notes after correcting their original issue text) — typing.get_type_hints evaluates against module globals and is unaffected. Replacing the shadowed list[...] with typing.List[...] (never shadowed) is the standard, correct workaround, and it is applied consistently to every annotation that is actually affected:

  • sandbox.pySandbox.create(distribution_scope=...), Sandbox.list, list_v2, list_snapshots, clone (return + local sandboxes) — 6 sites, all genuinely affected.
  • _template.pyTemplate.list return + the seven list[...] params of Template.build — 8 sites, all genuinely affected.
  • _filesystem.pyFilesystem.write_files(files=...) and Filesystem.list — 2 sites, genuinely affected.
  • _volume.pyVolume.list return — 1 site genuinely affected.

No behavioral change: annotations are strings under the future import, typing.List resolves at runtime and for get_type_hints, and the public API (including the list methods themselves) is untouched. No test coverage is needed for an annotation-only change, and the repo's CI gate for the Python SDK (sdk-test-check.ymltests/unittest/run_sdk_test.shpytest) is unaffected.

Findings

1. Five rewrites are in scopes where list was never shadowed (low severity, not blocking).

  • sdk/python/cubesandbox/_template.py:44 (TemplateBuild.logs), :83 (TemplateInfo.replicas), :87 (TemplateInfo.builds) — these dataclasses do not define a list method, so list[...] there resolved to the builtin and produced no mypy error.
  • sdk/python/cubesandbox/_volume.py:201 (_serialize_volume_mounts return) and :203 (the serialized local) — module-level function, list resolves to the builtin at module scope.

The PR body's rationale for the file-level sweep ("_volume.py and _filesystem.py have the same construct and would start producing the same errors") is accurate for the methods in those files, but it does not cover dataclass fields or module-level functions. These five sites could stay list[...]: they are unrelated to the shadowing, and keeping them as list[...] preserves the PEP-585 style used throughout the same files (_models.py, _commands.py) and avoids typing.List in scopes where ruff UP006 would flag it. Note the repo's pyproject.toml selects the UP rule group, and _policy.py already contains typing.List/typing.Optional in non-shadowed scopes, so this is a consistency/focus nit rather than a CI breaker.

2. Local verification claim uses a narrower lint selection than the project config (informational).

The PR states "ruff — no new findings" based on ruff check --select F,E9. The project config (sdk/python/pyproject.toml) selects E, F, I, UP; UP006 is not exercised by the author's command. Combined with finding 1, a full ruff check on the branch may report new UP006 diagnostics on the five non-shadowed sites. No ruff/mypy CI gate exists for the Python SDK today, so this does not fail CI.

Minor notes

  • typing.List is deprecated per PEP 585; as a workaround for the shadowing it is fine (and consistent with _policy.py), but it would be preferable to confine it to the 17 genuinely affected sites.
  • The PR description says "No comment changes", but sdk/python/cubesandbox/_volume.py:247 (# list[VolumeInfo]# List[VolumeInfo] in the class docstring) is a comment change. Trivial/cosmetic — flagged only for accuracy.

No correctness, security, or runtime-behavior issues found.

@wbzdssm

wbzdssm commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Thank you for your PR. Could you please provide more details about the test results?

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.

[Bug Report] Classes with a list method shadow the builtin in their own annotations, so mypy cannot check those parameters

3 participants