Skip to content
Merged
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: 6 additions & 9 deletions .github/workflows/doctest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@ jobs:
env:
OS: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: "3.11"
python-version: "3.13"
- name: Build myfm
run: |
pip install --upgrade pip
pip install numpy scipy pandas scikit-learn
pip install --upgrade pip scikit-build setuptools-scm nanobind
pip install .
curl http://files.grouplens.org/datasets/movielens/ml-100k.zip -o ~/.ml-100k.zip
- name: Run pytest
- name: install pytest
run: |
pip install pytest phmdoctest sphinx==4.4.0 sphinx_rtd_theme
pip install pytest phmdoctest sphinx==8.2.3 sphinx_rtd_theme scikit-learn
- name: Test Readme.md
run: |
GEN_TEST_FILE=phmdoctest_out.py
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ jobs:
env:
SKIP: no-commit-to-branch
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.0
- uses: actions/checkout@v4
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.0
30 changes: 14 additions & 16 deletions .github/workflows/run-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,35 @@ name: Test & Upload coverage
on: [push]
jobs:
run_pytest_upload_coverage:
permissions:
id-token: write
runs-on: ubuntu-latest
env:
OS: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build myfm
python-version: '3.13'
- name: Build myfm & test
run: |
pip install --upgrade pip
pip install numpy scipy pandas
sudo apt-get install lcov
FLAGS="-fprofile-arcs -ftest-coverage"
CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" pip install -e .
- name: Run pytest
run: |
pip install pytest pytest-cov pytest-mock
pip install --upgrade pip
pip install scikit-build setuptools-scm pytest pytest-cov pytest-mock nanobind
FLAGS="-O0 -fprofile-arcs -ftest-coverage -fprofile-update=atomic"
CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" pip install --editable .
pytest --cov=./src/myfm tests/
- name: Generate coverage (ubuntu)
run: |
coverage xml
lcov -d `pwd` -c -o coverage.info
lcov -d `pwd` -c -o coverage.info --ignore-errors source
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v5
with:
use_oidc: true
files: ./coverage.xml,./coverage.info
verbose: false
verbose: true
env_vars: OS,PYTHON
name: codecov-umbrella
fail_ci_if_error: false
159 changes: 35 additions & 124 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,160 +7,71 @@ on:
types:
- created
env:
cibuildwheel_version: "2.12.2"
cibuildwheel_version: '3.0.1'
jobs:
build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/checkout@v4
- uses: actions/setup-python@v3
name: Install Python
with:
python-version: "3.11"
python-version: '3.13'
- name: Build sdist
run: pip install pybind11 && python setup.py sdist
- uses: actions/upload-artifact@v2
run: pip install build && python -m build --sdist
- uses: actions/upload-artifact@v4
with:
path: dist/*.tar.gz
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
MACOSX_DEPLOYMENT_TARGET: "10.9"
CIBW_BUILD_VERBOSITY: "1"
CIBW_BUILD: "${{ matrix.cibw.build || '*' }}"
CIBW_SKIP: "${{ matrix.cibw.skip || '' }}"
CIBW_ENVIRONMENT: "${{ matrix.cibw.env || '' }}"
CIBW_TEST_COMMAND: "pytest {project}/tests"
CIBW_TEST_REQUIRES: pytest pytest-mock
CIBW_MANYLINUX_X86_64_IMAGE: "${{ matrix.cibw.manylinux_image }}"
CIBW_MANYLINUX_I686_IMAGE: "${{ matrix.cibw.manylinux_image }}"
CIBW_MANYLINUX_AARCH64_IMAGE: "${{ matrix.cibw.manylinux_image }}"
CIBW_ARCHS_LINUX: "${{ matrix.cibw.arch || 'auto' }}"
CIBW_ARCHS_MACOS: "${{ matrix.cibw.arch || 'auto' }}"
runs-on: ${{ matrix.runs-on }}
strategy:
matrix:
include:
- os: macos-10.15
name: mac
cibw:
arch: x86_64
build: "cp37* cp38*"

- os: macos-10.15
name: mac-arm
cibw:
arch: universal2
build: "cp39* cp310* cp311*"

- os: ubuntu-20.04
name: manylinux1
cibw:
build: "cp37*"
skip: "*musllinux*"
manylinux_image: manylinux2010
arch: auto64

- os: ubuntu-20.04
name: manylinux2014
cibw:
build: "cp38* cp39* cp310* cp311*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: auto64

- os: ubuntu-20.04
name: manylinux_aarch64_cp37
cibw:
build: "cp37*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: aarch64

- os: ubuntu-20.04
name: manylinux_aarch64_cp38
cibw:
build: "cp38*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: aarch64

- os: ubuntu-20.04
name: manylinux_aarch64_cp39
cibw:
build: "cp39*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: aarch64

- os: ubuntu-20.04
name: manylinux_aarch64_cp310
cibw:
build: "cp310*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: aarch64

- os: ubuntu-20.04
name: manylinux_aarch64_cp311
cibw:
build: "cp311*"
skip: "*musllinux*"
manylinux_image: manylinux2014
arch: aarch64

- os: windows-2019
name: win_amd64
architecture: x64
cibw:
skip: "cp36*"
build: "cp*win_amd64"

- os: linux-intel
runs-on: ubuntu-latest
- os: linux-arm
runs-on: ubuntu-24.04-arm
- os: windows-intel
runs-on: windows-latest
- os: macos-intel
runs-on: macos-13
- os: macos-arm
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-python@v2
name: Install Python
- name: register qemu
if: contains(matrix.cibw.arch, 'aarch64')
run: |
docker run --rm --privileged hypriot/qemu-register:v4.2.0
- name: Install cibuildwheel
run: python -m pip install cibuildwheel=="${{env.cibuildwheel_version}}"
- uses: actions/checkout@v4
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse

- uses: actions/upload-artifact@v2
uses: pypa/cibuildwheel@v3.0.1
env:
CIBW_PLATFORM: ${{ matrix.platform || 'auto' }}
- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl

upload_pypi:
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v4
with:
name: artifact
pattern: cibw-*
path: dist
merge-multiple: true
- name: Publish package to TestPyPI
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.TEST_PYPI_APITOKEN }}
packages_dir: dist/
repository_url: https://test.pypi.org/legacy/
packages-dir: dist/
repository-url: https://test.pypi.org/legacy/
verbose: true
skip_existing: true
skip-existing: true
attestations: false
- name: Publish package to PyPI
if: github.event_name == 'release'
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_APITOKEN }}
packages_dir: dist/
packages-dir: dist/
verbose: true
skip_existing: true
skip-existing: true
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ stubs/*

doc/source/api_reference/*.rst
.cache
src/myfm/_version.py

mise.toml

.venv
13 changes: 3 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,21 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
rev: v4.6.0
hooks:
- id: check-merge-conflict
- id: check-yaml
- id: end-of-file-fixer
- id: no-commit-to-branch
args: [--branch, main]
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
name: isort
- repo: https://github.com/psf/black
rev: 22.3.0
rev: 24.10.0
hooks:
- id: black
language_version: python3 # Should be a command that runs python3.6+
- repo: https://github.com/hadialqattan/pycln
rev: v1.1.0
hooks:
- id: pycln
args: [--config=pyproject.toml]
46 changes: 36 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)
cmake_minimum_required(VERSION 3.15...3.27)
project(myFM VERSION 0.1.0)

cmake_minimum_required(VERSION 3.0.0)
project(myfm)
if (CMAKE_VERSION VERSION_LESS 3.18)
set(DEV_MODULE Development)
else()
set(DEV_MODULE Development.Module)
endif()

set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS_INIT} -std=c++11 -fPIC")

add_subdirectory(pybind11)
include_directories(include eigen-3.3.7)
pybind11_add_module(_myfm src/bind.cpp src/Faddeeva.cc)
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/eigen-3.4.0")
file(DOWNLOAD https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.zip "${CMAKE_CURRENT_BINARY_DIR}/eigen-3.4.0.zip")
file(ARCHIVE_EXTRACT INPUT "${CMAKE_CURRENT_BINARY_DIR}/eigen-3.4.0.zip")
endif()

find_package(Threads REQUIRED)


include_directories("${CMAKE_BINARY_DIR}/eigen-3.4.0" cpp_source)
include_directories("${CMAKE_SOURCE_DIR}/include" cpp_source)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CPack)


# Detect the installed nanobind package and import it into CMake
find_package(Python 3.8 COMPONENTS Interpreter ${DEV_MODULE} REQUIRED)
execute_process(
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT)
find_package(nanobind CONFIG REQUIRED)

nanobind_add_module(_myfm cpp_source/bind.cpp cpp_source/Faddeeva.cc)

install(TARGETS _myfm LIBRARY DESTINATION myfm/)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ X_movie = movie_ohe.transform(
block_user = RelationBlock(user_indices, X_user)
block_movie = RelationBlock(movie_indices, X_movie)

fm = MyFMRegressor(rank=2).fit(None, ratings.rating, X_rel=[block_user, block_movie])
fm = MyFMRegressor(rank=2).fit(None, ratings.rating.values, X_rel=[block_user, block_movie])

prediction_df = pd.DataFrame([
dict(user_id=user_id,movie_id=movie_id,
Expand Down
4 changes: 3 additions & 1 deletion cpp_source/bind.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "declare_module.hpp"
#include <nanobind/nanobind.h>
#include <nanobind/nb_defs.h>

PYBIND11_MODULE(_myfm, m) {
NB_MODULE(_myfm, m) {
declare_functional<double>(m);
}
Loading
Loading