or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bundling-configuration.mdindex.mdpackaging-systems.mdpython-functions.mdpython-layers.md
tile.json

packaging-systems.mddocs/

Packaging Systems

Support for multiple Python dependency management systems with automatic detection and conversion.

Note: The packaging system provides automatic dependency detection and bundling. Users typically interact with the packaging system through the bundling options of PythonFunction and PythonLayerVersion constructs. This documentation covers the underlying packaging system classes and interfaces for advanced use cases.

Capabilities

Packaging Class

Central class for handling different Python dependency management systems.

/**
 * Handles different Python dependency management systems
 * Provides static factory methods for creating packaging configurations
 */
class Packaging {
  /**
   * Standard packaging with pip and requirements.txt
   * @returns Packaging instance configured for pip
   */
  static withPip(): Packaging;

  /**
   * Packaging with pipenv and Pipfile/Pipfile.lock
   * @returns Packaging instance configured for pipenv
   */
  static withPipenv(): Packaging;

  /**
   * Packaging with poetry and poetry.lock
   * @param props - Optional Poetry-specific configuration
   * @returns Packaging instance configured for poetry
   */
  static withPoetry(props?: PoetryPackagingProps): Packaging;

  /**
   * Packaging with uv and uv.lock
   * @returns Packaging instance configured for uv
   */
  static withUv(): Packaging;

  /**
   * No dependencies or packaging
   * @returns Packaging instance with no dependency management
   */
  static withNoPackaging(): Packaging;

  /**
   * Auto-detect packaging type from entry directory
   * Examines the entry directory for dependency files and selects appropriate packaging
   * @param entry - Path to examine for dependency files
   * @param poetryIncludeHashes - Whether to include hashes in Poetry exports
   * @param poetryWithoutUrls - Whether to exclude URLs in Poetry exports
   * @returns Packaging instance based on detected files
   */
  static fromEntry(
    entry: string,
    poetryIncludeHashes?: boolean,
    poetryWithoutUrls?: boolean
  ): Packaging;

  /**
   * The dependency file type for this packaging configuration
   */
  readonly dependenciesFile: string;

  /**
   * Command to export dependencies to pip-compatible requirements.txt format
   */
  readonly exportCommand?: string;
}

Dependencies File Enum

Enumeration of supported dependency file types.

/**
 * Supported dependency file types for Python packaging
 */
enum DependenciesFile {
  /** pip requirements file */
  PIP = 'requirements.txt',
  /** Poetry lock file */
  POETRY = 'poetry.lock',
  /** Pipenv lock file */
  PIPENV = 'Pipfile.lock',
  /** uv lock file */
  UV = 'uv.lock',
  /** No dependencies */
  NONE = '',
}

Configuration Interfaces

Interfaces for configuring packaging behavior.

/**
 * Properties for Packaging class constructor
 */
interface PackagingProps {
  /**
   * Dependency file for the type of packaging
   */
  readonly dependenciesFile: DependenciesFile;
  
  /**
   * Command to export the dependencies into a pip-compatible requirements.txt format
   * @default - No dependencies are exported
   */
  readonly exportCommand?: string;
}

/**
 * Poetry-specific packaging configuration
 */
interface PoetryPackagingProps {
  /**
   * Whether to export Poetry dependencies with hashes
   * Note that this can cause builds to fail if not all dependencies export with a hash
   * @default false - Hashes are NOT included in the exported requirements.txt file
   */
  readonly poetryIncludeHashes?: boolean;

  /**
   * Whether to export Poetry dependencies with source repository urls
   * @default false - URLs are included in the exported requirements.txt file
   */
  readonly poetryWithoutUrls?: boolean;
}

Packaging Types

pip (requirements.txt)

Standard pip packaging with requirements.txt file.

Directory Structure:

lambda/
├── index.py
├── requirements.txt   # pip dependencies
└── other_modules.py

Usage:

const pipPackaging = Packaging.withPip();
// OR auto-detected when requirements.txt is present

Bundling Process:

  1. Copies requirements.txt to container
  2. Runs: python -m pip install -r requirements.txt -t /output
  3. Installs dependencies directly to output directory

Poetry (poetry.lock + pyproject.toml)

Modern Python packaging with Poetry dependency management.

Directory Structure:

lambda/
├── index.py
├── pyproject.toml     # Poetry project configuration
├── poetry.lock        # Poetry lock file (required)
└── other_modules.py

Usage:

// Basic Poetry packaging
const poetryPackaging = Packaging.withPoetry();

// With custom options
const poetryWithOptions = Packaging.withPoetry({
  poetryIncludeHashes: true,
  poetryWithoutUrls: false,
});

Bundling Process:

  1. Detects poetry.lock file
  2. Runs export command: poetry export --with-credentials --format requirements.txt --output requirements.txt
  3. Installs exported requirements with pip

Export Command Options:

  • --without-hashes: Excludes dependency hashes (default)
  • --with-hashes: Includes dependency hashes (if poetryIncludeHashes: true)
  • --without-urls: Excludes source repository URLs (if poetryWithoutUrls: true)
  • --with-credentials: Includes authentication credentials

Pipenv (Pipfile + Pipfile.lock)

Python packaging with Pipenv virtual environment management.

Directory Structure:

lambda/
├── index.py
├── Pipfile           # Pipenv dependencies
├── Pipfile.lock      # Pipenv lock file (required)
└── other_modules.py

Usage:

const pipenvPackaging = Packaging.withPipenv();
// OR auto-detected when Pipfile.lock is present

Bundling Process:

  1. Detects Pipfile.lock file
  2. Sets PIPENV_VENV_IN_PROJECT=1 to create local virtual environment
  3. Runs: pipenv requirements > requirements.txt
  4. Cleans up virtual environment: rm -rf .venv
  5. Installs requirements with pip

uv (uv.lock + pyproject.toml)

Modern ultra-fast Python package installer and resolver.

Directory Structure:

lambda/
├── index.py
├── pyproject.toml     # uv project configuration
├── uv.lock           # uv lock file (required)
├── .python-version   # Python version (ignored during bundling)
└── other_modules.py

Usage:

const uvPackaging = Packaging.withUv();
// OR auto-detected when uv.lock is present

Bundling Process:

  1. Detects uv.lock file
  2. Runs export command: uv export --frozen --no-emit-workspace --no-dev --no-editable -o requirements.txt
  3. Installs with uv: uv pip install -r requirements.txt --target /output
  4. Automatically excludes .python-version file from assets

Export Options:

  • --frozen: Use exact versions from lock file
  • --no-emit-workspace: Don't include workspace dependencies
  • --no-dev: Exclude development dependencies
  • --no-editable: Don't include editable installations

No Packaging

For Lambda functions with no external dependencies.

Directory Structure:

lambda/
├── index.py
└── utils.py          # Only local Python modules

Usage:

const noPackaging = Packaging.withNoPackaging();
// OR auto-detected when no dependency files are present

Bundling Process:

  1. No dependency files detected
  2. Only copies Python source files
  3. No dependency installation performed

Auto-Detection

The fromEntry method automatically detects the packaging type based on files present in the entry directory.

Detection Priority

  1. Pipenv: If Pipfile.lock exists
  2. Poetry: If poetry.lock exists
  3. pip: If requirements.txt exists
  4. uv: If uv.lock exists
  5. None: If no dependency files are found
// Automatic detection
const packaging = Packaging.fromEntry('./my-lambda');

// With Poetry options for auto-detection
const poetryPackaging = Packaging.fromEntry(
  './my-lambda',
  true,   // poetryIncludeHashes
  false   // poetryWithoutUrls
);

Usage Examples

Manual Packaging Selection

import * as python from '@aws-cdk/aws-lambda-python-alpha';

// Explicitly use pip packaging
const pipFunc = new python.PythonFunction(this, 'PipFunction', {
  entry: './pip-lambda',
  runtime: Runtime.PYTHON_3_8,
  // Auto-detects requirements.txt or can be explicitly set
});

// Explicitly use Poetry packaging
const poetryFunc = new python.PythonFunction(this, 'PoetryFunction', {
  entry: './poetry-lambda',
  runtime: Runtime.PYTHON_3_8,
  bundling: {
    poetryIncludeHashes: true,
    poetryWithoutUrls: false,
  },
});

Mixed Packaging in Same Project

// Different functions can use different packaging systems
const pipFunction = new python.PythonFunction(this, 'PipFunction', {
  entry: './functions/pip-function',    # Contains requirements.txt
  runtime: Runtime.PYTHON_3_8,
});

const poetryFunction = new python.PythonFunction(this, 'PoetryFunction', {
  entry: './functions/poetry-function', # Contains poetry.lock
  runtime: Runtime.PYTHON_3_8,
});

