Skip to content

Commit

Permalink
CI and NumPy compatibility updates (CPJKU#540)
Browse files Browse the repository at this point in the history
* Increase minimum Python version
* Let CI continue with other Python versions if one fails
* Fix Cython and NumPy 2 compatiblity
* Replace imp library calls with importlib
* Adjust Python build and runtime dependencies to make them NumPy 2 compatible
* Fix NumPy 2.1 errors
* Deal with new copy behaviour of np.array() in NumPy 2
  • Loading branch information
jpauwels authored Aug 25, 2024
1 parent 0551aa8 commit 27f032e
Show file tree
Hide file tree
Showing 16 changed files with 47 additions and 35 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ jobs:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip' # caching pip dependencies
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}

# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
Expand All @@ -51,6 +51,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
6 changes: 3 additions & 3 deletions madmom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

import doctest

import pkg_resources
from importlib.metadata import distribution

# import all packages
from . import audio, evaluation, features, io, ml, models, processors, utils

# define a version variable
__version__ = pkg_resources.get_distribution("madmom").version
__version__ = distribution("madmom") .version

# Create a doctest output checker that optionally ignores the unicode string
# literal.
Expand Down Expand Up @@ -98,4 +98,4 @@ def check_output(self, want, got, optionflags):
doctest.OutputChecker = _OutputChecker

