Skip to content

Commit 6d0d1fc

Browse files
authored
8.1 Deployment (#173)
2 parents 11fed04 + 084c7b0 commit 6d0d1fc

28 files changed

+95
-45
lines changed

.ci/BHoMBot/Nuget/BHoM.Interop.Python.nuspec

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
<dependency id="NETStandard.Library" version="2.0.3" />
2020
</group>
2121
</dependencies>
22+
<contentFiles>
23+
<files include="any\any\PythonEnvironment\**\*" buildAction="Content" copyToOutput="true" flatten="false"/>
24+
</contentFiles>
2225
</metadata>
2326
<files>
24-
<file src="C:\ProgramData\BHoM\Extensions\PythonCode\Python_Toolkit\src\python_toolkit\bhom\wrapped\**\*.*" exclude="**\__pycache__\*;**\docs\**\*" target="contentFiles\any\any\PythonCode\Python_Toolkit\src\python_toolkit\bhom\wrapped"/>
2527
<file src="C:\ProgramData\BHoM\Extensions\PythonCode\Python_Toolkit\src\**\*.*" exclude="**\__pycache__\*;**\docs\**\*" target="contentFiles\any\any\PythonEnvironment\Lib\site-packages" />
2628
<file src="licence/licence.txt" target="" />
2729
<file src="images/icon.png" target="" />

Python_Engine/Compute/BasePythonEnvironment.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -33,7 +33,6 @@ namespace BH.Engine.Python
3333
{
3434
public static partial class Compute
3535
{
36-
[PreviousVersion("8.0", "BH.Engine.Python.Compute.BasePythonEnvironment(System.Boolean, System.Boolean)")]
3736
[Description("Retrieve or reinstall the base Python Environment for BHoM workflows.")]
3837
[Input("version", "The target version of python to be installed or retrieved.")]
3938
[Input("reload", "Reload the base Python environment rather than recreating it, if it already exists.")]
@@ -79,3 +78,4 @@ public static PythonEnvironment BasePythonEnvironment(
7978
}
8079
}
8180

81+

Python_Engine/Compute/Download.cs

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -89,7 +89,6 @@ public static string DownloadFile(
8989

9090
/******************************************************/
9191

92-
[PreviousVersion("8.0", "BH.Engine.Python.Compute.DownloadPython(BH.oM.Python.Enums.PythonVersion, System.String)")]
9392
[Description("Download and install a specified version of python, and return the executable for it.")]
9493
[Input("version", "The version of python to download.")]
9594
[Output("pythonExecutable", "The executable (python.exe) for the python version that was installed")]
@@ -133,8 +132,19 @@ public static string DownloadPythonVersion(this PythonVersion version)
133132
}
134133
}
135134

136-
return Path.Combine(basePath, "python.exe");
135+
string pythonExePath = Path.Combine(basePath, "python.exe");
136+
137+
// It is possible for the installer to exit with ExitCode==0 without installing Python in the requested location. This can happen if the same version of Python appears to be installed elsewhere on the system. It can also happen if there was a 'dodgy' uninstall of a previous version. We've been unable to figure out where the installer is actually looking for existing installs. To fix dodgy uninstalls, run the installer again for the target version of Python (download links within EmbeddableURL.cs) and run a combination of 'repair' and 'uninstall' until it's gone. Installing the py launcher (via 'modify' in the installer) before attempting to uninstall could also help.
138+
139+
if (!File.Exists(pythonExePath))
140+
{
141+
BH.Engine.Base.Compute.RecordError($"The Python installer appears to have completed successfully, but \n{pythonExePath} does not exist. \nThis usually means that Python {version} already exists on your machine, but in a different location. \nThis toolkit is therefore unable to run any Python commands right now. \nTry uninstalling Python {version} from your system before running this BHoM method again.");
142+
return null;
143+
}
144+
145+
return pythonExePath;
137146
}
138147
}
139148
}
140149

150+

Python_Engine/Compute/InstallPackage.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -177,3 +177,4 @@ string packageDirectory
177177
}
178178
}
179179

180+

Python_Engine/Compute/Remove.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -81,7 +81,6 @@ public static void RemoveAllVirtualEnvironments()
8181
}
8282
}
8383

84-
[PreviousVersion("8.0", "BH.Engine.Python.Compute.RemoveBaseEnvironment()")]
8584
[Description("Remove the base install for the python version specified.")]
8685
[Input("version", "The base python version to remove.")]
8786
public static void RemoveBaseVersion(PythonVersion version = PythonVersion.v3_10)
@@ -139,3 +138,4 @@ public static void RemoveEverything()
139138
}
140139
}
141140

141+

Python_Engine/Compute/RequirementsTxt.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -85,3 +85,4 @@ public static string RequirementsTxt(
8585
}
8686
}
8787

88+

Python_Engine/Compute/Run.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -99,3 +99,4 @@ public static string RunPythonString(this oM.Python.PythonEnvironment env, strin
9999
}
100100
}
101101

102+

Python_Engine/Compute/UnzipFile.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -82,3 +82,4 @@ public static void UnzipFile(
8282
}
8383
}
8484

85+

Python_Engine/Compute/VirtualEnvironment.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -127,3 +127,4 @@ public static PythonEnvironment VirtualEnvironment(this PythonVersion version, s
127127
}
128128
}
129129

130+

Python_Engine/Convert/ToPython.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/*
1+
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -38,4 +38,4 @@ public static bool ToPython<T>(this T[,] input)
3838
return false;
3939
}
4040
}
41-
}
41+
}

Python_Engine/Modify/AddQuotesIfRequired.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -47,3 +47,4 @@ public static string AddQuotesIfRequired(this string path)
4747

4848

4949

50+

Python_Engine/Python/src/python_toolkit/bhom/analytics.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
import uuid
77
from functools import wraps
88
from typing import Any, Callable
9+
from datetime import datetime
910

1011
# pylint: enable=E0401
1112

1213
from .logging import ANALYTICS_LOGGER
1314
from .util import csharp_ticks
14-
from . import BHOM_VERSION, TOOLKIT_NAME
15+
from . import BHOM_VERSION, TOOLKIT_NAME, BHOM_LOG_FOLDER
1516

1617

1718
def bhom_analytics() -> Callable:
@@ -82,6 +83,12 @@ def wrapper(*args, **kwargs) -> Any:
8283
exec_metadata["Errors"].extend(sys.exc_info())
8384
raise exc
8485
finally:
86+
log_file = BHOM_LOG_FOLDER / f"{function.__module__.split('.')[0]}_{datetime.now().strftime('%Y%m%d')}.log"
87+
88+
if ANALYTICS_LOGGER.handlers[0].baseFilename != str(log_file):
89+
ANALYTICS_LOGGER.handlers[0].close()
90+
ANALYTICS_LOGGER.handlers[0].baseFilename = str(log_file)
91+
8592
ANALYTICS_LOGGER.info(
8693
json.dumps(exec_metadata, default=str, indent=None)
8794
)

Python_Engine/Python/src/python_toolkit/bhom/logging/file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
formatter = logging.Formatter("%(message)s")
1414
handler = RotatingFileHandler(
15-
BHOM_LOG_FOLDER / f"{TOOLKIT_NAME}_{datetime.now().strftime('%Y%m%d')}.log",
15+
str(BHOM_LOG_FOLDER / f"{TOOLKIT_NAME}_{datetime.now().strftime('%Y%m%d')}.log"),
1616
mode="a",
1717
maxBytes=25 * 1024 * 1024, # 25mb max before file overwritten
1818
backupCount=1,

Python_Engine/Python/src/python_toolkit/plot/heatmap.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def heatmap(
4444
day_time_matrix = (
4545
series.dropna()
4646
.to_frame()
47-
.pivot_table(columns=series.index.date, index=series.index.time)
47+
.pivot_table(columns=series.dropna().index.date, index=series.dropna().index.time)
4848
)
4949
x = mdates.date2num(day_time_matrix.columns.get_level_values(1))
5050
y = mdates.date2num(
@@ -53,11 +53,14 @@ def heatmap(
5353
z = day_time_matrix.values
5454

5555
if "mask" in kwargs:
56+
if not isinstance(kwargs["mask"], (list, np.ndarray, pd.Series)):
57+
raise TypeError("The type of 'mask' must be a list, numpy ndarray or pandas Series")
5658
if len(kwargs["mask"]) != len(series):
5759
raise ValueError(
5860
f"Length of mask ({len(kwargs['mask'])}) must match length of data ({len(series)})."
5961
)
60-
z = np.ma.masked_array(z, mask=kwargs.pop("mask"))
62+
mask_flip = pd.Series(kwargs.pop("mask")).to_frame().pivot_table(columns=series.index.date, index=series.index.time)
63+
z = np.ma.masked_array(z, mask=mask_flip)
6164

6265
# handle non-standard kwargs
6366
extend = kwargs.pop("extend", "neither")

Python_Engine/Python/src/python_toolkit/plot/utilities.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import base64
44
import colorsys
5+
import io
56
from pathlib import Path
67
from typing import Any
78
import copy
@@ -319,7 +320,7 @@ def base64_to_image(base64_string: str, image_path: Path) -> Path:
319320
base64_string = base64_string.split(";")[-1]
320321

321322
with open(Path(image_path), "wb") as fp:
322-
fp.write(base64.decodebytes(base64_string))
323+
fp.write(base64.decodebytes(base64_string.encode('utf-8')))
323324

324325
return image_path
325326

Python_Engine/Python/tests/__init__.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from pathlib import Path
22
import pandas as pd
3+
import matplotlib as mpl
4+
35

46
# identifier for all downstream processes
57
BASE_IDENTIFIER = "PythonBHoM_pytest"
@@ -9,4 +11,7 @@ def get_timeseries():
911
df = df.set_index(pd.to_datetime(df.index))
1012
return pd.Series(df["Value"], index=df.index)
1113

12-
TIMESERIES_COLLECTION = get_timeseries()
14+
TIMESERIES_COLLECTION = get_timeseries()
15+
16+
#use 'agg' for testing plot methods, as tkinter occasionally throws strange errors (missing component/library when component isn't missing) when the default backend is used only when using pytest
17+
mpl.use("agg")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
import pandas as pd
4+
import pytest
5+
from matplotlib.figure import Figure
6+
from pathlib import Path
7+
8+
from python_toolkit.plot.utilities import figure_to_base64, image_to_base64, base64_to_image, figure_to_image
9+
10+
def test_figure_round_trip():
11+
"""very simple test to check that base64 serialisation is working"""
12+
fig, ax = plt.subplots(1, 1)
13+
base64 = figure_to_base64(fig)
14+
assert isinstance(base64, str)
15+
16+
path = base64_to_image(base64, image_path = Path("tests/assets/temp.png").resolve())
17+
assert path.exists()
18+
19+
base64_2 = image_to_base64(path)
20+
path.unlink() #make sure to clean up after ourselves
21+
assert base64 == base64_2

Python_Engine/Python_Engine.csproj

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
32
<PropertyGroup>
43
<TargetFramework>netstandard2.0</TargetFramework>
54
<AssemblyVersion>8.0.0.0</AssemblyVersion>
@@ -8,14 +7,12 @@
87
<Authors>BHoM</Authors>
98
<Copyright>Copyright © https://github.com/BHoM</Copyright>
109
<RootNamespace>BH.Engine.Python</RootNamespace>
11-
<FileVersion>8.0.0.0</FileVersion>
10+
<FileVersion>8.1.0.0</FileVersion>
1211
<OutputPath>..\Build\</OutputPath>
1312
</PropertyGroup>
14-
1513
<ItemGroup>
1614
<ProjectReference Include="..\Python_oM\Python_oM.csproj" />
1715
</ItemGroup>
18-
1916
<ItemGroup>
2017
<Reference Include="BHoM">
2118
<SpecificVersion>False</SpecificVersion>
@@ -38,13 +35,10 @@
3835
<Private>False</Private>
3936
</Reference>
4037
</ItemGroup>
41-
4238
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
4339
<Exec Command="xcopy $(TargetDir)$(TargetFileName) $(ProgramData)\BHoM\Assemblies /Y" />
4440
</Target>
45-
4641
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
4742
<Exec Command="if not exist $(ProgramData)\BHoM\Extensions\PythonEnvironments mkdir $(ProgramData)\BHoM\Extensions\PythonEnvironments&#xD;&#xA;if not exist $(ProgramData)\BHoM\Extensions\PythonCode mkdir $(ProgramData)\BHoM\Extensions\PythonCode&#xD;&#xA; &#xD;&#xA;if exist $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) rmdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /S /Q&#xD;&#xA;mkdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName)&#xD;&#xA; &#xD;&#xA;robocopy $(ProjectDir)Python $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /mir /xf &quot;*.pyc&quot; &quot;*.ipynb&quot; /xd &quot;__*__&quot; &quot;.*&quot; &gt; output.log&#xD;&#xA;del output.log" />
4843
</Target>
49-
5044
</Project>

Python_Engine/Query/Directory.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -67,7 +67,6 @@ public static string DirectoryEnvironments()
6767
return dir;
6868
}
6969

70-
[PreviousVersion("8.0", "BH.Engine.Python.Query.DirectoryBaseEnvironment()")]
7170
[Description("The location where the base Python environment exists.")]
7271
[Input("version", "The python version to get the base environment for.")]
7372
[Output("path", "The location where the base Python environment exists.")]

Python_Engine/Query/EmbeddableURL.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -91,3 +91,4 @@ public static string EmbeddableURL(this PythonVersion version)
9191
}
9292

9393

94+

Python_Engine/Query/IsValidEnvironmentName.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -52,3 +52,4 @@ public static bool IsValidEnvironmentName(string name)
5252
}
5353

5454

55+

Python_Engine/Query/ToolkitName.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* This file is part of the Buildings and Habitats object Model (BHoM)
3-
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
44
*
55
* Each contributor holds copyright over their respective contributions.
66
* The project versioning (Git) records all such contribution source information.
@@ -39,3 +39,4 @@ public static string ToolkitName()
3939

4040

4141

42+

0 commit comments

Comments
 (0)