diff --git a/.github/workflows/python_bindings.yml b/.github/workflows/python_bindings.yml index df0db1f984..1985167a97 100644 --- a/.github/workflows/python_bindings.yml +++ b/.github/workflows/python_bindings.yml @@ -24,14 +24,14 @@ jobs: # fail-fast: Default is true, switch to false to allow one platform to fail and still run others fail-fast: false matrix: - name: [Ubuntu, macOS, macOS_arm64, Windows_py37, Windows_py38, Windows_py39, Windows_py310, Windows_py311, Windows_py312] + name: [Ubuntu, macOS, macOS_arm64, Windows_py37, Windows_py38, Windows_py39, Windows_py310, Windows_py311, Windows_py312, Windows_py313] include: - name: Ubuntu - os: ubuntu-20.04 + os: ubuntu-22.04 python-version: 3.8 allow_failure: false - name: macOS - os: macos-11 + os: macos-12 python-version: 3.8 allow_failure: false MACOSX_DEPLOYMENT_TARGET: 10.15 @@ -41,7 +41,7 @@ jobs: python-version: 3.8 allow_failure: false MACOSX_DEPLOYMENT_TARGET: 12.1 - SDKROOT: /Applications/Xcode_14.3.1.app + SDKROOT: /Applications/Xcode_15.2.app - name: Windows_py37 os: windows-2019 python-version: 3.7 @@ -65,19 +65,32 @@ jobs: - name: Windows_py312 os: windows-2019 python-version: '3.12' + allow_failure: false + - name: Windows_py313 + os: windows-2019 + python-version: '3.13' allow_failure: true # Possible this fails, don't care yet + steps: - uses: actions/checkout@v4 # with: # ref: develop - name: Set up Python ${{ matrix.python-version }} - id: setup-python + if: runner.os == 'macOS' + id: setup-python-macos # 3.10 is the first one to have a prebuilt binary for macos-14 (arm64) on the actions/setup-python, so I forked it and actions/python-versions to add 3.8 uses: jmarrec/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Set up Python ${{ matrix.python-version }} + if: runner.os != 'macOS' + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install System dependencies shell: bash run: | @@ -263,10 +276,18 @@ jobs: set -x begin_group "Conan install" + PYTHON_ARCH=x64 if [ "$RUNNER_OS" == "macOS" ]; then - # Avoid "builtin __has_nothrow_assign is deprecated; use __is_nothrow_assignable instead" in boost/1.79 with recent clang - conan install . --output-folder=./build --build=missing -c tools.cmake.cmaketoolchain:generator=Ninja -s compiler.cppstd=20 -s build_type=Release -o with_testing=False -o with_benchmark=False -c tools.build:cxxflags="['-D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION']" + PYTHON_VERSION=${{ steps.setup-python-macos.outputs.python-version }} + if [ "${{ matrix.name }}" == "macOS_arm64" ]; then + PYTHON_ARCH=arm64 + # Avoid "builtin __has_nothrow_assign is deprecated; use __is_nothrow_assignable instead" in boost/1.79 with recent clang + conan install . --output-folder=./build --build=missing -c tools.cmake.cmaketoolchain:generator=Ninja -s compiler.cppstd=20 -s build_type=Release -o with_testing=False -o with_benchmark=False -c tools.build:cxxflags="['-D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION -Wno-enum-constexpr-conversion']" + else + conan install . --output-folder=./build --build=missing -c tools.cmake.cmaketoolchain:generator=Ninja -s compiler.cppstd=20 -s build_type=Release -o with_testing=False -o with_benchmark=False -c tools.build:cxxflags="['-D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION']" + fi else + PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} conan install . --output-folder=./build --build=missing -c tools.cmake.cmaketoolchain:generator=Ninja -s compiler.cppstd=20 -s build_type=Release -o with_testing=False -o with_benchmark=False fi echo -e "::endgroup::" @@ -274,8 +295,8 @@ jobs: begin_group "CMake Configure" cmake --preset conan-release \ -DBUILD_PYTHON_BINDINGS:BOOL=ON -DBUILD_PYTHON_PIP_PACKAGE:BOOL=ON -DPYTHON_PIP_REPOSITORY:STRING=${{ env.PYTHON_PIP_REPOSITORY }} \ - -DPYTHON_VERSION:STRING=${{ steps.setup-python.outputs.python-version }} \ - -DPython_ROOT_DIR:PATH=$RUNNER_TOOL_CACHE/Python/${{ steps.setup-python.outputs.python-version }}/x64/ \ + -DPYTHON_VERSION:STRING=$PYTHON_VERSION \ + -DPython_ROOT_DIR:PATH=$RUNNER_TOOL_CACHE/Python/$PYTHON_VERSION/$PYTHON_ARCH/ \ -DBUILD_TESTING:BOOL=OFF -DBUILD_RUBY_BINDINGS:BOOL=${{ env.BUILD_RUBY_BINDINGS }} -DBUILD_CLI:BOOL=${{ env.BUILD_CLI }} echo -e "::endgroup::" @@ -309,7 +330,7 @@ jobs: upload_python_bindings_to_testpypi: needs: python_bindings name: Upload to TestPyPi - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Set up Python @@ -351,7 +372,7 @@ jobs: done; ls -R - python -m twine upload --skip-existing --repository testpypi dist/* + python -m twine upload --verbose --skip-existing --repository testpypi dist/* test_python_bindings: @@ -363,14 +384,14 @@ jobs: # fail-fast: Default is true, switch to false to allow one platform to fail and still run others fail-fast: false matrix: - name: [Ubuntu, macOS, macOS_arm64, Windows_py37, Windows_py38, Windows_py39, Windows_py310, Windows_py311, Windows_py312] + name: [Ubuntu, macOS, macOS_arm64, Windows_py37, Windows_py38, Windows_py39, Windows_py310, Windows_py311, Windows_py312, Windows_py313] include: - name: Ubuntu - os: ubuntu-20.04 + os: ubuntu-22.04 python-version: 3.11 # Voluntarily using a newer version than built with for Unix allow_failure: false - name: macOS - os: macos-11 + os: macos-12 python-version: 3.11 allow_failure: false - name: macOS_arm64 @@ -400,8 +421,11 @@ jobs: - name: Windows_py312 os: windows-2019 python-version: '3.12' + allow_failure: false + - name: Windows_py313 + os: windows-2019 + python-version: '3.13' allow_failure: true # Possible this fails, don't care yet - steps: - uses: actions/checkout@v4 @@ -438,7 +462,7 @@ jobs: if: contains(github.ref, 'refs/tags') needs: test_python_bindings name: Upload to PyPi - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Set up Python @@ -478,4 +502,4 @@ jobs: done; ls -R - python -m twine upload --skip-existing --repository pypi dist/* + python -m twine upload --verbose --skip-existing --repository pypi dist/* diff --git a/python/engine/PythonEngine.cpp b/python/engine/PythonEngine.cpp index 97e12250ba..a9b9514011 100644 --- a/python/engine/PythonEngine.cpp +++ b/python/engine/PythonEngine.cpp @@ -25,6 +25,17 @@ # pragma GCC diagnostic pop #endif +// >= 3.13.0 +// #if PY_VERSION_HEX >= 0x30d0000 +#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 12) +extern "C" +{ + // These functions was removed from Python 3.13 API but are still exported + // for the stable ABI. Until we upgrade to PyConfig, just keep using it + extern void Py_SetPath(const wchar_t* path); +} +#endif + namespace openstudio { void addToPythonPath(const openstudio::path& includePath) { diff --git a/python/module/openstudio.py b/python/module/openstudio.py index 70b72eadb5..62e8260b44 100644 --- a/python/module/openstudio.py +++ b/python/module/openstudio.py @@ -45,6 +45,12 @@ from .openstudioutilitiesxml import * else: + import os + if os.name == 'nt': + # When we're using system python to load the **installed** C:\openstudio-X.Y-Z\Python stuff (not PyPi package) + # This allows finding openstudiolib.dll and the msvc ones in the bin/ folder while we're in the Python/ folder + # Otherwise you'd have to manually copy these DLLs from bin/ to Python/ + os.add_dll_directory(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'bin'))) import openstudioairflow as airflow import openstudioenergyplus as energyplus import openstudioepjson as epjson