feat(python): Scan nested dependency files in usesDep (#457)

* feat(python): Scan nested dependency files in usesDep

* snapshot

* remove readme

* use single brace-expanded glob instead of three separate globs
This commit is contained in:
Ray Chen
2026-02-12 07:30:43 +08:00
committed by GitHub
parent 0990f0df18
commit a66d8d94b5
9 changed files with 296 additions and 2 deletions
@@ -0,0 +1,195 @@
{
"caches": {
"apt": {
"directory": "/var/cache/apt",
"type": "locked"
},
"apt-lists": {
"directory": "/var/lib/apt/lists",
"type": "locked"
},
"uv": {
"directory": "/opt/uv-cache",
"type": "shared"
}
},
"deploy": {
"base": {
"step": "packages:apt:runtime"
},
"inputs": [
{
"include": [
"/mise/shims",
"/mise/installs",
"/usr/local/bin/mise",
"/etc/mise/config.toml",
"/root/.local/state/mise"
],
"step": "packages:mise"
},
{
"include": [
"/app/.venv"
],
"step": "build"
},
{
"exclude": [
".venv"
],
"include": [
"."
],
"step": "build"
}
],
"startCommand": "python main.py",
"variables": {
"PIP_DEFAULT_TIMEOUT": "100",
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
"PYTHONDONTWRITEBYTECODE": "1",
"PYTHONFAULTHANDLER": "1",
"PYTHONHASHSEED": "random",
"PYTHONUNBUFFERED": "1"
}
},
"steps": [
{
"caches": [
"apt",
"apt-lists"
],
"commands": [
{
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev'",
"customName": "install apt packages: libpq-dev"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:apt:build"
},
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "mise install",
"customName": "install mise packages: python, uv"
}
],
"inputs": [
{
"step": "packages:apt:build"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_NODE_VERIFY": "false",
"MISE_PARANOID": "1",
"MISE_PYTHON_COMPILE": "false",
"MISE_SHIMS_DIR": "/mise/shims",
"MISE_TRUSTED_CONFIG_PATHS": "/app"
}
},
{
"caches": [
"uv"
],
"commands": [
{
"path": "/root/.local/bin"
},
{
"path": "/app/.venv/bin"
},
{
"cmd": "uv sync --locked --no-dev --no-install-project"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"include": [
"."
],
"local": true
}
],
"name": "install",
"variables": {
"PIP_DEFAULT_TIMEOUT": "100",
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
"PYTHONDONTWRITEBYTECODE": "1",
"PYTHONFAULTHANDLER": "1",
"PYTHONHASHSEED": "random",
"PYTHONUNBUFFERED": "1",
"UV_CACHE_DIR": "/opt/uv-cache",
"UV_COMPILE_BYTECODE": "1",
"UV_LINK_MODE": "copy",
"UV_PYTHON_DOWNLOADS": "never",
"VIRTUAL_ENV": "/app/.venv"
}
},
{
"commands": [
{
"cmd": "uv sync --locked --no-dev --no-editable"
}
],
"inputs": [
{
"step": "install"
},
{
"include": [
"."
],
"local": true
}
],
"name": "build",
"secrets": [
"*"
]
},
{
"caches": [
"apt",
"apt-lists"
],
"commands": [
{
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq5'",
"customName": "install apt packages: libpq5"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
}
],
"name": "packages:apt:runtime"
}
]
}
+5 -2
View File
@@ -465,9 +465,12 @@ func (p *PythonProvider) addMetadata(ctx *generate.GenerateContext) {
}
func (p *PythonProvider) usesDep(ctx *generate.GenerateContext, dep string) bool {
for _, file := range []string{"requirements.txt", "pyproject.toml", "Pipfile"} {
files, err := ctx.App.FindFiles("**/{requirements.txt,pyproject.toml,Pipfile}")
if err != nil {
return false
}
for _, file := range files {
if contents, err := ctx.App.ReadFile(file); err == nil {
// TODO: Do something better than string comparison
if strings.Contains(strings.ToLower(contents), strings.ToLower(dep)) {
return true
}
+10
View File
@@ -83,6 +83,11 @@ func TestUsesBinaryPsycopg(t *testing.T) {
path: "../../../examples/python-django",
want: false,
},
{
name: "psycopg2 in workspace sub-package (non-binary)",
path: "../../../examples/python-uv-workspace-postgres",
want: false,
},
}
for _, tt := range tests {
@@ -121,6 +126,11 @@ func TestUsesPostgres(t *testing.T) {
path: "../../../examples/python-django",
want: true,
},
{
name: "psycopg2 in workspace sub-package needs apt packages",
path: "../../../examples/python-uv-workspace-postgres",
want: true,
},
}
for _, tt := range tests {
@@ -0,0 +1,12 @@
[project]
name = "db-package"
version = "0.1.0"
description = "Add your description here"
requires-python = ">=3.13"
dependencies = [
"psycopg2>=2.9",
]
[build-system]
requires = ["uv_build>=0.8.11,<0.9.0"]
build-backend = "uv_build"
@@ -0,0 +1,2 @@
def get_connection_string():
return "postgresql://localhost/test"
@@ -0,0 +1,9 @@
from db_package import get_connection_string
def main():
print(f"Connection: {get_connection_string()}", end="")
if __name__ == "__main__":
main()
@@ -0,0 +1,17 @@
[project]
name = "python-uv-workspace-postgres"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"db-package",
]
[tool.uv.workspace]
members = [
"db-package",
]
[tool.uv.sources]
db-package = { workspace = true }
@@ -0,0 +1,5 @@
[
{
"justBuild": true
}
]
+41
View File
@@ -0,0 +1,41 @@
version = 1
revision = 3
requires-python = ">=3.13"
[manifest]
members = [
"db-package",
"python-uv-workspace-postgres",
]
[[package]]
name = "db-package"
version = "0.1.0"
source = { editable = "db-package" }
dependencies = [
{ name = "psycopg2" },
]
[package.metadata]
requires-dist = [{ name = "psycopg2", specifier = ">=2.9" }]
[[package]]
name = "psycopg2"
version = "2.9.11"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/89/8d/9d12bc8677c24dad342ec777529bce705b3e785fa05d85122b5502b9ab55/psycopg2-2.9.11.tar.gz", hash = "sha256:964d31caf728e217c697ff77ea69c2ba0865fa41ec20bb00f0977e62fdcc52e3", size = 379598, upload-time = "2025-10-10T11:14:46.075Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5a/18c8cb13fc6908dc41a483d2c14d927a7a3f29883748747e8cb625da6587/psycopg2-2.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:8dc379166b5b7d5ea66dcebf433011dfc51a7bb8a5fc12367fa05668e5fc53c8", size = 2714048, upload-time = "2025-10-10T11:10:19.816Z" },
{ url = "https://files.pythonhosted.org/packages/47/08/737aa39c78d705a7ce58248d00eeba0e9fc36be488f9b672b88736fbb1f7/psycopg2-2.9.11-cp314-cp314-win_amd64.whl", hash = "sha256:f10a48acba5fe6e312b891f290b4d2ca595fc9a06850fe53320beac353575578", size = 2803738, upload-time = "2025-10-10T11:10:23.196Z" },
]
[[package]]
name = "python-uv-workspace-postgres"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "db-package" },
]
[package.metadata]
requires-dist = [{ name = "db-package", editable = "db-package" }]