Skip to content

Migrate to pyproject and tox #242

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ jobs:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
python3 -c "import precice"

setup_test:
name: Run setup test
run_tox:
name: Run tox
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
Expand All @@ -65,16 +65,15 @@ jobs:
cd precice-core
mkdir build && cd build
cmake .. -DPRECICE_FEATURE_MPI_COMMUNICATION=OFF -DPRECICE_FEATURE_PETSC_MAPPING=OFF -DPRECICE_FEATURE_PYTHON_ACTIONS=OFF -DBUILD_TESTING=OFF
- name: Install dependencies
run: |
python3 -c 'import toml; c = toml.load("pyproject.toml"); print("\n".join(c["build-system"]["requires"]))' | pip3 install -r /dev/stdin
- name: Run setup test
- name: Install tox
run: pip install tox
- name: Run tox
env:
PKG_CONFIG_PATH: "precice-core/build"
PKG_CONFIG_SYSTEM_INCLUDE_PATH: 1
run: |
export CFLAGS=-I$GITHUB_WORKSPACE
python3 setup.py test
export PKG_CONFIG_PATH=$(readlink -f "precice-core/build")
tox
Copy link
Member Author

Choose a reason for hiding this comment

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

We can probably replace a substantial part of the workflow with tox itself.


pip_install:
name: Run pip install
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ include LICENSE.txt
include cyprecice/*.pyx
include cyprecice/*.pxd
include test/test_bindings_module.py
include versioneer.py
include precice/_version.py
32 changes: 30 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
[build-system]
# PEP 518 - minimum build system requirements
requires = ["setuptools>=61,<72", "wheel", "Cython>=0.29", "packaging", "pip>=19.0.0", "numpy", "mpi4py", "pkgconfig"]
requires = ["setuptools>=61", "wheel", "Cython>=0.29", "packaging", "pip>=19.0.0", "numpy", "mpi4py", "pkgconfig", "setuptools-git-versioning"]
Copy link
Member Author

Choose a reason for hiding this comment

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

I am not sure which minimum version of setuptools we need.
Also pip can most likely go.

build-backend = "setuptools.build_meta"

[project]
name = "pyprecice"
dynamic = [ "version" ]
readme = "README.md"
description="Python language bindings for the preCICE coupling library"
license = "LGPL-3.0"
Copy link
Member Author

Choose a reason for hiding this comment

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

Is it LGPL-3.0 or LGPL-3.0-or-later?

license-files = ["LICENSE.txt"]

requires-python = ">= 3.10"
dependencies = [
"numpy",
"mpi4py", # mpi4py is only needed, if preCICE was compiled with MPI see https://github.com/precice/python-bindings/issues/8
]

authors = [
{name = "the preCICE developers", email = "[email protected]"},
]

[project.urls]
Repository = "https://github.com/precice/python-bindings.git"
Issues = "https://github.com/precice/python-bindings/issues"
Copy link
Member Author

Choose a reason for hiding this comment

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


[tool.setuptools-git-versioning]
enabled = true

[tool.setuptools]
packages = ["precice"]
21 changes: 0 additions & 21 deletions setup.cfg

This file was deleted.

134 changes: 15 additions & 119 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,63 +1,13 @@
import os
import sys
import warnings
import versioneer

uses_pip = "pip" in __file__

if uses_pip:
# If installed with pip we need to check its version
try:
import pip
except ModuleNotFoundError:
raise Exception(
"It looks like you are trying to use pip for installation of the package, but pip is not "
"installed on your system (or cannot be found). This can lead to problems with missing "
"dependencies. Please make sure that pip is discoverable. Try python3 -c 'import pip'. "
"Alternatively, you can also run python3 setup.py install --user.")
try:
from packaging import version
except ModuleNotFoundError:
warnings.warn(
"It looks like you are trying to use pip for installation of the package. Please install, "
"the module packaging by running 'pip3 install --user packaging', since it is needed to perform "
"additional security checks. You can continue installation. However, if you face problems when "
"installing or running pyprecice, it might be a good idea to install packaging to enable "
"additional checks.")
if "pip" in sys.modules and "packaging" in sys.modules:
if version.parse(pip.__version__) < version.parse("19.0"):
# version 19.0 is required, since we are using pyproject.toml for definition of build-time depdendencies.
# See https://pip.pypa.io/en/stable/news/#id209
raise Exception(
"You are using pip version {}. However, pip version >= 19.0 is required. Please upgrade "
"your pip installation via 'pip3 install --upgrade pip'. You might have to add the --user"
" flag.".format(pip.__version__))

import pathlib
from setuptools import setup
from setuptools.command.test import test
from setuptools.command.install import install
from Cython.Distutils.extension import Extension
from Cython.Distutils.build_ext import new_build_ext as build_ext
from Cython.Build import cythonize
import numpy
import pkgconfig
import os


# name of Interfacing API
APPNAME = "pyprecice"

PYTHON_BINDINGS_PATH = os.path.dirname(os.path.abspath(__file__))


def get_extensions(is_test):
compile_args = []
link_args = []
compile_args.append("-std=c++17")
include_dirs = [numpy.get_include()]

bindings_sources = [os.path.join(PYTHON_BINDINGS_PATH, "cyprecice",
"cyprecice" + ".pyx")]

def get_extensions():
if not pkgconfig.exists('libprecice'):
raise Exception("\n".join([
"pkg-config was unable to find libprecice.",
Expand All @@ -67,13 +17,17 @@ def get_extensions(is_test):

print("Found preCICE version " + pkgconfig.modversion('libprecice'))

compile_args = ["-std=c++17"]
link_args = []
include_dirs = [numpy.get_include()]
bindings_sources = ["cyprecice/cyprecice.pyx"]
compile_args += pkgconfig.cflags('libprecice').split()

if not is_test:
if os.environ.get('TOX_ENV_NAME') is not None:
Copy link
Member Author

@fsimonis fsimonis Jul 3, 2025

Choose a reason for hiding this comment

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

We currently use TOX_ENV_NAME to detect a testing scenario.
Maybe an env like PYPRECICE_MOCKED would be a better fit to simplify testing outside of tox environments.

Furthermore, this currently blocks us from running the solverdummies as a normal pytest in a tox environment.

print("Builing mocked pyprecice as we are in a tox environment")
bindings_sources.append("test/Participant.cpp")
else:
link_args += pkgconfig.libs('libprecice').split()
if is_test:
bindings_sources.append(os.path.join(PYTHON_BINDINGS_PATH, "test",
"Participant.cpp"))

return [
Extension(
Expand All @@ -89,67 +43,9 @@ def get_extensions(is_test):
]


class my_build_ext(build_ext, object):
def finalize_options(self):
try:
self.distribution.is_test
except AttributeError:
self.distribution.is_test = False

if not self.distribution.ext_modules:
self.distribution.ext_modules = cythonize(
get_extensions(self.distribution.is_test),
compiler_directives={'language_level': "3"})

super().finalize_options()


class my_install(install, object):
def finalize_options(self):
try:
self.distribution.is_test
except AttributeError:
self.distribution.is_test = False

if not self.distribution.ext_modules:
self.distribution.ext_modules = cythonize(
get_extensions(self.distribution.is_test),
compiler_directives={'language_level': "3"})

super().finalize_options()


class my_test(test, object):
def initialize_options(self):
self.distribution.is_test = True
super().initialize_options()


this_directory = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

my_cmdclass = {
'test': my_test,
'build_ext': my_build_ext,
'install': my_install}

# build precice.so python extension to be added to "PYTHONPATH" later
setup(
name=APPNAME,
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(my_cmdclass),
description='Python language bindings for the preCICE coupling library',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/precice/python-bindings',
author='the preCICE developers',
author_email='[email protected]',
license='LGPL-3.0',
python_requires='>=3',
install_requires=['numpy', 'mpi4py', 'Cython'],
# mpi4py is only needed, if preCICE was compiled with MPI
# see https://github.com/precice/python-bindings/issues/8
packages=['precice'],
zip_safe=False # needed because setuptools are used
ext_modules=cythonize(
get_extensions(),
compiler_directives={'language_level': "3"}
)
)
13 changes: 13 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[tox]
env_list =
py3
minversion = 4.23.2

[testenv]
description = run the tests with pytest
package = sdist
wheel_build_env = .pkg
deps =
pytest>=6
commands =
pytest {tty:--color=yes} {posargs}
Loading