Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 11, 2025

Issue describing the changes in this PR

resolves #4709

Python projects using poetry or uv for dependency management were blocked from using func pack --no-build due to hard requirement for requirements.txt. Additionally, func pack without --no-build would fail for uv-created venvs lacking pip.

Validation: func pack --no-build now accepts:

  • requirements.txt (existing)
  • pyproject.toml (poetry)
  • pyproject.toml + uv.lock (uv)

Dependency Resolution: func pack auto-detects and uses appropriate tool:

  • uv (priority 1): Both pyproject.toml and uv.lock present → uv exportpip download
  • poetry (priority 2): Only pyproject.toml present → poetry exportpip download
  • pip (priority 3): requirements.txt present → pip download (unchanged)

Priority logic when multiple files present:

  • pyproject.toml + uv.lock + requirements.txt → uses uv
  • pyproject.toml + requirements.txt (no uv.lock) → uses poetry
  • requirements.txt only → uses pip

Docker builds (--build-native-deps): Exports from poetry/uv to temporary requirements.txt before Docker build, cleanup in finally block.

Checksum handling: Separate MD5 files per tool (requirements.txt.md5, pyproject.toml.md5, uv.md5) to avoid conflicts when switching tools.

Implementation:

  • Added PythonDependencyManager enum and detection logic
  • Added RestorePythonRequirementsWithPoetry() and RestorePythonRequirementsWithUv()
  • Updated GetPythonDeploymentPackage() to route to appropriate restore method
  • All poetry/uv commands execute from function app root directory

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Backward compatibility: 100% compatible - existing requirements.txt workflows unchanged.

Tool availability: Graceful failure with actionable error messages if poetry/uv not installed.

Priority rationale: Matches Oryx behavior - uv (most specific) > poetry > pip (fallback).

Test coverage: Added comprehensive tests including edge cases for all file combinations:

  • Test with requirements.txt only → Pip
  • Test with pyproject.toml only → Poetry
  • Test with pyproject.toml + uv.lock → Uv
  • Test with pyproject.toml + uv.lock + requirements.txt → Uv (all files, uv takes priority)
  • Test with pyproject.toml + requirements.txt (no uv.lock) → Poetry (poetry takes priority over pip)
  • Test with no dependency files → Unknown
Original prompt

This section details on the original issue you should resolve

<issue_title>Remove need for requirement.txt for Python projects in func pack</issue_title>
<issue_description>### Description

Recently we added made some changes in Oryx, which removes the need for requirements.txt for Python apps. With the change, if customer only has pyproject.toml then poetry will be used to resolve dependencies, if both pyproject.toml and uv.lock are present then uv will be used, and if requirements.txt is present then pip will be used.

Today, the func pack with --no-build flag is still expecting Python projects to have a requirements.txt:

func pack --no-build
local.settings.json found in root directory (/Users/lily/Desktop/Functions/mcp/functions-hosting/test/mcp-sdk-functions-hosting-python).
Resolving worker runtime to 'python'.
local.settings.json found in root directory (/Users/lily/Desktop/Functions/mcp/functions-hosting/test/mcp-sdk-functions-hosting-python).
Resolving worker runtime to 'python'.
 
Validating project...
 
  Validate host.json: PASSED
  Validate Flag Compatibility: PASSED
  Validate Folder Structure: FAILED
 
**Required file(s) 'requirements.txt' not found in /Users/lily/Desktop/Functions/mcp/functions-hosting/test/mcp-sdk-functions-hosting-python.**

Related issue

func pack (--no-build flag is not specified) defaults to using pip install for ensuring the dependencies are available, but this will fail for venv's created by uv since pip is not installed by default.

(durableagent) PS Q:\src\durable-agent-framework\python\samples\01_SingleAgent> func pack
local.settings.json found in root directory (Q:\src\durable-agent-framework\python\samples\01_SingleAgent).
Resolving worker runtime to 'python'.
local.settings.json found in root directory (Q:\src\durable-agent-framework\python\samples\01_SingleAgent).
Resolving worker runtime to 'python'.

Validating project...

  Validate host.json: PASSED
  Validate Flag Compatibility: PASSED
  Validate Folder Structure: PASSED
  Validation .python_packages directory exists: WARNING
    Directory '.python_packages' not found or is empty.
  Validate Python Programming Model: PASSED

Found Python version 3.13.7 (py).
Q:\src\durable-agent-framework\python\.venv\Scripts\python.exe -m pip download -r Q:\src\durable-agent-framework\python\samples\01_SingleAgent\requirements.txt --dest C:\Users\larohra\AppData\Local\Temp\azureworker9ez2uk0n        

There was an error restoring dependencies. Q:\src\durable-agent-framework\python\.venv\Scripts\python.exe: No module named pip
ERROR: ['Q:\\src\\durable-agent-framework\\python\\.venv\\Scripts\\python.exe', '-m', 'pip', 'download', '-r', 'Q:\\src\\durable-agent-framework\\python\\samples\\01_SingleAgent\\requirements.txt', '--dest', 'C:\\Users\\larohra\\AppData\\Local\\Temp\\azureworker9ez2uk0n'] failed with exit code 1

Ask

The following asks are for Python projects -

  1. func pack --no-build should check for the presence of pyproject.toml and uv.lock, and if they're present, the project doesn't need a requirements.txt to pack.
  2. func pack should check for presence of requirements.txt before using pip to install dependencies. If the project only has pyproject.toml then poetry should be used. If both pyproject.toml and uv.lock are present then uv should be used.

FYI @im-samz </issue_description>

<agent_instructions>The issue is only specific to Python and no other language should be impacted. I am assuming most of the changes would be in PythonHelper</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Remove need for requirements.txt in func pack for Python projects Support pyproject.toml and uv.lock for Python dependency management in func pack Nov 11, 2025
Copilot AI requested a review from vrdmr November 11, 2025 23:23
Copilot finished work on behalf of vrdmr November 11, 2025 23:23
@vrdmr
Copy link
Member

vrdmr commented Nov 12, 2025

@copilot The test needs update - DetectPythonDependencyManager_WithPyProjectTomlAndRequirementsTxt_ReturnsUv

        Directory.CreateDirectory(tempDir);
        try
        {
            File.WriteAllText(Path.Combine(tempDir, Constants.PyProjectToml), "[tool.poetry]\nname = \"test\"");
            File.WriteAllText(Path.Combine(tempDir, Constants.UvLock), "version = 1");
            File.WriteAllText(Path.Combine(tempDir, Constants.RequirementsTxt), "flask==2.0.0");
            var result = PythonHelpers.DetectPythonDependencyManager(tempDir);
            // uv takes priority when both pyproject.toml and uv.lock are present
            Assert.Equal(PythonDependencyManager.Uv, result);

THis isn't checking tool.uv but checking tool.poertry in the

Also - can there be a check where uvlock isn't present

Copy link
Contributor Author

Copilot AI commented Nov 12, 2025

@copilot The test needs update - DetectPythonDependencyManager_WithPyProjectTomlAndRequirementsTxt_ReturnsUv

        Directory.CreateDirectory(tempDir);...

Fixed in 93e21b0:

  1. Renamed test to DetectPythonDependencyManager_WithPyProjectTomlUvLockAndRequirementsTxt_ReturnsUv and updated pyproject.toml content to use [tool.uv] instead of [tool.poetry]
  2. Added new test DetectPythonDependencyManager_WithPyProjectTomlAndRequirementsTxt_ReturnsPoetry to cover the case where uv.lock is NOT present but both pyproject.toml and requirements.txt exist (poetry takes priority over pip)

Copilot finished work on behalf of vrdmr November 12, 2025 00:48
Comment on lines +37 to +38
var hasUvLock = FileSystemHelpers.FileExists(Path.Combine(directory, Constants.UvLock));
var hasRequirementsTxt = FileSystemHelpers.FileExists(Path.Combine(directory, Constants.RequirementsTxt));
Copy link
Member

Choose a reason for hiding this comment

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

Since we're not checking this till line 53, we should not read the value so early as it might never be used.

{
PythonDependencyManager.Pip => Constants.RequirementsTxt,
PythonDependencyManager.Poetry => Constants.PyProjectToml,
PythonDependencyManager.Uv => $"{Constants.PyProjectToml} + {Constants.UvLock}",
Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense for the file name to be two file names in one string? "pyproject.toml uv.lock" - if we're seperating this later, doesn't it make more sense to use a delimeter like , = "pyproject.toml,uv.lock"

{
PythonDependencyManager.Pip => $"{Constants.RequirementsTxt}.md5",
PythonDependencyManager.Poetry => $"{Constants.PyProjectToml}.md5",
PythonDependencyManager.Uv => "uv.md5",
Copy link
Member

Choose a reason for hiding this comment

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

Why is uv not a const like the other two are?


namespace Azure.Functions.Cli.Helpers
{
public enum PythonDependencyManager
Copy link
Member

Choose a reason for hiding this comment

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

In .NET maming something as a manager often refers to classes that perform management operations. Could we use something like PythonPackageTool, PythonDependencyTool or PythonPackageSystem instead?

Copy link
Member

Choose a reason for hiding this comment

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

We would also update any reference to dependencyManager to something that makes sense like packageTool

{
File.WriteAllText(Path.Combine(_tempDirectory, Constants.PyProjectToml), "[tool.poetry]\nname = \"test\"");
File.WriteAllText(Path.Combine(_tempDirectory, Constants.UvLock), "version = 1");
// Should not throw
Copy link
Member

Choose a reason for hiding this comment

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

Can we validate actual output/return instead of just hoping for "does not throw"

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove need for requirement.txt for Python projects in func pack shan

3 participants