diff --git a/CMakeLists.txt b/CMakeLists.txt index e53f375e9a..f19cc10502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -362,6 +362,9 @@ if(BUILD_PYTHON) "NOT BUILD_DEPS" ON) message(STATUS "Python: Build pybind11_protobuf: ${BUILD_pybind11_protobuf}") + option(GENERATE_PYTHON_STUB "Generate Python stub file (.pyi)" ON) + message(STATUS "Python: Generate stub file: ${GENERATE_PYTHON_STUB}") + CMAKE_DEPENDENT_OPTION(BUILD_PYTHON_DOC "Build the Python doc" OFF "NOT BUILD_DOC" ON) message(STATUS "Python: Build doc: ${BUILD_PYTHON_DOC}") diff --git a/bazel/notebook_requirements.in b/bazel/notebook_requirements.in index 385bd5f2ee..6a31d07b0b 100644 --- a/bazel/notebook_requirements.in +++ b/bazel/notebook_requirements.in @@ -5,6 +5,7 @@ protobuf==4.24.4 scipy==1.11.1 # OR-Tools build dependencies +mypy==1.6.1 mypy-protobuf==3.5.0 virtualenv==20.24.2 black==23.7.0 diff --git a/bazel/notebook_requirements.txt b/bazel/notebook_requirements.txt index 96cb767393..7a55294808 100644 --- a/bazel/notebook_requirements.txt +++ b/bazel/notebook_requirements.txt @@ -158,8 +158,12 @@ matplotlib-inline==0.1.6 # ipython mistune==3.0.1 # via nbconvert +mypy==1.6.1 + # via -r bazel/notebook_requirements.in mypy-extensions==1.0.0 - # via black + # via + # black + # mypy mypy-protobuf==3.5.0 # via -r bazel/notebook_requirements.in nbclient==0.8.0 @@ -340,6 +344,8 @@ traitlets==5.9.0 # qtconsole types-protobuf==4.24.0.0 # via mypy-protobuf +typing-extensions==4.8.0 + # via mypy tzdata==2023.3 # via pandas uri-template==1.3.0 diff --git a/bazel/ortools_requirements.in b/bazel/ortools_requirements.in index 180b6149fd..5f114deb95 100644 --- a/bazel/ortools_requirements.in +++ b/bazel/ortools_requirements.in @@ -5,6 +5,7 @@ protobuf==4.24.4 scipy==1.11.1 # OR-Tools build dependencies +mypy==1.6.1 mypy-protobuf==3.5.0 virtualenv==20.24.2 black==23.7.0 diff --git a/bazel/ortools_requirements.txt b/bazel/ortools_requirements.txt index 96cd33620e..960827bfbc 100644 --- a/bazel/ortools_requirements.txt +++ b/bazel/ortools_requirements.txt @@ -14,8 +14,12 @@ distlib==0.3.7 # via virtualenv filelock==3.12.2 # via virtualenv +mypy==1.6.1 + # via -r bazel/ortools_requirements.in mypy-extensions==1.0.0 - # via black + # via + # black + # mypy mypy-protobuf==3.5.0 # via -r bazel/ortools_requirements.in numpy==1.25.2 @@ -47,6 +51,8 @@ six==1.16.0 # via python-dateutil types-protobuf==4.24.0.0 # via mypy-protobuf +typing-extensions==4.8.0 + # via mypy tzdata==2023.3 # via pandas virtualenv==20.24.2 diff --git a/cmake/README.md b/cmake/README.md index 43fb96ec70..76c7dcca4c 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -253,6 +253,8 @@ cmake -S. -Bbuild -LH | `BUILD_FAT_JAR` | OFF | Build a `ortools-java` .jar that includes all of its own Maven dependencies, including the native package
Only available if `BUILD_JAVA=ON` | | | | | | `BUILD_pybind11` | `BUILD_DEPS` | Static build the pybind11 libraries
**Forced** to ON if `BUILD_DEPS=ON`
Only available if `BUILD_PYTHON=ON` | +| `BUILD_pybind11_protobuf` | `BUILD_DEPS` | Static build the pybind11_protobuf libraries
**Forced** to ON if `BUILD_DEPS=ON`
Only available if `BUILD_PYTHON=ON` | +| `GENERATE_PYTHON_STUB` | ON | Generate python stub files
Only available if `BUILD_PYTHON=ON` | | `BUILD_VENV` | `BUILD_TESTING` | Create python venv in `BINARY_DIR/python/venv`
**Forced** to ON if `BUILD_TESTING=ON`
Only available if `BUILD_PYTHON=ON` | | `VENV_USE_SYSTEM_SITE_PACKAGES` | OFF | Python venv can use system site package (e.g. `py3-numpy` on Alpine)
Only available if `BUILD_PYTHON=ON` and `BUILD_VENV=ON` | | `FETCH_PYTHON_DEPS` | `BUILD_DEPS` | Fetch python modules needed to build ortools package
Only available if `BUILD_PYTHON=ON` | diff --git a/cmake/python.cmake b/cmake/python.cmake index ed28516d53..6175596187 100644 --- a/cmake/python.cmake +++ b/cmake/python.cmake @@ -308,6 +308,56 @@ configure_file( ${PROJECT_BINARY_DIR}/python/README.txt COPYONLY) +# Generate Stub +if(GENERATE_PYTHON_STUB) +# Look for required python modules +search_python_module( + NAME mypy + PACKAGE mypy + NO_VERSION) + +find_program( + stubgen_EXECUTABLE + NAMES stubgen stubgen.exe + REQUIRED +) + +add_custom_command( + OUTPUT python/stub/timestamp + COMMAND ${CMAKE_COMMAND} -E remove_directory stub + COMMAND ${CMAKE_COMMAND} -E make_directory stub + COMMAND ${stubgen_EXECUTABLE} -p ortools.init.python.init --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.algorithms.python.knapsack_solver --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.graph.python.linear_sum_assignment --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.graph.python.max_flow --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.graph.python.min_cost_flow --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.constraint_solver.pywrapcp --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.linear_solver.pywraplp --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.linear_solver.python.model_builder_helper --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.pdlp.python.pdlp --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.sat.python.swig_helper --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.scheduling.python.rcpsp --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.util.python.sorted_interval_list --output . + COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR}/python/stub/timestamp + MAIN_DEPENDENCY + ortools/python/setup.py.in + DEPENDS + init_pybind11 + knapsack_solver_pybind11 + linear_sum_assignment_pybind11 + max_flow_pybind11 + min_cost_flow_pybind11 + pywrapcp + pywraplp + model_builder_helper_pybind11 + pdlp_pybind11 + swig_helper_pybind11 + rcpsp_pybind11 + sorted_interval_list_pybind11 + WORKING_DIRECTORY python + COMMAND_EXPAND_LISTS) +endif() + # Look for required python modules search_python_module( NAME setuptools @@ -357,6 +407,7 @@ add_custom_command( swig_helper_pybind11 rcpsp_pybind11 sorted_interval_list_pybind11 + $<$:python/stub/timestamp> BYPRODUCTS python/${PYTHON_PROJECT} python/${PYTHON_PROJECT}.egg-info diff --git a/ortools/python/setup.py.in b/ortools/python/setup.py.in index 05a0b056eb..f0e21ec3fb 100644 --- a/ortools/python/setup.py.in +++ b/ortools/python/setup.py.in @@ -50,21 +50,21 @@ setup( ], package_data={ '@PYTHON_PROJECT@':[$<$,SHARED_LIBRARY>:'.libs/*','../$'>], - '@PYTHON_PROJECT@.init.python':['$'], - '@PYTHON_PROJECT@.algorithms.python':['$'], + '@PYTHON_PROJECT@.init.python':['$', '*.pyi'], + '@PYTHON_PROJECT@.algorithms.python':['$', '*.pyi'], '@PYTHON_PROJECT@.bop':['*.pyi'], '@PYTHON_PROJECT@.glop':['*.pyi'], '@PYTHON_PROJECT@.graph.python':[ '$', '$', - '$' - ], + '$', + '*.pyi'], '@PYTHON_PROJECT@.constraint_solver':['$', '*.pyi'], '@PYTHON_PROJECT@.linear_solver':['$', '*.pyi'], '@PYTHON_PROJECT@.linear_solver.python':['$', '*.pyi'], '@PYTHON_PROJECT@.packing':['*.pyi'], '@PYTHON_PROJECT@.pdlp':['*.pyi'], - '@PYTHON_PROJECT@.pdlp.python':['$'], + '@PYTHON_PROJECT@.pdlp.python':['$', '*.pyi'], '@PYTHON_PROJECT@.sat':['*.pyi'], '@PYTHON_PROJECT@.sat.colab':['*.pyi'], '@PYTHON_PROJECT@.sat.python':['$', '*.pyi'],