Shared Packages Management Strategy
Status: Analysis & Recommendations Last Updated: 2025-10-25 Purpose: Eliminate "module not found" errors across local, Docker, and Azure ACR deployments Related Docs: Azure Deployment Architecture
Executive Summary
This document analyzes the recurring "module not found" issues for shared packages (loan_defenders_models and loan_defenders_utils) across different deployment environments and provides best practices to ensure consistent, reliable imports.
Current Status: Packages use uv workspace with editable installs locally, multi-stage Docker builds with PYTHONPATH, and potential ACR build context issues.
Root Cause: Inconsistent package installation strategies across environments (editable installs vs. regular installs, PYTHONPATH dependency, build context variations).
Recommended Solution: Standardize on proper Python package installation with consistent patterns across all environments, eliminate PYTHONPATH dependency.
Table of Contents
- Current Architecture Analysis
- Root Causes of Module Not Found
- Environment-Specific Issues
- Best Practices Comparison
- Recommended Strategy
- Implementation Plan
- Verification Checklist
Current Architecture Analysis
Package Structure
loan-defenders/
├── pyproject.toml # Workspace root configuration
├── uv.lock # Lock file for all dependencies
├── loan_defenders_models/ # Shared domain models
│ ├── pyproject.toml # Package configuration
│ ├── __init__.py
│ ├── application.py
│ ├── assessment.py
│ ├── decision.py
│ └── responses.py
├── loan_defenders_utils/ # Shared utilities
│ ├── pyproject.toml # Package configuration
│ ├── __init__.py
│ ├── azure_credential.py
│ ├── mcp_config.py
│ ├── mcp_transport.py
│ └── observability.py
└── apps/
├── api/ # FastAPI application
│ ├── pyproject.toml
│ └── loan_defenders/
├── ui/ # React frontend
└── mcp_servers/ # MCP server implementations
├── application_verification/
├── document_processing/
└── financial_calculations/
Current Configuration (Root pyproject.toml)
Workspace Setup:
[tool.uv.workspace]
members = [
"apps/api",
"loan_defenders_models",
"loan_defenders_utils",
"apps/mcp_servers/application_verification",
"apps/mcp_servers/document_processing",
"apps/mcp_servers/financial_calculations",
]
[tool.uv.sources]
loan-defenders-utils = { workspace = true }
loan-defenders-models = { workspace = true }
Dependencies:
Package Configuration (loan_defenders_models/pyproject.toml)
[project]
name = "loan-defenders-models"
version = "0.1.0"
description = "Shared business domain models for Loan Defenders multi-agent system"
requires-python = ">=3.10"
dependencies = [
"pydantic>=2.5.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["."]
[tool.hatch.build.targets.editable]
packages = ["."]
Issue Identified: Using flat layout (packages = ["."]) which can cause issues with package discovery.
Current Dockerfile Pattern (apps/api/Dockerfile)
# Stage 1: Builder
FROM python:3.11-slim AS builder
WORKDIR /app
# Copy workspace files
COPY pyproject.toml uv.lock ./
# Copy shared packages first
COPY loan_defenders_models ./loan_defenders_models
COPY loan_defenders_utils ./loan_defenders_utils
# Copy API package config
COPY apps/api/pyproject.toml ./apps/api/
# Install dependencies
RUN uv sync --frozen --no-dev --package loan-defenders-api
# Stage 2: Runtime
FROM python:3.11-slim
WORKDIR /app
# Copy venv and shared packages
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app/loan_defenders_models /app/loan_defenders_models
COPY --from=builder /app/loan_defenders_utils /app/loan_defenders_utils
# Copy application code
COPY apps/api/loan_defenders ./loan_defenders
# Set PATH and PYTHONPATH
ENV PATH="/app/.venv/bin:$PATH" \
PYTHONPATH="/app"
# Run application
CMD ["uvicorn", "loan_defenders.api.app:app", "--host", "0.0.0.0", "--port", "8000"]
Key Observation: Relies on PYTHONPATH=/app to make shared packages importable.
Root Causes of Module Not Found
1. PYTHONPATH Dependency (High Risk)
Problem: Current Docker setup depends on PYTHONPATH=/app environment variable.
Why This Is Fragile: - PYTHONPATH is not always respected (depends on how Python is invoked) - Can be overridden by other tools or configurations - Not standard Python packaging practice - Doesn't work in all execution contexts (e.g., some CI/CD runners)
Symptom:
Root Cause: Packages not installed into Python's site-packages, relying on PYTHONPATH hack.
2. Inconsistent Installation Methods
Problem: Different installation methods across environments.
| Environment | Installation Method | Result |
|---|---|---|
| Local Development | uv sync (editable install) |
Works with workspace |
| Docker Builder | uv sync --frozen --no-dev |
May or may not install shared packages |
| Docker Runtime | COPY + PYTHONPATH | Not properly installed |
| Azure ACR Build | az acr build with context |
Build context may be incomplete |
Root Cause: Shared packages not installed as proper dependencies in runtime environment.
3. Flat Layout Package Structure
Problem: Using packages = ["."] in hatch configuration.
Issue: This tells the build system to treat the package root as the package itself, which can confuse package discovery.
Better Approach: Use src layout or explicit package naming.
4. Azure ACR Build Context
Problem: When running az acr build, the build context might not include shared packages.
Example:
# This might fail if run from apps/api/
az acr build --registry myacr --image api:latest --file Dockerfile .
# Because Dockerfile expects:
COPY loan_defenders_models ./loan_defenders_models
# But loan_defenders_models is not in apps/api/, it's in repo root
Root Cause: Build context is limited to specified directory, doesn't include repo root.
5. Editable Install Confusion
Problem: uv sync in workspace creates editable installs locally, but Docker doesn't use editable installs.
Local (works):
$ uv sync
# Creates editable links in .venv/lib/python3.11/site-packages/
# loan_defenders_models.pth → points to /workspaces/loan-defenders/loan_defenders_models
Docker (doesn't work same way):
RUN uv sync --frozen --no-dev --package loan-defenders-api
# Installs loan-defenders-api and its dependencies
# But shared packages might not be in site-packages properly
Root Cause: Workspace editable installs don't translate directly to Docker isolated builds.
Environment-Specific Issues
Local Development
Current Approach: uv sync with workspace configuration.
Status: ✅ Generally works
Why It Works: - Editable installs via workspace - Packages linked from repo root - PYTHONPATH handled by uv/IDE
Potential Issues:
- New developers might forget to run uv sync
- IDE might not recognize workspace packages immediately
- PYTHONPATH environment variable conflicts
Symptom:
$ python -c "import loan_defenders_models"
ModuleNotFoundError: No module named 'loan_defenders_models'
# Even though uv sync was run
Fix Required: Ensure proper package installation, not just editable links.
Docker Builds (Local)
Current Approach: Multi-stage build with COPY + PYTHONPATH.
Status: ⚠️ Works but fragile
Why It's Fragile: - Depends on PYTHONPATH environment variable - Shared packages not in site-packages - No proper installation of shared packages in venv
Symptom:
# In container:
$ python -c "import loan_defenders_models"
# Works if PYTHONPATH=/app is set
# Fails if PYTHONPATH is unset or overridden
Issue:
# If running Python differently:
$ cd /app
$ python -m uvicorn loan_defenders.api.app:app
# Might fail because uvicorn resets PYTHONPATH in some contexts
Fix Required: Install shared packages into venv during build stage.
Docker Builds (Azure ACR)
Current Approach: az acr build from repository root or subdirectory.
Status: ❌ High risk of failure
Potential Issues:
Issue 1: Build Context Location
# If deploying from subdirectory:
$ cd apps/api
$ az acr build --registry myacr --file Dockerfile .
# Dockerfile expects:
COPY loan_defenders_models ./loan_defenders_models # ← Not in current directory!
Issue 2: Missing Lock File
Issue 3: Workspace Resolution
# ACR build happens in isolation
# Workspace references like { workspace = true } don't work
# Because ACR doesn't understand monorepo structure
Fix Required: Ensure ACR builds run from repository root with full context.
Azure Container Instances (ACI) / Container Apps
Current Approach: Pull pre-built images from ACR, run with environment variables.
Status: ⚠️ Depends on image quality
Potential Issues: - If image wasn't built correctly (wrong context), runtime fails - PYTHONPATH might be overridden by orchestrator - No way to fix after deployment (need to rebuild image)
Symptom:
Fix Required: Ensure images have properly installed packages.
Best Practices Comparison
Option 1: PYTHONPATH + COPY (Current - Not Recommended)
Approach: Copy shared package source, set PYTHONPATH.
Pros: - ✅ Simple to implement - ✅ Fast builds (no installation overhead)
Cons: - ❌ Fragile (PYTHONPATH can be overridden) - ❌ Not standard Python practice - ❌ Doesn't work in all contexts - ❌ Hard to debug when it fails - ❌ Not portable across environments
Verdict: ❌ Avoid - This is the source of current issues.
Option 2: Local Package Install (Recommended)
Approach: Install shared packages as proper Python packages in builder stage.
Pattern:
# Stage 1: Builder
FROM python:3.11-slim AS builder
WORKDIR /build
# Copy workspace files
COPY pyproject.toml uv.lock ./
# Copy shared packages with their pyproject.toml files
COPY loan_defenders_models/ ./loan_defenders_models/
COPY loan_defenders_utils/ ./loan_defenders_utils/
# Copy application package config
COPY apps/api/ ./apps/api/
# Install all dependencies INCLUDING shared packages into venv
# uv workspace will resolve and install shared packages properly
RUN uv sync --frozen --no-dev --package loan-defenders-api
# Stage 2: Runtime
FROM python:3.11-slim
WORKDIR /app
# Copy ONLY the venv (shared packages are now inside it!)
COPY --from=builder /build/.venv /app/.venv
# Copy ONLY application code (NOT shared packages - they're in venv)
COPY apps/api/loan_defenders ./loan_defenders
# No PYTHONPATH needed - packages in site-packages!
ENV PATH="/app/.venv/bin:$PATH"
CMD ["uvicorn", "loan_defenders.api.app:app", "--host", "0.0.0.0", "--port", "8000"]
Pros: - ✅ Standard Python packaging - ✅ Shared packages in venv/site-packages - ✅ No PYTHONPATH needed - ✅ Works in all contexts - ✅ Proper dependency resolution - ✅ Easy to debug
Cons: - ⚠️ Slightly longer build time (install overhead) - ⚠️ Requires proper package configuration
Verdict: ✅ Recommended - Standard, reliable, portable.
Option 3: Multi-Repo with Published Packages (Future Consideration)
Approach: Publish shared packages to private PyPI or Azure Artifacts.
Pattern:
# Publish shared packages
$ cd loan_defenders_models
$ uv build
$ uv publish --repository private-pypi
# In application Dockerfile
FROM python:3.11-slim
RUN pip install --index-url https://private-pypi.example.com loan-defenders-models loan-defenders-utils
Pros: - ✅ Clean separation of concerns - ✅ Versioned dependencies - ✅ Can upgrade shared packages independently - ✅ Standard enterprise pattern
Cons: - ❌ Requires private package registry - ❌ More infrastructure to maintain - ❌ Versioning overhead - ❌ Overkill for current project size
Verdict: 🟡 Future - Consider when team grows or packages become stable APIs.
Option 4: Git Submodules (Not Recommended for Python)
Approach: Use git submodules for shared code.
Verdict: ❌ Avoid - Adds Git complexity, doesn't solve Python import issues.
Recommended Strategy
Strategy: Proper Workspace Package Installation
Goal: Install shared packages into venv/site-packages in all environments, eliminate PYTHONPATH dependency.
Key Principles: 1. Shared packages are proper Python packages (with pyproject.toml) 2. All environments install packages the same way (via uv/pip) 3. No PYTHONPATH hacks - use site-packages 4. Build from repository root - ensure full context
Implementation Approach
1. Package Configuration Fix
Current Issue: Flat layout with packages = ["."]
Recommendation: Use explicit package specification or src layout.
Option A: Explicit Package Name (Simpler)
# loan_defenders_models/pyproject.toml
[tool.hatch.build.targets.wheel]
packages = ["loan_defenders_models"] # Explicit package name
[tool.hatch.build.targets.editable]
packages = ["loan_defenders_models"]
Option B: Src Layout (More Standard)
loan_defenders_models/
├── pyproject.toml
└── src/
└── loan_defenders_models/
├── __init__.py
├── application.py
└── ...
Verdict: Use Option A for minimal changes, Option B for long-term maintainability.
2. Dockerfile Pattern Update
Principle: Install shared packages into venv, don't copy as source + PYTHONPATH.
Updated Pattern:
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Stage 1: Builder - Install ALL dependencies including shared packages
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FROM python:3.11-slim AS builder
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /build
# Copy workspace configuration first
COPY pyproject.toml uv.lock ./
# Copy shared packages WITH their pyproject.toml files
COPY loan_defenders_models/ ./loan_defenders_models/
COPY loan_defenders_utils/ ./loan_defenders_utils/
# Copy application package configuration
COPY apps/api/pyproject.toml apps/api/README.md ./apps/api/
# Install dependencies
# This will install:
# 1. loan-defenders-models into .venv/lib/python3.11/site-packages/
# 2. loan-defenders-utils into .venv/lib/python3.11/site-packages/
# 3. loan-defenders-api dependencies
RUN uv sync --frozen --no-dev --package loan-defenders-api
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Stage 2: Runtime - Copy venv (includes shared packages), no PYTHONPATH
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Install runtime dependencies (curl for healthcheck)
RUN apt-get update && apt-get install -y curl && apt-get clean && rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN useradd -m -u 1000 apiuser
WORKDIR /app
# Copy venv from builder (includes installed shared packages!)
COPY --from=builder --chown=apiuser:apiuser /build/.venv /app/.venv
# Copy ONLY application code
COPY --chown=apiuser:apiuser apps/api/loan_defenders ./loan_defenders
# Switch to non-root user
USER apiuser
# Add venv to PATH (NO PYTHONPATH needed!)
ENV PATH="/app/.venv/bin:$PATH"
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "loan_defenders.api.app:app", "--host", "0.0.0.0", "--port", "8000"]
Key Changes:
- ✅ Shared packages copied WITH pyproject.toml in builder
- ✅ uv sync installs shared packages into venv/site-packages
- ✅ Runtime copies ONLY venv (shared packages inside it)
- ✅ NO copying of shared package source in runtime stage
- ✅ NO PYTHONPATH environment variable
- ✅ Standard Python import mechanism
3. Azure ACR Build Pattern
Problem: ACR builds need full repository context.
Solution: Always build from repository root with proper context.
Deployment Script Pattern:
# infrastructure/scripts/build-images.sh
#!/bin/bash
set -e
ACR_NAME="$1"
IMAGE_TAG="${2:-latest}"
echo "Building images in Azure Container Registry: $ACR_NAME"
# CRITICAL: Build from repository root with full context
cd "$(git rev-parse --show-toplevel)"
# Build API image
echo "Building loan-defenders-api..."
az acr build \
--registry "$ACR_NAME" \
--image "loan-defenders-api:$IMAGE_TAG" \
--file "apps/api/Dockerfile" \
. # ← Build context is repo root!
# Build MCP servers
for server in application_verification document_processing financial_calculations; do
echo "Building mcp-$server..."
az acr build \
--registry "$ACR_NAME" \
--image "mcp-$server:$IMAGE_TAG" \
--file "apps/mcp_servers/$server/Dockerfile" \
. # ← Build context is repo root!
done
echo "✅ All images built successfully"
Key Points:
- ✅ Always run from repository root
- ✅ Build context is . (repo root)
- ✅ Dockerfile path is relative: apps/api/Dockerfile
- ✅ Full context includes: pyproject.toml, uv.lock, shared packages
4. Local Development Setup
Goal: Ensure local development matches Docker behavior.
Setup Script (scripts/setup-dev-environment.sh):
#!/bin/bash
set -e
echo "Setting up Loan Defenders development environment..."
# Ensure we're in repo root
cd "$(git rev-parse --show-toplevel)"
# Install all workspace dependencies
echo "Installing dependencies with uv..."
uv sync
# Verify shared packages are importable
echo "Verifying shared packages installation..."
uv run python -c "import loan_defenders_models; import loan_defenders_utils; print('✅ Shared packages imported successfully')"
echo ""
echo "✅ Development environment ready!"
echo ""
echo "Next steps:"
echo " 1. Configure environment: cp .env.example .env"
echo " 2. Start services: uv run uvicorn apps.api.loan_defenders.api.app:app --reload"
Verification:
# Test imports work without PYTHONPATH
$ uv run python -c "import loan_defenders_models"
# Should succeed
# Inspect where package is installed
$ uv run python -c "import loan_defenders_models; print(loan_defenders_models.__file__)"
# Should show: .venv/lib/python3.11/site-packages/loan_defenders_models/__init__.py
Implementation Plan
Phase 1: Fix Package Configuration (No Code Changes)
Goal: Update package configuration for proper installation.
Tasks:
1. ✅ Already done: Packages have pyproject.toml files
2. ⚠️ Review needed: Check hatchling configuration
3. ⚠️ Verify: packages = ["."] vs explicit naming
Validation:
# Test package build
$ cd loan_defenders_models
$ uv build
# Should create dist/loan_defenders_models-0.1.0-py3-none-any.whl
# Test install
$ pip install dist/loan_defenders_models-0.1.0-py3-none-any.whl
$ python -c "import loan_defenders_models"
# Should succeed
Action Items: - [ ] Document current hatchling configuration behavior - [ ] Test package builds locally - [ ] Verify imports work after pip install
Phase 2: Update Dockerfiles (Code Changes Required)
Goal: Eliminate PYTHONPATH dependency, install packages properly.
Tasks: 1. Update apps/api/Dockerfile 2. Update apps/mcp_servers/*/Dockerfile (3 servers) 3. Update apps/ui/Dockerfile (if applicable)
Changes:
- Remove COPY of shared package source in runtime stage
- Remove PYTHONPATH environment variable
- Verify venv contains installed shared packages
Testing:
# Build locally
$ docker build -f apps/api/Dockerfile -t api:test .
# Run and test imports
$ docker run --rm api:test python -c "import loan_defenders_models"
# Should succeed
# Verify PYTHONPATH not needed
$ docker run --rm -e PYTHONPATH= api:test python -c "import loan_defenders_models"
# Should still succeed
Action Items: - [ ] Update API Dockerfile - [ ] Update 3 MCP server Dockerfiles - [ ] Test Docker builds locally - [ ] Verify imports work in container
Phase 3: Azure ACR Build Script (Code Changes Required)
Goal: Ensure ACR builds have full repository context.
Tasks:
1. Create infrastructure/scripts/build-images.sh
2. Update deployment scripts to use build script
3. Document build process
Script Template: See Azure ACR Build Pattern above.
Testing:
# Test ACR build script
$ ./infrastructure/scripts/build-images.sh <acr-name> test
# Verify images in ACR
$ az acr repository list --name <acr-name> --output table
# Pull and test image
$ az acr login --name <acr-name>
$ docker pull <acr-name>.azurecr.io/loan-defenders-api:test
$ docker run --rm <acr-name>.azurecr.io/loan-defenders-api:test python -c "import loan_defenders_models"
# Should succeed
Action Items: - [ ] Create build-images.sh script - [ ] Update deployment scripts - [ ] Test ACR builds - [ ] Verify deployed containers work
Phase 4: Documentation & Verification (No Code Changes)
Goal: Document the solution and create verification checklist.
Tasks: 1. Update deployment documentation 2. Create troubleshooting guide 3. Add pre-deployment verification checklist
Documentation Updates:
- docs/deployment/direct-azure-deployment.md - Update build instructions
- docs/getting-started/local-development.md - Update setup instructions
- docs/troubleshooting/module-not-found.md - New troubleshooting guide
Action Items: - [ ] Update deployment docs - [ ] Create troubleshooting guide - [ ] Document verification steps
Verification Checklist
Local Development
# 1. Clean environment
$ rm -rf .venv
$ uv sync
# 2. Verify shared packages installed
$ uv run python -c "import loan_defenders_models; print(loan_defenders_models.__file__)"
# Expected: .venv/lib/python3.11/site-packages/loan_defenders_models/__init__.py
$ uv run python -c "import loan_defenders_utils; print(loan_defenders_utils.__file__)"
# Expected: .venv/lib/python3.11/site-packages/loan_defenders_utils/__init__.py
# 3. Test imports without PYTHONPATH
$ env -u PYTHONPATH uv run python -c "import loan_defenders_models"
# Expected: Success
# 4. Run API locally
$ uv run uvicorn apps.api.loan_defenders.api.app:app --host 0.0.0.0 --port 8000
# Expected: Server starts without import errors
Docker Builds (Local)
# 1. Build API image
$ docker build -f apps/api/Dockerfile -t loan-defenders-api:test .
# 2. Verify shared packages in container
$ docker run --rm loan-defenders-api:test python -c "import loan_defenders_models; print(loan_defenders_models.__file__)"
# Expected: /app/.venv/lib/python3.11/site-packages/loan_defenders_models/__init__.py
# 3. Test without PYTHONPATH
$ docker run --rm -e PYTHONPATH= loan-defenders-api:test python -c "import loan_defenders_models"
# Expected: Success (no PYTHONPATH needed)
# 4. Run container
$ docker run -p 8000:8000 loan-defenders-api:test
# Expected: Server starts, check http://localhost:8000/health
# 5. Repeat for MCP servers
$ docker build -f apps/mcp_servers/financial_calculations/Dockerfile -t mcp-financial:test .
$ docker run --rm mcp-financial:test python -c "import loan_defenders_models"
# Expected: Success
Azure ACR Builds
# 1. Build in ACR
$ az acr build \
--registry <acr-name> \
--image loan-defenders-api:test \
--file apps/api/Dockerfile \
.
# 2. Verify build succeeded
$ az acr repository show --name <acr-name> --image loan-defenders-api:test
# Expected: Image details returned
# 3. Pull and test image
$ az acr login --name <acr-name>
$ docker pull <acr-name>.azurecr.io/loan-defenders-api:test
$ docker run --rm <acr-name>.azurecr.io/loan-defenders-api:test python -c "import loan_defenders_models"
# Expected: Success
# 4. Test in ACI (optional)
$ az container create \
--resource-group <rg-name> \
--name test-api \
--image <acr-name>.azurecr.io/loan-defenders-api:test \
--registry-login-server <acr-name>.azurecr.io \
--registry-username <username> \
--registry-password <password> \
--ports 8000
$ az container logs --resource-group <rg-name> --name test-api
# Expected: No ModuleNotFoundError, server starts successfully
Automated Verification Script
#!/bin/bash
# scripts/verify-shared-packages.sh
set -e
echo "🔍 Verifying shared package installation across environments..."
# Function to check import
check_import() {
local context="$1"
local command="$2"
echo -n " [$context] Testing import... "
if eval "$command" &>/dev/null; then
echo "✅"
return 0
else
echo "❌"
return 1
fi
}
# Test local
echo "📦 Local Development:"
check_import "uv run" "uv run python -c 'import loan_defenders_models'"
check_import "no PYTHONPATH" "env -u PYTHONPATH uv run python -c 'import loan_defenders_models'"
# Test Docker
echo "🐳 Docker:"
check_import "API container" "docker run --rm loan-defenders-api:test python -c 'import loan_defenders_models'"
check_import "no PYTHONPATH" "docker run --rm -e PYTHONPATH= loan-defenders-api:test python -c 'import loan_defenders_models'"
echo ""
echo "✅ All verification checks passed!"
Summary
Current Issues
- PYTHONPATH Dependency: Fragile, non-standard, breaks in some contexts
- Inconsistent Installation: Editable installs locally, COPY in Docker
- ACR Build Context: Missing shared packages when building from subdirectory
- Package Configuration: Flat layout can cause discovery issues
Recommended Solution
- Proper Package Installation: Install shared packages into venv/site-packages
- No PYTHONPATH: Use standard Python import mechanism
- Consistent Pattern: Same installation method across all environments
- Full Build Context: Always build from repository root
Implementation Timeline
- Phase 1 (Review): 1-2 hours (no code changes)
- Phase 2 (Dockerfiles): 2-3 hours (5 Dockerfiles to update)
- Phase 3 (ACR Script): 1-2 hours (new build script)
- Phase 4 (Documentation): 2-3 hours (docs + verification)
Total: 6-10 hours to eliminate all module not found issues permanently.
Success Criteria
- ✅ Imports work in all environments without PYTHONPATH
- ✅ Docker builds succeed locally and in ACR
- ✅ Deployed containers start without module errors
- ✅ Local development matches production behavior
- ✅ No more "module not found" issues
References
Python Packaging
uv Documentation
Docker Best Practices
Azure Container Registry
Last Updated: 2025-10-25 Review Frequency: After any deployment failures or package structure changes Next Review: After implementing Phase 2-3 updates