Skip to content

Bug: PostgresContainer().get_connection_url(driver=None) does not function as documented #587

@oliverlambson

Description

@oliverlambson

Describe the bug

get_connection_url(driver=None) should return a connection string starting postgresql://..., but actually returns postgresql+None://...

This is not inline with the documented intention:

        If a driver is set in the constructor (defaults to psycopg2!), the URL will contain the
        driver. The optional driver argument to :code:`get_connection_url` overwrites the constructor
        set value. Pass :code:`driver=None` to get URLs without a driver.

To Reproduce

$ python <<EOF
from testcontainers.postgres import PostgresContainer
postgres = PostgresContainer("postgres:16")
postgres.start()
print(f"{postgres.get_connection_url(driver=None)=}")
EOF

WARNING:root:DOCKER_AUTH_CONFIG is experimental, see testcontainers/testcontainers-python#566
Pulling image testcontainers/ryuk:0.7.0
INFO:testcontainers.core.container:Pulling image testcontainers/ryuk:0.7.0
Container started: 2d9d0ae2c1f5
INFO:testcontainers.core.container:Container started: 2d9d0ae2c1f5
Waiting for container <Container: 2d9d0ae2c1f5> with image testcontainers/ryuk:0.7.0 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: 2d9d0ae2c1f5> with image testcontainers/ryuk:0.7.0 to be ready ...
Pulling image postgres:16
INFO:testcontainers.core.container:Pulling image postgres:16
Container started: 2dba2ba8e9ec
INFO:testcontainers.core.container:Container started: 2dba2ba8e9ec
Waiting for container <Container: 2dba2ba8e9ec> with image postgres:16 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: 2dba2ba8e9ec> with image postgres:16 to be ready ...
Waiting for container <Container: 2dba2ba8e9ec> with image postgres:16 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: 2dba2ba8e9ec> with image postgres:16 to be ready ...
postgres.get_connection_url(driver=None)='postgresql+None://test:test@localhost:32776/test'

It does work if driver=None is passed to the constructor. I find this unintuitive.

python <<EOF 
from testcontainers.postgres import PostgresContainer
postgres = PostgresContainer("postgres:16", driver=None)
postgres.start()
print(f"{postgres.get_connection_url()=}")
EOF

WARNING:root:DOCKER_AUTH_CONFIG is experimental, see testcontainers/testcontainers-python#566
Pulling image testcontainers/ryuk:0.7.0
INFO:testcontainers.core.container:Pulling image testcontainers/ryuk:0.7.0
Container started: 4a0e020f0691
INFO:testcontainers.core.container:Container started: 4a0e020f0691
Waiting for container <Container: 4a0e020f0691> with image testcontainers/ryuk:0.7.0 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: 4a0e020f0691> with image testcontainers/ryuk:0.7.0 to be ready ...
Pulling image postgres:16
INFO:testcontainers.core.container:Pulling image postgres:16
Container started: ce239a341dab
INFO:testcontainers.core.container:Container started: ce239a341dab
Waiting for container <Container: ce239a341dab> with image postgres:16 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: ce239a341dab> with image postgres:16 to be ready ...
Waiting for container <Container: ce239a341dab> with image postgres:16 to be ready ...
INFO:testcontainers.core.waiting_utils:Waiting for container <Container: ce239a341dab> with image postgres:16 to be ready ...
postgres.get_connection_url()='postgresql://test:test@localhost:32776/test'

Runtime environment

Provide a summary of your runtime environment. Which operating system, python version, and docker version are you using? What is the version of testcontainers-python you are using? You can run the following commands to get the relevant information.

# Get the operating system information (on a unix os).
$ uname -a
Darwin ip-... 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:11:08 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T8122 arm64

# Get the python version.
$ python --version
Python 3.11.9

# Get the docker version and other docker information.
$ docker info
Client:
 Version:    25.0.5
 Context:    orbstack
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.13.1
    Path:     /Users/oliverlambson/.docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.24.5
    Path:     /Users/oliverlambson/.docker/cli-plugins/docker-compose

# Get all python packages.
$ pip freeze
certifi==2024.2.2
charset-normalizer==3.3.2
docker==7.1.0
idna==3.7
requests==2.32.2
testcontainers==4.5.0
typing_extensions==4.12.0
urllib3==2.2.1
wrapt==1.16.0

This is either a documentation issue (it does work if driver=None is passed to the constructor) or it can be handled in code, so that the driver can be overridden by the method in this line:

-         driver_str = self.driver if driver is _UNSET else f"+{driver}"
+         driver_str = f"+{driver}" if driver not in [_UNSET, None] else self.driver

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