Skip to content

Commit

Permalink
Support Python 3.12 (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
fealho authored Apr 1, 2024
1 parent 27675a7 commit 1c088f3
Show file tree
Hide file tree
Showing 13 changed files with 475 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/end_to_end.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/minimum.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/numerical.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tutorials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
Expand Down
10 changes: 8 additions & 2 deletions copulas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import sys
import warnings
from copy import deepcopy
from importlib.metadata import entry_points
from operator import attrgetter

import numpy as np
import pandas as pd
from pkg_resources import iter_entry_points

EPSILON = np.finfo(np.float32).eps

Expand Down Expand Up @@ -311,7 +311,13 @@ def _get_addon_target(addon_path_name):
def _find_addons():
"""Find and load all copulas add-ons."""
group = 'copulas_modules'
for entry_point in iter_entry_points(group=group):
try:
eps = entry_points(group=group)
except TypeError:
# Load-time selection requires Python >= 3.10 or importlib_metadata >= 3.6
eps = entry_points().get(group, [])

for entry_point in eps:
try:
addon = entry_point.load()
except Exception: # pylint: disable=broad-exception-caught
Expand Down
17 changes: 10 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,25 @@ classifiers = [
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
]
keywords = [ 'copulas' ]
dynamic = ["version"]
license = { text = 'BSL-1.1' }
requires-python = '>=3.8,<3.12'
requires-python = '>=3.8,<3.13'
readme = 'README.md'
dependencies = [
"numpy>=1.20.0,<2;python_version<'3.10'",
"numpy>=1.23.3,<2;python_version>='3.10'",
"numpy>=1.23.3,<2;python_version>='3.10' and python_version<'3.12'",
"numpy>=1.26.0,<2;python_version>='3.12'",
"pandas>=1.1.3;python_version<'3.10'",
"pandas>=1.3.4;python_version>='3.10' and python_version<'3.11'",
"pandas>=1.5.0;python_version>='3.11'",
'plotly>=5.10.0,<6',
"scipy>=1.5.4,<2;python_version<'3.10'",
"scipy>=1.9.2,<2;python_version>='3.10'",
"scipy>=1.9.2,<2;python_version>='3.10' and python_version<'3.12'",
"scipy>=1.12.0,<2;python_version>='3.12'",
]

[project.urls]
Expand All @@ -47,14 +50,15 @@ version = {attr = 'copulas.__version__'}
[project.optional-dependencies]
tutorials = [
'markupsafe<=2.0.1',
'scikit-learn>=0.24,<1.2',
"scikit-learn>=0.24,<1.2;python_version<'3.10'",
"scikit-learn>=0.24,<1.5;python_version>='3.10'",
'jupyter>=1.0.0,<2',
]
test = [
'copulas[tutorials]',
'pytest>=6.2.5,<7',
'pytest-cov>=2.6.0,<3',
'pytest-rerunfailures>=9.0.0,<10',
'pytest-rerunfailures>=10.3,<15',
'rundoc>=0.4.3,<0.5',
'tomli>=2.0.0,<3',
]
Expand All @@ -65,7 +69,7 @@ dev = [
'pip>=9.0.1',
'build>=1.0.0,<2',
'bump-my-version>=0.18.3,<1',
'watchdog>=0.8.3,<0.11',
'watchdog>=1.0.1,<5',

# docs
'm2r>=0.2.0,<0.3',
Expand Down Expand Up @@ -164,7 +168,6 @@ namespaces = false
'*.png',
'*.gif'
]
'tests' = ['*']

[tool.setuptools.exclude-package-data]
'*' = [
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/bivariate/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_save(self, json_mock, open_mock):
instance.save('test.json')

# Check
assert open_mock.called_once_with('test.json', 'w')
open_mock.assert_called_once_with('test.json', 'w')
assert json_mock.called
compare_nested_dicts(json_mock.call_args[0][0], expected_content)

Expand All @@ -99,10 +99,10 @@ def test_load_from_file(self, json_mock, open_mock):
instance = Bivariate.load('somefile.json')

# Check
assert open_mock.called_once_with('test.json', 'r')
instance.copula_type == CopulaTypes.FRANK
instance.tau == -0.33333333333333337
instance.theta == -3.305771759329249
open_mock.assert_called_once_with('somefile.json')
assert instance.copula_type == CopulaTypes.FRANK
assert instance.tau == -0.33333333333333337
assert instance.theta == -3.305771759329249

@mock.patch('copulas.bivariate.clayton.Clayton.partial_derivative')
def test_partial_derivative_scalar(self, derivative_mock):
Expand Down
12 changes: 8 additions & 4 deletions tests/unit/multivariate/test_gaussian.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,15 @@ def test_sample(self, normal_mock):
# Check
assert result.equals(expected_result)

assert normal_mock.called_once_with(
np.zeros(instance.correlation.shape[0]),
instance.correlation,
5
np.testing.assert_array_equal(
normal_mock.call_args[0][0],
np.zeros(instance.correlation.shape[0])
)
np.testing.assert_array_equal(
normal_mock.call_args[0][1],
instance.correlation
)
assert normal_mock.call_args[1] == {'size': 5}

def test_sample_random_state(self):
"""When random_state is set the samples are the same."""
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/test___init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ def mock_copulas():
sys.modules['copulas'] = copulas_module


@patch.object(copulas, 'iter_entry_points')
@patch.object(copulas, 'entry_points')
def test__find_addons_module(entry_points_mock, mock_copulas):
"""Test loading an add-on."""
# Setup
Expand All @@ -452,7 +452,7 @@ def test__find_addons_module(entry_points_mock, mock_copulas):
assert mock_copulas.submodule.entry_name == 'entry_point'


@patch.object(copulas, 'iter_entry_points')
@patch.object(copulas, 'entry_points')
def test__find_addons_object(entry_points_mock, mock_copulas):
"""Test loading an add-on."""
# Setup
Expand All @@ -470,7 +470,7 @@ def test__find_addons_object(entry_points_mock, mock_copulas):


@patch('warnings.warn')
@patch('copulas.iter_entry_points')
@patch('copulas.entry_points')
def test__find_addons_bad_addon(entry_points_mock, warning_mock):
"""Test failing to load an add-on generates a warning."""
# Setup
Expand All @@ -493,7 +493,7 @@ def entry_point_error():


@patch('warnings.warn')
@patch('copulas.iter_entry_points')
@patch('copulas.entry_points')
def test__find_addons_wrong_base(entry_points_mock, warning_mock):
"""Test incorrect add-on name generates a warning."""
# Setup
Expand All @@ -514,7 +514,7 @@ def test__find_addons_wrong_base(entry_points_mock, warning_mock):


@patch('warnings.warn')
@patch('copulas.iter_entry_points')
@patch('copulas.entry_points')
def test__find_addons_missing_submodule(entry_points_mock, warning_mock):
"""Test incorrect add-on name generates a warning."""
# Setup
Expand All @@ -535,7 +535,7 @@ def test__find_addons_missing_submodule(entry_points_mock, warning_mock):


@patch('warnings.warn')
@patch('copulas.iter_entry_points')
@patch('copulas.entry_points')
def test__find_addons_module_and_object(entry_points_mock, warning_mock):
"""Test incorrect add-on name generates a warning."""
# Setup
Expand All @@ -556,7 +556,7 @@ def test__find_addons_module_and_object(entry_points_mock, warning_mock):


@patch('warnings.warn')
@patch.object(copulas, 'iter_entry_points')
@patch.object(copulas, 'entry_points')
def test__find_addons_missing_object(entry_points_mock, warning_mock, mock_copulas):
"""Test incorrect add-on name generates a warning."""
# Setup
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py39-lint, py3{8,9,10,11}-{readme,unit,end_to_end,numerical,minimum,tutorials}
envlist = py39-lint, py3{8,9,10,11,12}-{readme,unit,end_to_end,numerical,minimum,tutorials}

[testenv]
skipsdist = false
Expand Down
Loading

0 comments on commit 1c088f3

Please sign in to comment.