const noDepsFunction = new python.PythonFunction(this, 'NoDepsFunction', {
  entry: './functions/utils-only',      # No dependency files
  runtime: Runtime.PYTHON_3_8,
});

Layer Packaging

// Layers also support all packaging types
const poetryLayer = new python.PythonLayerVersion(this, 'PoetryLayer', {
  entry: './layers/poetry-layer',       # Contains poetry.lock
  compatibleRuntimes: [Runtime.PYTHON_3_8],
});

const pipLayer = new python.PythonLayerVersion(this, 'PipLayer', {
  entry: './layers/pip-layer',          # Contains requirements.txt
  compatibleRuntimes: [Runtime.PYTHON_3_8],
});

Dependency File Examples

requirements.txt (pip)

# Production dependencies
requests>=2.25.0,<3.0.0
boto3>=1.20.0
pydantic==1.8.2

# Optional dependencies with extras
fastapi[all]==0.68.0
sqlalchemy[postgresql]==1.4.23

# Development dependencies (usually excluded in production)
pytest>=6.0.0
black>=21.0.0

pyproject.toml + poetry.lock (Poetry)

[tool.poetry]
name = "my-lambda"
version = "0.1.0"
description = "Lambda function with Poetry"

[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.25.0"
boto3 = "^1.20.0"
pydantic = "^1.8.2"

[tool.poetry.group.dev.dependencies]
pytest = "^6.0.0"
black = "^21.0.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

Pipfile + Pipfile.lock (Pipenv)

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = ">=2.25.0,<3.0.0"
boto3 = ">=1.20.0"
pydantic = "==1.8.2"

[dev-packages]
pytest = ">=6.0.0"
black = ">=21.0.0"

[requires]
python_version = "3.8"

pyproject.toml + uv.lock (uv)

[project]
name = "my-lambda"
version = "0.1.0"
description = "Lambda function with uv"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.25.0,<3.0.0",
    "boto3>=1.20.0",
    "pydantic==1.8.2",
]

[project.optional-dependencies]
dev = [
    "pytest>=6.0.0",
    "black>=21.0.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Best Practices

Lock File Management

  • Always commit lock files to version control for reproducible builds
  • Keep lock files updated but test thoroughly before deploying
  • Use specific versions in lock files to avoid dependency conflicts

Dependency Organization

  • Separate dev and production dependencies to minimize bundle size
  • Use dependency groups to organize optional dependencies
  • Pin critical dependencies to specific versions for stability

Performance Optimization

  • Use lock files for faster dependency resolution
  • Minimize dependencies to reduce bundle size and cold start time
  • Consider layers for shared dependencies across multiple functions

Security Considerations

  • Audit dependencies regularly for security vulnerabilities
  • Use trusted package indexes and verify package signatures when possible
  • Keep dependencies updated but test thoroughly in staging environments

Troubleshooting

Common Issues

  1. Lock file missing: Dependency manager detected but lock file not found
  2. Export command failures: Poetry/Pipenv export command fails due to missing dependencies
  3. Version conflicts: Dependencies have conflicting version requirements
  4. Platform compatibility: Dependencies not available for target Lambda architecture

Error Resolution

// Handle missing lock files
const func = new python.PythonFunction(this, 'SafeFunction', {
  entry: './lambda',
  runtime: Runtime.PYTHON_3_8,
  bundling: {
    commandHooks: {
      beforeBundling: () => [
        'ls -la',  // List files to verify lock file presence
        'cat requirements.txt || echo "No requirements.txt found"',
      ],
      afterBundling: () => [],
    },
  },
});

Debug Packaging Detection

// Debug auto-detection process
const func = new python.PythonFunction(this, 'DebugPackaging', {
  entry: './lambda',
  runtime: Runtime.PYTHON_3_8,
  bundling: {
    commandHooks: {
      beforeBundling: (inputDir, outputDir) => [
        `echo "Input directory: ${inputDir}"`,
        `ls -la ${inputDir}`,
        'test -f Pipfile.lock && echo "Found Pipfile.lock"',
        'test -f poetry.lock && echo "Found poetry.lock"', 
        'test -f requirements.txt && echo "Found requirements.txt"',
        'test -f uv.lock && echo "Found uv.lock"',
      ],
      afterBundling: () => [],
    },
  },
});