Bug: PostgresContainer().get_connection_url(driver=None) does not function as documented
envgap__testcontainers__testcontainers-python-587
01 / FAILURE SIGNATURE
As reported upstream
No identifying execution failure has been captured.
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
4766e4829407c19de039effc7ea8fcc8b6dcc214- Manifest
pyproject.toml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / ORIGINAL ISSUE TEXT
testcontainers/testcontainers-python #587 · read the original issue
**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**
```bash
$ 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.
```bash
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.
```bash
# 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](https://github.com/testcontainers/testcontainers-python/blob/111bd094428b83233d7eca693d94e10b34ee8ae8/modules/postgres/testcontainers/postgres/__init__.py#L82):
```diff
- driver_str = self.driver if driver is _UNSET else f"+{driver}"
+ driver_str = f"+{driver}" if driver not in [_UNSET, None] else self.driver
```04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]