Files
pack/core/providers/python/python_test.go
T
86314dc9d8 fix: avoid apt package when psycopg-binary is used (#379)
* feat: detect psycopg[binary] and skip apt packages

When using psycopg2-binary or psycopg[binary], the PostgreSQL client
libraries (libpq-dev, libpq5) are not needed because these variants
ship with pre-compiled binaries. This change:

- Adds usesBinaryPsycopg() to detect binary variants
- Updates usesPostgres() to return false when binary variants are used
- Skips libpq-dev (build) and libpq5 (runtime) apt package installation
- Adds comprehensive unit tests for binary psycopg detection

This reduces image size and build time for projects using binary variants.

* test: add psycopg[binary] integration test

Adds a dedicated test example for psycopg[binary] to verify that the
bracket syntax for optional dependencies is correctly detected. This
ensures the binary detection works for both psycopg2-binary and
psycopg[binary] variants.

Test coverage now includes:
- psycopg2-binary (existing python-system-deps example)
- psycopg[binary] (new python-psycopg-binary example)
- psycopg non-binary (existing python-latest-psycopg example)
- psycopg2 non-binary (existing python-django example)

* test: snapshot update

* test: add binary pyscogp test

* test: ensure libpq is installed for pyscog operation

* build: add helper for running the current dir tests

* test: check to make sure the libpg library is not installed when a binary postgres connection is requested

* test: update snapshot

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-01-15 11:32:30 -07:00

135 lines
2.6 KiB
Go

package python
import (
"testing"
"github.com/stretchr/testify/require"
testingUtils "github.com/railwayapp/railpack/core/testing"
)
func TestDetect(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{
name: "pip",
path: "../../../examples/python-pip",
want: true,
},
{
name: "poetry",
path: "../../../examples/python-poetry",
want: true,
},
{
name: "pdm",
path: "../../../examples/python-pdm",
want: true,
},
{
name: "uv",
path: "../../../examples/python-uv",
want: true,
},
{
name: "bot.py only",
path: "../../../examples/python-bot-only",
want: true,
},
{
name: "no python",
path: "../../../examples/go-mod",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := PythonProvider{}
got, err := provider.Detect(ctx)
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
func TestUsesBinaryPsycopg(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{
name: "psycopg2-binary",
path: "../../../examples/python-system-deps",
want: true,
},
{
name: "psycopg[binary]",
path: "../../../examples/python-psycopg-binary",
want: true,
},
{
name: "psycopg (non-binary)",
path: "../../../examples/python-latest-psycopg",
want: false,
},
{
name: "psycopg2 (django)",
path: "../../../examples/python-django",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := PythonProvider{}
got := provider.usesBinaryPsycopg(ctx)
require.Equal(t, tt.want, got)
})
}
}
func TestUsesPostgres(t *testing.T) {
tests := []struct {
name string
path string
want bool
}{
{
name: "psycopg2-binary should not need apt packages",
path: "../../../examples/python-system-deps",
want: false,
},
{
name: "psycopg[binary] should not need apt packages",
path: "../../../examples/python-psycopg-binary",
want: false,
},
{
name: "psycopg (non-binary) needs apt packages",
path: "../../../examples/python-latest-psycopg",
want: true,
},
{
name: "psycopg2 (django) needs apt packages",
path: "../../../examples/python-django",
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := PythonProvider{}
got := provider.usesPostgres(ctx)
require.Equal(t, tt.want, got)
})
}
}