Skip to content

feat: Python UV workflow #756

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open

Conversation

sriram-mv
Copy link
Contributor

@sriram-mv sriram-mv commented Jun 20, 2025

Issue link: #743

Core Features:

  • Intelligent handling of pyproject.toml with automatic uv.lock detection
  • Multi-format support: pyproject.toml, requirements.txt, and requirements-*.txt variants
  • Lock file optimization: Automatic uv.lock usage for reproducible builds when available
  • Platform targeting: Lambda-compatible builds for x86_64 and ARM64 architectures
  • Python version control: Precise Python version targeting via UV's --python flags

UV Functionality:

  • uv sync --python X.Y for lock-based builds (pyproject.toml + uv.lock)
  • uv lock && uv export workflow for pyproject.toml without lock files
  • uv pip install --python-version X.Y --python-platform for requirements.txt
  • Proper virtual environment handling and site-packages extraction

Documentation:

  • Complete DESIGN.md with architecture overview and usage patterns
  • Accurate API documentation reflecting constructor + method call pattern
  • Smart dispatch logic clearly explained with examples
  • Updated to match actual implementation (no outdated references)

Compatibility:

  • Compatible with existing Lambda Builders interface
  • Supports standard build parameters (source_dir, artifacts_dir, scratch_dir)
  • Runtime parameter properly extracted and used for Python version targeting
  • Architecture parameter mapped to UV platform specifications

Issue #, if available:

Description of changes:

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@sriram-mv sriram-mv force-pushed the python-uv branch 2 times, most recently from b89aa89 to ec932ce Compare June 21, 2025 04:30
Core Features:
 * Intelligent handling of pyproject.toml with automatic uv.lock detection
 * Multi-format support: pyproject.toml, requirements.txt, and requirements-*.txt variants
 * Lock file optimization: Automatic uv.lock usage for reproducible builds when available
 * Platform targeting: Lambda-compatible builds for x86_64 and ARM64 architectures
 * Python version control: Precise Python version targeting via UV's --python flags

UV Functionality:
* `uv sync --python X.Y` for lock-based builds (pyproject.toml + uv.lock)
* `uv lock && uv export` workflow for pyproject.toml without lock files
* `uv pip install --python-version X.Y --python-platform` for requirements.txt
* Proper virtual environment handling and site-packages extraction

Documentation:
* Complete DESIGN.md with architecture overview and usage patterns
* Accurate API documentation reflecting constructor + method call pattern
* Smart dispatch logic clearly explained with examples
* Updated to match actual implementation (no outdated references)

Compatibility:
* Compatible with existing Lambda Builders interface
* Supports standard build parameters (source_dir, artifacts_dir, scratch_dir)
* Runtime parameter properly extracted and used for Python version targeting
* Architecture parameter mapped to UV platform specifications
@sriram-mv sriram-mv marked this pull request as ready for review June 23, 2025 19:28
@sriram-mv sriram-mv requested a review from a team as a code owner June 23, 2025 19:28
Comment on lines +283 to +286
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
enable-cache: true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we separate jobs for python-uv and python-pip, like we do for Java with Maven and Gradle. It would be easier to identify which tool caused failure.

class MissingUvError(LambdaBuilderError):
"""Exception raised when UV executable is not found."""

MESSAGE = "uv executable not found in your environment. Please install uv: https://docs.astral.sh/uv/getting-started/installation/"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also print the {uv_path} in the message, to mention the specific location where the uv executable was not found.

artifacts_dir_path: str,
scratch_dir_path: str,
manifest_path: str,
architecture: str = X86_64,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we hardcode the architecture here?

handler = self._get_manifest_handler(manifest_name)

# Execute the handler
handler(manifest_path, artifacts_dir_path, scratch_dir_path, python_version, architecture, config)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this method actually building the dependencies? For reference here is how python pip handles building the dependencies.

except Exception as e:
raise UvBuildError(reason=f"Failed to build from pyproject.toml: {str(e)}")

def _export_pyproject_to_requirements(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we converting pyproject.toml to requirements.txt, when it is recommended t o use pyproject.toml to define dependencies for UV?

MESSAGE = "Lock file operation failed: {reason}"


class ManifestNotFoundError(LambdaBuilderError):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where have we used this exception?

MESSAGE = "Failed to install dependencies using uv: {reason}"


class UvResolutionError(LambdaBuilderError):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where have we used this exception?

@patch("aws_lambda_builders.workflows.python_uv.packager.OSUtils")
def test_subprocess_uv_init_missing_uv(self, mock_osutils_class):
mock_osutils = Mock()
mock_osutils.which.return_value = None

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just keep the path here /usr/bin/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants