From 935dbbd6e09948e839e41b95c991b2e974fa122a Mon Sep 17 00:00:00 2001
From: Gavin Aguiar <80794152+gavin-aguiar@users.noreply.github.com>
Date: Tue, 29 Oct 2024 13:55:51 -0500
Subject: [PATCH] Added support for python3.12 (#3796)
* Added support for python3.12
* Fixed variable name
* Updated tests
* Added dockerfile for 312
---
.../Azure.Functions.Cli.csproj | 3 ++
src/Azure.Functions.Cli/Common/Constants.cs | 2 ++
.../Helpers/PythonHelpers.cs | 30 +++++++++++--------
.../StaticResources/Dockerfile.python3.12 | 11 +++++++
.../StaticResources/StaticResources.cs | 2 ++
.../PythonHelperTests.cs | 11 ++++---
6 files changed, 43 insertions(+), 16 deletions(-)
create mode 100644 src/Azure.Functions.Cli/StaticResources/Dockerfile.python3.12
diff --git a/src/Azure.Functions.Cli/Azure.Functions.Cli.csproj b/src/Azure.Functions.Cli/Azure.Functions.Cli.csproj
index ac9997361..fa9c0554d 100644
--- a/src/Azure.Functions.Cli/Azure.Functions.Cli.csproj
+++ b/src/Azure.Functions.Cli/Azure.Functions.Cli.csproj
@@ -114,6 +114,9 @@
$(AssemblyName).Dockerfile.python3.11
+
+ $(AssemblyName).Dockerfile.python3.12
+
$(AssemblyName).Dockerfile.javascript
diff --git a/src/Azure.Functions.Cli/Common/Constants.cs b/src/Azure.Functions.Cli/Common/Constants.cs
index 47b7be41c..52eb0b096 100644
--- a/src/Azure.Functions.Cli/Common/Constants.cs
+++ b/src/Azure.Functions.Cli/Common/Constants.cs
@@ -180,6 +180,8 @@ public static class DockerImages
public const string LinuxPython39ImageAmd64 = "mcr.microsoft.com/azure-functions/python:3.0.15066-python3.9-buildenv";
public const string LinuxPython310ImageAmd64 = "mcr.microsoft.com/azure-functions/python:4-python3.10-buildenv";
public const string LinuxPython311ImageAmd64 = "mcr.microsoft.com/azure-functions/python:4-python3.11-buildenv";
+ public const string LinuxPython312ImageAmd64 = "mcr.microsoft.com/azure-functions/python:4-python3.12-buildenv";
+
}
public static class StaticResourcesNames
diff --git a/src/Azure.Functions.Cli/Helpers/PythonHelpers.cs b/src/Azure.Functions.Cli/Helpers/PythonHelpers.cs
index c6ff82076..65595232e 100644
--- a/src/Azure.Functions.Cli/Helpers/PythonHelpers.cs
+++ b/src/Azure.Functions.Cli/Helpers/PythonHelpers.cs
@@ -167,7 +167,7 @@ public static void AssertPythonVersion(WorkerLanguageVersionInfo pythonVersion,
{
if (pythonVersion?.Version == null)
{
- var message = "Could not find a Python version. Python 3.6.x, 3.7.x, 3.8.x, 3.9.x, 3.10.x or 3.11.x is recommended, and used in Azure Functions.";
+ var message = "Could not find a Python version. 3.7.x, 3.8.x, 3.9.x, 3.10.x, 3.11.x or 3.12.x is recommended, and used in Azure Functions.";
if (errorIfNoVersion) throw new CliException(message);
ColoredConsole.WriteLine(WarningColor(message));
return;
@@ -175,23 +175,23 @@ public static void AssertPythonVersion(WorkerLanguageVersionInfo pythonVersion,
ColoredConsole.WriteLine(AdditionalInfoColor($"Found Python version {pythonVersion.Version} ({pythonVersion.ExecutablePath})."));
- // Python 3.[6|7|8|9|10|11] (supported)
+ // Python 3.[7|8|9|10|11|12] (supported)
if (IsVersionSupported(pythonVersion))
{
return;
}
- // Python 3.x (but not 3.[6|7|8|9|10|11]), not recommended, may fail. E.g.: 3.4, 3.5.
+ // Python 3.x (but not 3.[7|8|9|10|11|12]), not recommended, may fail. E.g.: 3.4, 3.5.
if (pythonVersion.Major == 3)
{
if (errorIfNotSupported)
- throw new CliException($"Python 3.6.x to 3.11.x is required for this operation. " +
- $"Please install Python 3.6, 3.7, 3.8, 3.9, 3.10 or 3.11 and use a virtual environment to switch to Python 3.6, 3.7, 3.8, 3.9, 3.10 or 3.11.");
- ColoredConsole.WriteLine(WarningColor("Python 3.6.x, 3.7.x, 3.8.x, 3.9.x, 3.10.x or 3.11.x is recommended, and used in Azure Functions."));
+ throw new CliException($"Python 3.7.x to 3.12.x is required for this operation. " +
+ $"Please install Python 3.7, 3.8, 3.9, 3.10, 3.11 or 3.12 and use a virtual environment to switch to Python 3.7, 3.8, 3.9, 3.10, 3.11 or 3.12.");
+ ColoredConsole.WriteLine(WarningColor("Python 3.7.x, 3.8.x, 3.9.x, 3.10.x, 3.11.x or 3.12.x is recommended, and used in Azure Functions."));
}
// No Python 3
- var error = "Python 3.x (recommended version 3.[6|7|8|9|10|11]) is required.";
+ var error = "Python 3.x (recommended version 3.[7|8|9|10|11|12]) is required.";
if (errorIfNoVersion) throw new CliException(error);
ColoredConsole.WriteLine(WarningColor(error));
}
@@ -225,6 +225,7 @@ public static async Task GetEnvironmentPythonVersion(
var python39GetVersionTask = GetVersion("python3.9");
var python310GetVersionTask = GetVersion("python3.10");
var python311GetVersionTask = GetVersion("python3.11");
+ var python312GetVersionTask = GetVersion("python3.12");
var versions = new List
{
@@ -237,6 +238,7 @@ public static async Task GetEnvironmentPythonVersion(
await python39GetVersionTask,
await python310GetVersionTask,
await python311GetVersionTask,
+ await python312GetVersionTask
};
// Highest preference -- Go through the list, if we find the first python 3.6 or python 3.7 worker, we prioritize that.
@@ -559,6 +561,8 @@ public static Task GetDockerInitFileContent(WorkerLanguageVersionInfo in
return StaticResources.DockerfilePython310;
case 11:
return StaticResources.DockerfilePython311;
+ case 12:
+ return StaticResources.DockerfilePython312;
}
}
return StaticResources.DockerfilePython37;
@@ -582,6 +586,8 @@ private static string GetBuildNativeDepsEnvironmentImage(WorkerLanguageVersionIn
return Constants.DockerImages.LinuxPython310ImageAmd64;
case 11:
return Constants.DockerImages.LinuxPython311ImageAmd64;
+ case 12:
+ return Constants.DockerImages.LinuxPython312ImageAmd64;
}
}
return Constants.DockerImages.LinuxPython36ImageAmd64;
@@ -593,12 +599,12 @@ private static bool IsVersionSupported(WorkerLanguageVersionInfo info)
{
switch (info?.Minor)
{
+ case 12:
case 11:
case 10:
case 9:
case 8:
- case 7:
- case 6: return true;
+ case 7: return true;
default: return false;
}
} else return false;
@@ -606,11 +612,11 @@ private static bool IsVersionSupported(WorkerLanguageVersionInfo info)
public static bool IsLinuxFxVersionRuntimeVersionMatched(string linuxFxVersion, int? major, int? minor)
{
- // No linux fx version will default to python 3.6
+ // No linux fx version will default to python 3.11
if (string.IsNullOrEmpty(linuxFxVersion))
{
- // Match if version is 3.6
- return major == 3 && minor == 6;
+ // Match if version is 3.11
+ return major == 3 && minor == 11;
}
// Only validate on LinuxFxVersion that follows the pattern PYTHON|
else if (!linuxFxVersion.StartsWith("PYTHON|", StringComparison.OrdinalIgnoreCase))
diff --git a/src/Azure.Functions.Cli/StaticResources/Dockerfile.python3.12 b/src/Azure.Functions.Cli/StaticResources/Dockerfile.python3.12
new file mode 100644
index 000000000..ae1f86f01
--- /dev/null
+++ b/src/Azure.Functions.Cli/StaticResources/Dockerfile.python3.12
@@ -0,0 +1,11 @@
+# To enable ssh & remote debugging on app service change the base image to the one below
+# FROM mcr.microsoft.com/azure-functions/python:4-python3.12-appservice
+FROM mcr.microsoft.com/azure-functions/python:4-python3.12
+
+ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
+ AzureFunctionsJobHost__Logging__Console__IsEnabled=true
+
+COPY requirements.txt /
+RUN pip install -r /requirements.txt
+
+COPY . /home/site/wwwroot
diff --git a/src/Azure.Functions.Cli/StaticResources/StaticResources.cs b/src/Azure.Functions.Cli/StaticResources/StaticResources.cs
index 70a07c1a9..3f5ae6e83 100644
--- a/src/Azure.Functions.Cli/StaticResources/StaticResources.cs
+++ b/src/Azure.Functions.Cli/StaticResources/StaticResources.cs
@@ -56,6 +56,8 @@ public static async Task GetValue(string name)
public static Task DockerfilePython311 => GetValue("Dockerfile.python3.11");
+ public static Task DockerfilePython312 => GetValue("Dockerfile.python3.12");
+
public static Task DockerfilePowershell7 => GetValue("Dockerfile.powershell7");
public static Task DockerfilePowershell72 => GetValue("Dockerfile.powershell7.2");
diff --git a/test/Azure.Functions.Cli.Tests/PythonHelperTests.cs b/test/Azure.Functions.Cli.Tests/PythonHelperTests.cs
index 28936f255..9c19b667f 100644
--- a/test/Azure.Functions.Cli.Tests/PythonHelperTests.cs
+++ b/test/Azure.Functions.Cli.Tests/PythonHelperTests.cs
@@ -44,7 +44,6 @@ public async void WorkerInfoRuntimeShouldBePython()
[Theory]
[InlineData("DOCKER|mcr.microsoft.com/azure-functions/python", 3, 9, true)]
[InlineData("", 3, 7, false)]
- [InlineData("", 3, 6, true)]
[InlineData("PYTHON|3.6", 3, 6, true)]
[InlineData("PYTHON|3.6", 3, 7, false)]
[InlineData("PYTHON|3.7", 3, 6, false)]
@@ -54,6 +53,9 @@ public async void WorkerInfoRuntimeShouldBePython()
[InlineData("PYTHON|3.9", null, 9, false)]
[InlineData("PYTHON|3.9", 3, null, false)]
[InlineData("PYTHON|3.9", null, null, false)]
+ [InlineData("Python|3.10", 3, 10, true)]
+ [InlineData("Python|3.11", 3, 11, true)]
+ [InlineData("Python|3.12", 3, 12, true)]
public void ShouldHaveMatchingLinuxFxVersion(string linuxFxVersion, int major, int minor, bool expectedResult)
{
bool result = PythonHelpers.IsLinuxFxVersionRuntimeVersionMatched(linuxFxVersion, major, minor);
@@ -66,12 +68,13 @@ public void ShouldHaveMatchingLinuxFxVersion(string linuxFxVersion, int major, i
[Theory]
[InlineData("2.7.10", true)]
[InlineData("3.5.5", true)]
- [InlineData("3.6.8b", false)]
+ [InlineData("3.6.8b", true)]
[InlineData("3.7.2", false)]
[InlineData("3.8.0", false)]
[InlineData("3.9.0", false)]
[InlineData("3.10.0", false)]
[InlineData("3.11.0", false)]
+ [InlineData("3.12.0", false)]
public void AssertPythonVersion(string pythonVersion, bool expectException)
{
WorkerLanguageVersionInfo worker = new WorkerLanguageVersionInfo(WorkerRuntime.python, pythonVersion, "python");
@@ -93,11 +96,11 @@ public SkipIfPythonNonExistFact()
string[] pythons;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- pythons = new string[] { "python.exe", "python3.exe", "python36.exe", "python37.exe", "python38.exe", "python39.exe", "python310.exe", "python311.exe", "py.exe" };
+ pythons = new string[] { "python.exe", "python3.exe", "python37.exe", "python38.exe", "python39.exe", "python310.exe", "python311.exe", "python312.exe", "py.exe" };
}
else
{
- pythons = new string[] { "python", "python3", "python36", "python37", "python38", "python39", "python310", "python311" };
+ pythons = new string[] { "python", "python3", "python37", "python38", "python39", "python310", "python311", "python312" };
}
string pythonExe = pythons.FirstOrDefault(p => CheckIfPythonExist(p));