Skip to content

Falsy custom transports are silently replaced by default transports #3092

Description

@adamtheturtle

Summary

All six client constructors select their transport using transport or DefaultTransport(). An explicitly supplied transport whose truth value is false is therefore ignored, even though it is not None.

Affected clients:

  • VWS
  • CloudRecoService
  • VuMarkService
  • AsyncVWS
  • AsyncCloudRecoService
  • AsyncVuMarkService

This can affect valid transport implementations that define __bool__ or __len__. More seriously, silently replacing a test/offline transport can cause an unexpected real network request.

Reproducer

from vws import VWS
from vws.response import Response

class FalsyTransport:
    def __bool__(self) -> bool:
        return False

    def close(self) -> None:
        pass

    def __call__(self, *, method, url, headers, data, request_timeout):
        return Response(
            text="{}",
            url=url,
            status_code=200,
            headers={},
            request_body=data,
            tell_position=0,
            content=b"",
        )

transport = FalsyTransport()
client = VWS(
    server_access_key="access",
    server_secret_key="secret",
    transport=transport,
)

assert client._transport is transport
# Actual type: RequestsTransport

Async transports with the equivalent aclose/async __call__ behavior are replaced by AsyncHTTPXTransport.

Expected behavior

Only None should select the default transport, for example:

self._transport = transport if transport is not None else RequestsTransport()

Tests should cover a falsy protocol-conforming transport for each sync and async constructor.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions