Skip to content

geo_utils imports aiohttp unconditionally, breaking every aiohttp-free install #16

Description

@MugiwaraNoSeva

Repo: VAST-AI-Research/tripo-python-sdk · Version: 0.3.6

Summary

tripo3d/geo_utils.py imports aiohttp at module top level. The rest of the SDK
treats aiohttp as optional — client_impl/__init__.py uses find_spec and falls
back to LegacyClientImpl (raw sockets) when it is missing. That fallback is
defeated by geo_utils, because TripoClient.get_task() does:

from .geo_utils import get_china_mainland_status   # client.py:111

On any environment without aiohttp, this raises ModuleNotFoundError: No module named 'aiohttp' on the first task poll. create_task() succeeds, so tasks are
created and credits are consumed, but the client can never observe or download the
result.

This makes the SDK unusable inside Blender, which is where the official
tripo-3d-for-blender addon runs it. Blender's bundled Python does not ship
aiohttp and users cannot easily add it.

Reproduction

With Blender 4.5's bundled Python (no aiohttp present):

from tripo3d import TripoClient
# find_spec('aiohttp') -> False, LegacyClientImpl selected correctly
task_id = await client.text_to_model(prompt="a cube")   # OK, credits charged
await client.get_task(task_id)                          # ModuleNotFoundError

Via the Blender addon, the user-visible symptom is a dialog reading
Error downloading model: No module named 'aiohttp' after a successful submission.

Suggested fix

Make the import optional, matching how the rest of the SDK already treats it:

try:
    import aiohttp
except ImportError:
    aiohttp = None

and short-circuit _detect_via_api() when aiohttp is None. The DNS-based
fallback in _detect_via_dns() needs no changes, so geo detection keeps working in
degraded form rather than taking down the whole client.

Verified with Blender 4.5's Python: with those two changes the import chain
resolves, ClientImpl is LegacyClientImpl, and task polling and download both
complete normally.

Second, related issue: download failures are silently swallowed

client.py:286 in download_task_models():

download_results = await asyncio.gather(*download_coroutines, return_exceptions=True)
...
if isinstance(download_result, Exception):
    result[model_type] = None

Any download error becomes None with no logging and no re-raise. Callers that do
next(iter(result.values())) then receive None and fail far from the real cause —
in the Blender addon this surfaced as a completely silent no-op: no model, no error
dialog, no log entry.

Consider re-raising, or at minimum logging the exception, so failures are
diagnosable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions