#13842 Python: Migrate from setup.py to pyproject.toml

Replace legacy setup.py packaging with modern pyproject.toml (PEP 517/518/621).
Version is dynamically resolved via setuptools attr: directive from rips/_version.py,
which CMake generates.

Consolidate requirements.txt, dev-requirements.txt, and build-requirements.txt
into pyproject.toml dependencies and [dev] optional-dependencies.
Consolidate rips/mypy.ini into [tool.mypy] section of pyproject.toml.
Update GitHub Actions workflow and CMakeLists.txt accordingly.
This commit is contained in:
Kristian Bendiksen
2026-05-21 08:32:45 +02:00
parent 182ea91e2e
commit 5486c615a1
12 changed files with 156 additions and 141 deletions
+3 -3
View File
@@ -106,7 +106,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r GrpcInterface/Python/build-requirements.txt
pip install -e GrpcInterface/Python[dev]
- name: Use MSVC (Windows)
if: contains(matrix.config.os, 'windows')
@@ -272,8 +272,8 @@ jobs:
shell: bash
run: |
${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m pip install mypy types-protobuf
cd GrpcInterface/Python/rips
${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m mypy *.py generated/generated_classes.py
cd GrpcInterface/Python
${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m mypy rips/*.py rips/generated/generated_classes.py
- name: Run pytest
if: matrix.config.execute-pytests
+5 -5
View File
@@ -199,8 +199,8 @@ endforeach(rips_proto)
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
configure_file(${CMAKE_SOURCE_DIR}/ApplicationLibCode/Adm/RiaVersionInfo.py.cmake
${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py)
configure_file(${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake
${GRPC_PYTHON_SOURCE_PATH}/setup.py)
configure_file(${GRPC_PYTHON_SOURCE_PATH}/rips/_version.py.cmake
${GRPC_PYTHON_SOURCE_PATH}/rips/_version.py)
endif()
list (APPEND GRPC_PYTHON_GENERATED_SOURCES ${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py)
@@ -208,7 +208,7 @@ list (APPEND GRPC_PYTHON_GENERATED_SOURCES ${GRPC_PYTHON_SOURCE_PATH}/rips/gener
file(GLOB GRPC_PYTHON_RIPS_SOURCES ${GRPC_PYTHON_SOURCE_PATH}/rips/*.py)
file(GLOB GRPC_PYTHON_EXAMPLE_SOURCES ${GRPC_PYTHON_SOURCE_PATH}/rips/PythonExamples/*.py)
file(GLOB GRPC_PYTHON_TEST_SOURCES ${GRPC_PYTHON_SOURCE_PATH}/rips/tests/*.py)
file(GLOB GRPC_PYTHON_OTHER_FILES "${GRPC_PYTHON_SOURCE_PATH}/setup.py" "${GRPC_PYTHON_SOURCE_PATH}/requirements.txt" "${GRPC_PYTHON_SOURCE_PATH}/README.md" "${GRPC_PYTHON_SOURCE_PATH}/LICENSE")
file(GLOB GRPC_PYTHON_OTHER_FILES "${GRPC_PYTHON_SOURCE_PATH}/pyproject.toml" "${GRPC_PYTHON_SOURCE_PATH}/README.md" "${GRPC_PYTHON_SOURCE_PATH}/LICENSE")
list(
APPEND
@@ -249,10 +249,10 @@ endif()
# install gRPC Python files
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND RESINSIGHT_GRPC_DOWNLOAD_PYTHON_MODULE)
message(STATUS "Installing Python modules (dev-requirements.txt)")
message(STATUS "Installing Python dev modules")
add_custom_command(
TARGET PipInstall
COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m pip install -r ${GRPC_PYTHON_SOURCE_PATH}/dev-requirements.txt )
COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m pip install -e ${GRPC_PYTHON_SOURCE_PATH}[dev] )
endif()
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND RESINSIGHT_GRPC_BUNDLE_PYTHON_MODULE)
-1
View File
@@ -4,7 +4,6 @@ generated
dist
build
rips.egg-info
setup.py
grpc
grpcio*
six*
@@ -1,8 +0,0 @@
grpcio
grpcio-tools
protobuf
wheel
typing-extensions
pytest
setuptools>=70.0.0 # not directly required, pinned by Snyk to avoid a vulnerability
packaging>=22.0 # https://github.com/pypa/setuptools/issues/4483
+8 -8
View File
@@ -1,19 +1,19 @@
######################################################################
# All this is based on the MANIFEST.in and setup.py in Python-folder
# All this is based on the MANIFEST.in and pyproject.toml in Python-folder
######################################################################
# 1. Make sure dist folder is clear
del dist/*
# 2. Update rips-version tag in setup.py (".N after ResInsight version"). This is generated from setup.py.cmake
# 2. Update rips-version tag in rips/_version.py (".N after ResInsight version"). This is generated from rips/_version.py.cmake
# So that you for instance have version 2019.08.1 of rips.
# 3. Build source distribution
python setup.py sdist
python -m build
# 4. Test upload to test.pypi.org. This requires a ResInsight testpypi-user and you will be prompted for username and password
python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
# 5. Test install rips module.
pip install --index-url https://test.pypi.org/simple/ rips
@@ -23,4 +23,4 @@ pip install --index-url https://test.pypi.org/simple/ rips
# These incremented versions are just for testpypi and you can reset back to the wanted version before real upload
# 9. Upload to real Pypi. This requires a ResInsight pypi-user.
python -m twine upload dist/*
python -m twine upload dist/*
@@ -1,7 +0,0 @@
grpcio
grpcio-tools
protobuf
wheel
typing-extensions
pytest
setuptools>=70.0.0 # not directly required, pinned by Snyk to avoid a vulnerability
+138
View File
@@ -0,0 +1,138 @@
[build-system]
requires = ["setuptools>=70.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "rips"
dynamic = ["version"]
description = "Python Interface for ResInsight"
readme = "README.md"
license = "GPL-3.0-or-later"
license-files = ["LICENSE"]
requires-python = ">=3.11"
authors = [{name = "Ceetron Solutions", email = "info@ceetronsolutions.com"}]
dependencies = [
"grpcio",
"protobuf",
"typing_extensions",
]
[project.optional-dependencies]
dev = [
"grpcio-tools",
"pytest",
"mypy",
"types-protobuf",
"packaging>=22.0",
]
[project.urls]
Homepage = "http://www.resinsight.org"
[tool.setuptools.dynamic]
version = {attr = "rips._version.__version__"}
[tool.setuptools.packages.find]
include = ["rips*"]
[tool.setuptools.package-data]
rips = [
"py.typed",
"*.py",
"generated/*.py",
"PythonExamples/*.py",
"tests/*.py",
]
[tool.mypy]
python_version = "3.11"
show_error_codes = true
show_column_numbers = true
strict = true
ignore_missing_imports = true
implicit_reexport = true
allow_redefinition = false
strict_optional = true
warn_no_return = true
warn_unused_configs = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_return_any = true
strict_equality = true
[[tool.mypy.overrides]]
module = "rips.grpc_retry_interceptor.*"
disable_error_code = ["misc", "no-untyped-def", "no-untyped-call"]
[[tool.mypy.overrides]]
module = "rips.pdmobject.*"
disable_error_code = ["assignment", "return-value", "call-arg", "no-untyped-def", "no-untyped-call", "no-any-return"]
[[tool.mypy.overrides]]
module = "rips.case.*"
disable_error_code = ["no-untyped-def", "no-any-return"]
[[tool.mypy.overrides]]
module = "rips.grid.*"
disable_error_code = ["no-untyped-def", "no-untyped-call"]
[[tool.mypy.overrides]]
module = "rips.gridcasegroup.*"
disable_error_code = ["no-any-return", "no-untyped-def"]
[[tool.mypy.overrides]]
module = "rips.project.*"
disable_error_code = ["no-untyped-def", "no-any-return", "attr-defined"]
[[tool.mypy.overrides]]
module = "rips.well_log.*"
disable_error_code = ["attr-defined", "no-any-return"]
[[tool.mypy.overrides]]
module = "rips.well_log_plot.*"
disable_error_code = ["no-any-return"]
[[tool.mypy.overrides]]
module = "rips.well_path_collection.*"
disable_error_code = ["attr-defined"]
[[tool.mypy.overrides]]
module = "rips.contour_map.*"
disable_error_code = ["no-redef"]
[[tool.mypy.overrides]]
module = "rips.plot.*"
disable_error_code = ["no-untyped-def"]
[[tool.mypy.overrides]]
module = "rips.view.*"
disable_error_code = ["no-untyped-def"]
[[tool.mypy.overrides]]
module = "rips.instance.*"
disable_error_code = ["no-untyped-def", "no-untyped-call", "attr-defined"]
[[tool.mypy.overrides]]
module = "rips.well_path.*"
disable_error_code = ["attr-defined"]
[[tool.mypy.overrides]]
module = "rips.simulation_well.*"
disable_error_code = ["no-any-return", "attr-defined"]
[[tool.mypy.overrides]]
module = "rips.generated.generated_classes.*"
disable_error_code = ["no-any-return"]
[[tool.mypy.overrides]]
module = "rips.surface.*"
disable_error_code = ["attr-defined", "no-any-return"]
[[tool.mypy.overrides]]
module = "rips.category_mapping.*"
disable_error_code = ["attr-defined", "no-any-return"]
-5
View File
@@ -1,5 +0,0 @@
grpcio
grpcio-tools
protobuf
wheel
typing-extensions
+1
View File
@@ -0,0 +1 @@
__version__ = "0.0.0.dev"
@@ -0,0 +1 @@
__version__ = "@RESINSIGHT_MAJOR_VERSION@.@RESINSIGHT_MINOR_VERSION@.@RESINSIGHT_PATCH_VERSION@.1"
-80
View File
@@ -1,80 +0,0 @@
[mypy]
# General configuration
python_version = 3.11
show_error_codes = True
show_column_numbers = True
# Try to make mypy as strict as possible
strict = True
ignore_missing_imports = True
implicit_reexport = True
allow_redefinition = False
strict_optional = True
warn_no_return = True
warn_unused_configs = True
disallow_any_generics = True
disallow_subclassing_any = True
disallow_untyped_calls = True
disallow_incomplete_defs = True
disallow_untyped_decorators = True
no_implicit_optional = True
warn_redundant_casts = True
warn_return_any = True
strict_equality = True
# Explicit exceptions where type definitions are incomplete
[mypy-rips.grpc_retry_interceptor.*]
disable_error_code = misc, no-untyped-def, no-untyped-call
[mypy-rips.pdmobject.*]
disable_error_code = assignment, return-value, call-arg, no-untyped-def, no-untyped-call, no-any-return
[mypy-rips.case.*]
disable_error_code = no-untyped-def, no-any-return
[mypy-rips.grid.*]
disable_error_code = no-untyped-def, no-untyped-call
[mypy-rips.gridcasegroup.*]
disable_error_code = no-any-return, no-untyped-def
[mypy-rips.project.*]
disable_error_code = no-untyped-def, no-any-return, attr-defined
[mypy-rips.well_log.*]
disable_error_code = attr-defined, no-any-return
[mypy-rips.well_log_plot.*]
disable_error_code = no-any-return
[mypy-rips.well_path_collection.*]
disable_error_code = attr-defined
[mypy-rips.contour_map.*]
disable_error_code = no-redef
[mypy-rips.plot.*]
disable_error_code = no-untyped-def
[mypy-rips.view.*]
disable_error_code = no-untyped-def
[mypy-rips.instance.*]
disable_error_code = no-untyped-def, no-untyped-call, attr-defined
[mypy-rips.well_path.*]
disable_error_code = attr-defined
[mypy-rips.simulation_well.*]
disable_error_code = no-any-return, attr-defined
[mypy-rips.generated.generated_classes.*]
disable_error_code = no-any-return
[mypy-rips.surface.*]
disable_error_code = attr-defined, no-any-return
[mypy-rips.category_mapping.*]
disable_error_code = attr-defined, no-any-return
-24
View File
@@ -1,24 +0,0 @@
from setuptools import setup, find_packages
with open('README.md') as f:
readme = f.read()
with open('LICENSE') as f:
license = f.read()
RIPS_DIST_VERSION = '1'
setup(
name='rips',
version='@RESINSIGHT_MAJOR_VERSION@.@RESINSIGHT_MINOR_VERSION@.@RESINSIGHT_PATCH_VERSION@.' + RIPS_DIST_VERSION,
description='Python Interface for ResInsight',
long_description=readme,
author='Ceetron Solutions',
author_email='info@ceetronsolutions.com',
url='http://www.resinsight.org',
license=license,
packages=['rips'],
package_data={'rips': ['py.typed', '*.py', 'generated/*.py', 'PythonExamples/*.py', 'tests/*.py']},
install_requires=['grpcio', 'protobuf', 'wheel', 'typing_extensions'],
python_requires='>=3.11',
)