Skip to content

Commit 1227690

Browse files
authored
Add support for running python projects (dotnet#4142)
* Add support for running python projects
1 parent a0c3ea0 commit 1227690

22 files changed

+746
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,6 @@ node_modules/
145145
/playground/**/azure.yaml
146146
/playground/**/next-steps.md
147147
*.svclog
148+
149+
# Python virtual environments
150+
.venv

Aspire.sln

+17
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consumer", "playground\kafk
474474
EndProject
475475
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Producer", "playground\kafka\Producer\Producer.csproj", "{FEE2F9B0-F32D-41B3-8917-0C13DE4F5953}"
476476
EndProject
477+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Python", "src\Aspire.Hosting.Python\Aspire.Hosting.Python.csproj", "{CC7EF6E9-1E06-4387-A52B-2101A85C2A77}"
478+
EndProject
477479
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "milvus", "milvus", "{BD2CD8FB-18EC-4930-8228-C49D89622022}"
478480
EndProject
479481
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MilvusPlayground.AppHost", "playground\milvus\MilvusPlayground.AppHost\MilvusPlayground.AppHost.csproj", "{CE3B7E15-2319-45CD-9CED-0017E306DE9A}"
@@ -496,6 +498,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WithDockerfile.AppHost", "p
496498
EndProject
497499
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Containers.Tests", "tests\Aspire.Hosting.Containers.Tests\Aspire.Hosting.Containers.Tests.csproj", "{588CD2D7-EE70-43C1-8233-330854BDF53C}"
498500
EndProject
501+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "python", "python", "{7123AB7A-A4FD-4F64-8B05-D2DD0C3E2ABC}"
502+
EndProject
503+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.AppHost", "playground\python\Python.AppHost\Python.AppHost.csproj", "{173BDA6E-F175-4457-BF64-58CD184E9A81}"
504+
EndProject
499505
Global
500506
GlobalSection(SolutionConfigurationPlatforms) = preSolution
501507
Debug|Any CPU = Debug|Any CPU
@@ -1266,6 +1272,10 @@ Global
12661272
{FEE2F9B0-F32D-41B3-8917-0C13DE4F5953}.Debug|Any CPU.Build.0 = Debug|Any CPU
12671273
{FEE2F9B0-F32D-41B3-8917-0C13DE4F5953}.Release|Any CPU.ActiveCfg = Release|Any CPU
12681274
{FEE2F9B0-F32D-41B3-8917-0C13DE4F5953}.Release|Any CPU.Build.0 = Release|Any CPU
1275+
{CC7EF6E9-1E06-4387-A52B-2101A85C2A77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1276+
{CC7EF6E9-1E06-4387-A52B-2101A85C2A77}.Debug|Any CPU.Build.0 = Debug|Any CPU
1277+
{CC7EF6E9-1E06-4387-A52B-2101A85C2A77}.Release|Any CPU.ActiveCfg = Release|Any CPU
1278+
{CC7EF6E9-1E06-4387-A52B-2101A85C2A77}.Release|Any CPU.Build.0 = Release|Any CPU
12691279
{CE3B7E15-2319-45CD-9CED-0017E306DE9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12701280
{CE3B7E15-2319-45CD-9CED-0017E306DE9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
12711281
{CE3B7E15-2319-45CD-9CED-0017E306DE9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -1302,6 +1312,10 @@ Global
13021312
{588CD2D7-EE70-43C1-8233-330854BDF53C}.Debug|Any CPU.Build.0 = Debug|Any CPU
13031313
{588CD2D7-EE70-43C1-8233-330854BDF53C}.Release|Any CPU.ActiveCfg = Release|Any CPU
13041314
{588CD2D7-EE70-43C1-8233-330854BDF53C}.Release|Any CPU.Build.0 = Release|Any CPU
1315+
{173BDA6E-F175-4457-BF64-58CD184E9A81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1316+
{173BDA6E-F175-4457-BF64-58CD184E9A81}.Debug|Any CPU.Build.0 = Debug|Any CPU
1317+
{173BDA6E-F175-4457-BF64-58CD184E9A81}.Release|Any CPU.ActiveCfg = Release|Any CPU
1318+
{173BDA6E-F175-4457-BF64-58CD184E9A81}.Release|Any CPU.Build.0 = Release|Any CPU
13051319
EndGlobalSection
13061320
GlobalSection(SolutionProperties) = preSolution
13071321
HideSolutionNode = FALSE
@@ -1528,6 +1542,7 @@ Global
15281542
{A39389A0-E780-4B97-808B-DC95CF59B35C} = {920BB263-E68F-4FA2-93FC-2E385EEA405B}
15291543
{7AA4C56C-3BB2-4FF0-BB03-F3F0D6A4FDAB} = {920BB263-E68F-4FA2-93FC-2E385EEA405B}
15301544
{FEE2F9B0-F32D-41B3-8917-0C13DE4F5953} = {920BB263-E68F-4FA2-93FC-2E385EEA405B}
1545+
{CC7EF6E9-1E06-4387-A52B-2101A85C2A77} = {B80354C7-BE58-43F6-8928-9F3A74AB7F47}
15311546
{BD2CD8FB-18EC-4930-8228-C49D89622022} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
15321547
{CE3B7E15-2319-45CD-9CED-0017E306DE9A} = {BD2CD8FB-18EC-4930-8228-C49D89622022}
15331548
{13219E70-5647-4B71-95DC-2C8AFA2A4C5D} = {BD2CD8FB-18EC-4930-8228-C49D89622022}
@@ -1539,6 +1554,8 @@ Global
15391554
{A6813855-E322-41EF-B2E6-7A44949EF962} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
15401555
{E6BE41D3-872C-47D2-B5B1-78C37AFAEAF9} = {A6813855-E322-41EF-B2E6-7A44949EF962}
15411556
{588CD2D7-EE70-43C1-8233-330854BDF53C} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
1557+
{7123AB7A-A4FD-4F64-8B05-D2DD0C3E2ABC} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
1558+
{173BDA6E-F175-4457-BF64-58CD184E9A81} = {7123AB7A-A4FD-4F64-8B05-D2DD0C3E2ABC}
15421559
EndGlobalSection
15431560
GlobalSection(ExtensibilityGlobals) = postSolution
15441561
SolutionGuid = {6DCEDFEC-988E-4CB3-B45B-191EB5086E0C}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project>
2+
3+
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
4+
5+
<!-- NOTE: This line is only required because we are using P2P references, not NuGet. It will not exist in real apps. -->
6+
<Import Project="../../../src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.props" />
7+
8+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project>
2+
3+
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
4+
5+
<!-- NOTE: These lines are only required because we are using P2P references, not NuGet. They will not exist in real apps. -->
6+
<Import Project="..\..\..\src\Aspire.Hosting.AppHost\build\Aspire.Hosting.AppHost.targets" />
7+
<Import Project="..\..\..\src\Aspire.Hosting.Sdk\SDK\Sdk.targets" />
8+
9+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
var builder = DistributedApplication.CreateBuilder(args);
5+
6+
builder.AddPythonProject("script-only", "../script_only", "main.py");
7+
builder.AddPythonProject("instrumented-script", "../instrumented_script", "main.py");
8+
9+
builder.Build().Run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": true,
8+
"applicationUrl": "http://localhost:15207",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development",
11+
"DOTNET_ENVIRONMENT": "Development",
12+
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16022",
13+
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17039",
14+
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
15+
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
16+
}
17+
},
18+
"generate-manifest": {
19+
"commandName": "Project",
20+
"launchBrowser": true,
21+
"dotnetRunMessages": true,
22+
"commandLineArgs": "--publisher manifest --output-path aspire-manifest.json",
23+
"applicationUrl": "http://localhost:15207",
24+
"environmentVariables": {
25+
"ASPNETCORE_ENVIRONMENT": "Development",
26+
"DOTNET_ENVIRONMENT": "Development",
27+
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16022"
28+
}
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<IsAspireHost>true</IsAspireHost>
9+
<UserSecretsId>10c36641-05e0-4bfb-ad9d-a588431430f1</UserSecretsId>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<Compile Include="$(SharedDir)KnownResourceNames.cs" Link="KnownResourceNames.cs" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\..\..\src\Aspire.Dashboard\Aspire.Dashboard.csproj" />
18+
<ProjectReference Include="..\..\..\src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj" IsAspireProjectResource="false" />
19+
<ProjectReference Include="..\..\..\src\Aspire.Hosting.Python\Aspire.Hosting.Python.csproj" IsAspireProjectResource="false" />
20+
</ItemGroup>
21+
22+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning",
6+
"Aspire.Hosting.Dcp": "Warning"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"$schema": "https://json.schemastore.org/aspire-8.0.json",
3+
"resources": {
4+
"script-only": {
5+
"type": "dockerfile.v0",
6+
"path": "../script_only/Dockerfile",
7+
"context": "../script_only"
8+
},
9+
"instrumented-script": {
10+
"type": "dockerfile.v0",
11+
"path": "../instrumented_script/Dockerfile",
12+
"context": "../instrumented_script",
13+
"env": {
14+
"OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "true"
15+
}
16+
}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import logging
2+
3+
# Reset the logging configuration to a sensible default.
4+
logging.basicConfig()
5+
logging.getLogger().setLevel(logging.NOTSET)
6+
7+
# Write a basic log message.
8+
logging.getLogger(__name__).info("Hello world!")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
opentelemetry-distro[otlp]

playground/python/script_only/main.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import logging
2+
3+
# Reset the logging configuration to a sensible default.
4+
logging.basicConfig()
5+
logging.getLogger().setLevel(logging.NOTSET)
6+
7+
# Write a basic log message.
8+
logging.getLogger(__name__).info("Hello world!")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(NetCurrent)</TargetFramework>
5+
<IsPackable>true</IsPackable>
6+
<PackageTags>aspire hosting python</PackageTags>
7+
<Description>Python support for .NET Aspire.</Description>
8+
<MinCodeCoverage>80</MinCodeCoverage>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<Compile Include="$(SharedDir)PathNormalizer.cs" Link="Utils\PathNormalizer.cs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\Aspire.Hosting\Aspire.Hosting.csproj" />
17+
</ItemGroup>
18+
19+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#nullable enable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#nullable enable
2+
Aspire.Hosting.Python.PythonProjectResource
3+
Aspire.Hosting.Python.PythonProjectResource.PythonProjectResource(string! name, string! executablePath, string! projectDirectory) -> void
4+
Aspire.Hosting.PythonProjectResourceBuilderExtensions
5+
static Aspire.Hosting.PythonProjectResourceBuilderExtensions.AddPythonProject(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! projectDirectory, string! scriptPath, params string![]! scriptArgs) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<Aspire.Hosting.Python.PythonProjectResource!>!
6+
static Aspire.Hosting.PythonProjectResourceBuilderExtensions.AddPythonProject(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, string! projectDirectory, string! scriptPath, string! virtualEnvironmentPath, params string![]! scriptArgs) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<Aspire.Hosting.Python.PythonProjectResource!>!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Aspire.Hosting.ApplicationModel;
5+
6+
namespace Aspire.Hosting.Python;
7+
8+
/// <summary>
9+
/// A resource that represents a Python project.
10+
/// </summary>
11+
/// <param name="name">The name of the resource.</param>
12+
/// <param name="executablePath">The path to the executable used to run the python project.</param>
13+
/// <param name="projectDirectory">The path to the directory containing the python project.</param>
14+
public class PythonProjectResource(string name, string executablePath, string projectDirectory)
15+
: ExecutableResource(name, executablePath, projectDirectory)
16+
{
17+
18+
}

0 commit comments

Comments
 (0)