# keep namespace clean
del pkg_resources, doctest
del doctest
6 changes: 3 additions & 3 deletions madmom/evaluation/notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ def note_onset_evaluation(detections, annotations, window=WINDOW):
tp_, fp_, _, fn_, err_ = onset_evaluation(det[:, 0], ann[:, 0], window)
# convert returned arrays to lists and append the detections and
# annotations to the correct lists
tp = np.vstack((tp, det[np.in1d(det[:, 0], tp_)]))
fp = np.vstack((fp, det[np.in1d(det[:, 0], fp_)]))
fn = np.vstack((fn, ann[np.in1d(ann[:, 0], fn_)]))
tp = np.vstack((tp, det[np.isin(det[:, 0], tp_)]))
fp = np.vstack((fp, det[np.isin(det[:, 0], fp_)]))
fn = np.vstack((fn, ann[np.isin(ann[:, 0], fn_)]))
# append the note number to the errors
err_ = np.vstack((np.array(err_),
np.repeat(np.asarray([note]), len(err_)))).T
Expand Down
3 changes: 2 additions & 1 deletion madmom/evaluation/tempo.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ def sort_tempo(tempo):
Tempi sorted according to their strength.
"""
tempo = np.array(tempo, copy=False, ndmin=1)
if not isinstance(tempo, np.ndarray):
tempo = np.array(tempo, ndmin=1)
if tempo.ndim != 2:
raise ValueError('`tempo` has no strength information, cannot sort '
'them.')
Expand Down
3 changes: 2 additions & 1 deletion madmom/features/beats.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,8 @@ def process_online(self, activations, reset=True, **kwargs):
"""
# cast as 1-dimensional array
# Note: in online mode, activations are just float values
activations = np.array(activations, copy=False, subok=True, ndmin=1)
if not isinstance(activations, np.ndarray):
activations = np.array(activations, ndmin=1)
# reset to initial state
if reset:
self.reset()
Expand Down
8 changes: 4 additions & 4 deletions madmom/features/beats_hmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,17 +478,17 @@ def __init__(self, transition_models, transition_prob=None):
new_probabilities = []
for p in range(num_patterns):
# indices of states/prev_states/probabilities
idx = np.logical_and(np.in1d(prev_states, last_states[p]),
np.in1d(states, first_states[p]))
idx = np.logical_and(np.isin(prev_states, last_states[p]),
np.isin(states, first_states[p]))
# transition probability
prob = probabilities[idx]
# update transitions to same pattern with new probability
probabilities[idx] *= self.transition_prob[p, p]
# distribute that part among all other patterns
for p_ in np.setdiff1d(range(num_patterns), p):
idx_ = np.logical_and(
np.in1d(prev_states, last_states[p_]),
np.in1d(states, first_states[p_]))
np.isin(prev_states, last_states[p_]),
np.isin(states, first_states[p_]))
# make sure idx and idx_ have same length
if len(np.nonzero(idx)[0]) != len(np.nonzero(idx_)[0]):
raise ValueError('Cannot add transition between '
Expand Down
3 changes: 2 additions & 1 deletion madmom/features/onsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,8 @@ def process_online(self, activations, reset=True, **kwargs):
"""
# cast as 1-dimensional array
# Note: in online mode, activations are just float values
activations = np.array(activations, copy=False, subok=True, ndmin=1)
if not isinstance(activations, np.ndarray):
activations = np.array(activations, ndmin=1)
# buffer data
if self.buffer is None or reset:
# reset the processor
Expand Down
6 changes: 3 additions & 3 deletions madmom/features/tempo.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ def process_online(self, activations, reset=True, **kwargs):
Corresponding delays [frames].
"""

activations = np.array(activations, copy=False, subok=True, ndmin=1, dtype=float)
if not isinstance(activations, np.ndarray):
activations = np.array(activations, ndmin=1, dtype=float)
# reset to initial state
if reset:
self.reset()
Expand All @@ -402,7 +402,7 @@ def process_online(self, activations, reset=True, **kwargs):
# iterate over all activations
# Note: in online mode, activations are just float values, thus cast
# them as 1-dimensional array
for act in np.array(activations, copy=False, subok=True, ndmin=1):
for act in activations:
# online feed backward comb filter (y[n] = x[n] + α * y[n - τ])
y_n = act + self.alpha * self._comb_buffer[idx]
# shift output buffer with new value
Expand Down
1 change: 1 addition & 0 deletions madmom/ml/hmm.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import numpy as np

cimport numpy as np
cimport cython
np.import_array()

from numpy.math cimport INFINITY

Expand Down
2 changes: 1 addition & 1 deletion madmom/ml/nn/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ def activate(self, data, **kwargs):
Reshaped data.
"""
return np.reshape(data, self.newshape, self.order)
return np.reshape(data, self.newshape, order=self.order)


class AverageLayer(Layer):
Expand Down
2 changes: 1 addition & 1 deletion madmom/processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ def process(self, data, **kwargs):
ndmin = len(self.buffer_size)
# cast the data to have that many dimensions
if data.ndim < ndmin:
data = np.array(data, copy=False, subok=True, ndmin=ndmin)
data = np.array(data, ndmin=ndmin)
# length of the data
data_length = len(data)
# if length of data exceeds buffer length simply replace buffer data
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ requires = [
"setuptools",
"wheel",
"cython>=0.25",
"oldest-supported-numpy"
"numpy>2",
]
build-backend = "setuptools.build_meta"
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
# some PyPI metadata
classifiers = [
'Development Status :: 3 - Beta',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Environment :: Console',
'License :: OSI Approved :: BSD License',
'License :: Free for non-commercial use',
Expand All @@ -70,8 +70,7 @@
# requirements
requirements = [
'numpy>=1.13.4',
'scipy>=0.16',
'cython>=0.25',
'scipy>=1.13',
'mido>=1.2.6',
]

Expand Down
11 changes: 8 additions & 3 deletions tests/test_bin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

from __future__ import absolute_import, division, print_function

import imp
import os
import shutil
import sys
import tempfile
import types
import unittest
from importlib.machinery import SourceFileLoader
from os.path import join as pj

try:
Expand Down Expand Up @@ -45,7 +46,9 @@

def run_program(program):
# import module, capture stdout
test = imp.load_source('test', program[0])
loader = SourceFileLoader('test', program[0])
test = types.ModuleType(loader.name)
loader.exec_module(test)
sys.argv = program
backup = sys.stdout
sys.stdout = StringIO()
Expand Down Expand Up @@ -105,7 +108,9 @@ def run_load(program, infile, outfile, online=False, args=None):


def run_help(program):
test = imp.load_source('test', program)
loader = SourceFileLoader('test', program)
test = types.ModuleType(loader.name)
loader.exec_module(test)
sys.argv = [program, '-h']
try:
test.main()
Expand Down
7 changes: 5 additions & 2 deletions tests/test_bin_evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

from __future__ import absolute_import, division, print_function

import imp
import os
import sys
import types
import unittest
from importlib.machinery import SourceFileLoader

try:
from cStringIO import StringIO
Expand All @@ -30,7 +31,9 @@

def run_script(task, det_suffix=None, args=None):
# import module, capture stdout
test = imp.load_source('test', eval_script)
loader = SourceFileLoader('test', eval_script)
test = types.ModuleType(loader.name)
loader.exec_module(test)
sys.argv = [eval_script, task, '--csv', DETECTIONS_PATH, ANNOTATIONS_PATH]
if det_suffix:
sys.argv.extend(['-d', det_suffix])
Expand Down

0 comments on commit 27f032e

Please sign in to comment.