From d32329ec0be1109f180b06a6580d63b85d12f4fc Mon Sep 17 00:00:00 2001 From: Aaron Meyer <2065146+aarmey@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:16:36 -0700 Subject: [PATCH] =?UTF-8?q?Upgrade=20Python=20versions=20to=203.9=E2=80=93?= =?UTF-8?q?3.13=20(#576)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Upgrade python versions * pyupgrade recommendations * Stick with py 3.12 for now * py 3.13 is now out --- .github/workflows/deploy_pypi.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 8 ++++---- doc/conf.py | 5 ++--- doc/minify.py | 4 ++-- examples/decomposition/plot_nn_cp_hals.py | 6 +++--- examples/decomposition/plot_nn_tucker.py | 6 +++--- examples/decomposition/plot_parafac2.py | 1 - examples/plot_tensor.py | 5 ++--- examples/regression/plot_cp_regression.py | 2 +- examples/regression/plot_tucker_regression.py | 6 +++--- examples/sparse_parafac.ipynb | 6 ++---- tensorly/backend/__init__.py | 2 +- tensorly/backend/core.py | 2 +- tensorly/contrib/decomposition/_tt_cross.py | 8 ++------ tensorly/contrib/decomposition/tests/test_tt_TTOI.py | 1 - tensorly/contrib/sparse/backend/numpy_backend.py | 2 +- tensorly/random/base.py | 8 ++------ tensorly/tenalg/proximal.py | 4 ++-- tensorly/tenalg/tests/test_batched_tensordot.py | 4 ++-- tensorly/tenalg/tests/test_outer_product.py | 2 +- tensorly/tt_tensor.py | 8 ++------ tensorly/utils/deprecation.py | 4 ++-- tensorly/utils/tests/test_deprecation.py | 2 +- 24 files changed, 41 insertions(+), 59 deletions(-) diff --git a/.github/workflows/deploy_pypi.yml b/.github/workflows/deploy_pypi.yml index 9b5ee2393..24c1d8e4a 100644 --- a/.github/workflows/deploy_pypi.yml +++ b/.github/workflows/deploy_pypi.yml @@ -16,7 +16,7 @@ jobs: - name: Install Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2c5c58a73..45e0a81fb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e0c79603e..9c717ee85 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,13 +12,13 @@ jobs: BACKEND: ['numpy', 'pytorch', 'paddle'] python-version: ['3.12'] include: - - BACKEND: 'numpy' - python-version: '3.8' - BACKEND: 'numpy' python-version: '3.9' + - BACKEND: 'numpy' + python-version: '3.11' TENSORLY_TENALG_BACKEND: ['einsum'] - BACKEND: 'jax' - python-version: '3.12' + python-version: '3.13' TENSORLY_TENALG_BACKEND: ['einsum'] - BACKEND: 'tensorflow' python-version: '3.12' @@ -67,7 +67,7 @@ jobs: TENSORLY_BACKEND=${{matrix.BACKEND}} pytest -vv --cov tensorly --cov-report xml --durations=10 tensorly - name: Check coverage with CodeCov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./coverage.xml verbose: true diff --git a/doc/conf.py b/doc/conf.py index 6f30186a4..b025bd4a9 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # tensorly documentation build configuration file # @@ -75,9 +74,9 @@ master_doc = "index" # General information about the project. -project = u'tensorly' +project = 'tensorly' year = datetime.now().year -copyright = "2016 - {}, TensorLy Developers".format(year) +copyright = f"2016 - {year}, TensorLy Developers" author = "Jean Kossaifi" # The version info for the project you're documenting, acts as replacement for diff --git a/doc/minify.py b/doc/minify.py index 29044e721..d05667783 100644 --- a/doc/minify.py +++ b/doc/minify.py @@ -12,7 +12,7 @@ if ".min." in str(path): continue target_path = path.with_suffix(".min.js") - with open(path.as_posix(), "r") as f: + with open(path.as_posix()) as f: text = f.read() minified = jsmin(text, mangle=True, mangle_toplevel=True) with open(target_path.as_posix(), "w") as f: @@ -23,7 +23,7 @@ if ".min." in str(path): continue target_path = path.with_suffix(".min.css") - with open(path.as_posix(), "r") as f: + with open(path.as_posix()) as f: text = f.read() minified = cssmin(text) with open(target_path.as_posix(), "w") as f: diff --git a/examples/decomposition/plot_nn_cp_hals.py b/examples/decomposition/plot_nn_cp_hals.py index 9ba8bdb54..98e3b7d27 100644 --- a/examples/decomposition/plot_nn_cp_hals.py +++ b/examples/decomposition/plot_nn_cp_hals.py @@ -119,9 +119,9 @@ # ----------------------- # First comparison option is processing time for each algorithm: -print(str("{:.2f}".format(time_mu)) + " " + "seconds") -print(str("{:.2f}".format(time_hals)) + " " + "seconds") -print(str("{:.2f}".format(time_exact_hals)) + " " + "seconds") +print(str(f"{time_mu:.2f}") + " " + "seconds") +print(str(f"{time_hals:.2f}") + " " + "seconds") +print(str(f"{time_exact_hals:.2f}") + " " + "seconds") ############################################################################## # As it is expected, the exact solution takes much longer than the approximate diff --git a/examples/decomposition/plot_nn_tucker.py b/examples/decomposition/plot_nn_tucker.py index eee5e13fe..d91f057f3 100644 --- a/examples/decomposition/plot_nn_tucker.py +++ b/examples/decomposition/plot_nn_tucker.py @@ -109,9 +109,9 @@ # To compare the various methods, first we may look at each algorithm # processing time: -print("time for tensorly nntucker:" + " " + str("{:.2f}".format(time_mu))) -print("time for HALS with fista:" + " " + str("{:.2f}".format(time_fista))) -print("time for HALS with as:" + " " + str("{:.2f}".format(time_as))) +print("time for tensorly nntucker:" + " " + str(f"{time_mu:.2f}")) +print("time for HALS with fista:" + " " + str(f"{time_fista:.2f}")) +print("time for HALS with as:" + " " + str(f"{time_as:.2f}")) ############################################################################## # All algorithms should run with about the same number of iterations on our diff --git a/examples/decomposition/plot_parafac2.py b/examples/decomposition/plot_parafac2.py index 2a5810e5a..b64074dc7 100644 --- a/examples/decomposition/plot_parafac2.py +++ b/examples/decomposition/plot_parafac2.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Demonstration of PARAFAC2 diff --git a/examples/plot_tensor.py b/examples/plot_tensor.py index 127e87469..a92330e80 100644 --- a/examples/plot_tensor.py +++ b/examples/plot_tensor.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Basic tensor operations ======================= @@ -13,12 +12,12 @@ ########################################################################### # A tensor is simply a numpy array tensor = tl.tensor(np.arange(24).reshape((3, 4, 2))) -print("* original tensor:\n{}".format(tensor)) +print(f"* original tensor:\n{tensor}") ########################################################################### # Unfolding a tensor is easy for mode in range(tensor.ndim): - print("* mode-{} unfolding:\n{}".format(mode, tl.unfold(tensor, mode))) + print(f"* mode-{mode} unfolding:\n{tl.unfold(tensor, mode)}") ########################################################################### # Re-folding the tensor is as easy: diff --git a/examples/regression/plot_cp_regression.py b/examples/regression/plot_cp_regression.py index 346a48907..48f95ab5b 100644 --- a/examples/regression/plot_cp_regression.py +++ b/examples/regression/plot_cp_regression.py @@ -67,7 +67,7 @@ ax.set_axis_off() if i == 0: - ax.set_title("Learned\nrank = {}".format(rank)) + ax.set_title(f"Learned\nrank = {rank}") plt.suptitle("CP tensor regression") plt.show() diff --git a/examples/regression/plot_tucker_regression.py b/examples/regression/plot_tucker_regression.py index 1d61a0b17..d9c21c54e 100644 --- a/examples/regression/plot_tucker_regression.py +++ b/examples/regression/plot_tucker_regression.py @@ -31,7 +31,7 @@ for i, pattern in enumerate(patterns): - print("fitting pattern n.{}".format(i)) + print(f"fitting pattern n.{i}") # Generate the original image weight_img = gen_image( @@ -50,7 +50,7 @@ ax.set_title("Original\nweights") for j, rank in enumerate(ranks): - print("fitting for rank = {}".format(rank)) + print(f"fitting for rank = {rank}") # Create a tensor Regressor estimator estimator = TuckerRegressor( @@ -69,7 +69,7 @@ ax.set_axis_off() if i == 0: - ax.set_title("Learned\nrank = {}".format(rank)) + ax.set_title(f"Learned\nrank = {rank}") plt.suptitle("Tucker tensor regression") plt.show() diff --git a/examples/sparse_parafac.ipynb b/examples/sparse_parafac.ipynb index f4b5eb359..b5cdb0572 100644 --- a/examples/sparse_parafac.ipynb +++ b/examples/sparse_parafac.ipynb @@ -54,8 +54,7 @@ "approx_error = tl.norm(t - approx)\n", "nonzero_elems_count = sum(t_shape)*r\n", "\n", - "print('approx error: {}, non-zero elements in approx: {}'.format(approx_error,\\\n", - " nonzero_elems_count))" + "print(f'approx error: {approx_error}, non-zero elements in approx: {nonzero_elems_count}')" ] }, { @@ -82,8 +81,7 @@ "approx_error = tl.norm(t - approx_sp)\n", "nonzero_elems_count = sum(t_shape)*r + sparsity*np.prod(t_shape)\n", "\n", - "print('approx error: {}, non-zero elements in approx: {}'.format(approx_error,\\\n", - " nonzero_elems_count))" + "print(f'approx error: {approx_error}, non-zero elements in approx: {nonzero_elems_count}')" ] }, { diff --git a/tensorly/backend/__init__.py b/tensorly/backend/__init__.py index 063701766..a50b925d2 100644 --- a/tensorly/backend/__init__.py +++ b/tensorly/backend/__init__.py @@ -10,7 +10,7 @@ import sys -class dynamically_dispatched_class_attribute(object): +class dynamically_dispatched_class_attribute: """Enable dynamically dispatched attributes such as dtype Parameters diff --git a/tensorly/backend/core.py b/tensorly/backend/core.py index da934688d..37193cb19 100644 --- a/tensorly/backend/core.py +++ b/tensorly/backend/core.py @@ -88,7 +88,7 @@ def __name__(self): return "Index" -class Backend(object): +class Backend: _available_backends = dict() def __init_subclass__(cls, backend_name, **kwargs): diff --git a/tensorly/contrib/decomposition/_tt_cross.py b/tensorly/contrib/decomposition/_tt_cross.py index 7d006e6b1..f4df8c990 100644 --- a/tensorly/contrib/decomposition/_tt_cross.py +++ b/tensorly/contrib/decomposition/_tt_cross.py @@ -106,14 +106,10 @@ def tensor_train_cross(input_tensor, rank, tol=1e-4, n_iter_max=100, random_stat # Initialize rank if rank[0] != 1: - message = "Provided rank[0] == {} but boundary conditions dictate rank[0] == rank[-1] == 1.".format( - rank[0] - ) + message = f"Provided rank[0] == {rank[0]} but boundary conditions dictate rank[0] == rank[-1] == 1." raise ValueError(message) if rank[-1] != 1: - message = "Provided rank[-1] == {} but boundary conditions dictate rank[0] == rank[-1] == 1.".format( - rank[-1] - ) + message = f"Provided rank[-1] == {rank[-1]} but boundary conditions dictate rank[0] == rank[-1] == 1." raise ValueError(message) # list col_idx: column indices (right indices) for skeleton-decomposition: indicate which columns used in each core. diff --git a/tensorly/contrib/decomposition/tests/test_tt_TTOI.py b/tensorly/contrib/decomposition/tests/test_tt_TTOI.py index 51612e70e..77527943b 100644 --- a/tensorly/contrib/decomposition/tests/test_tt_TTOI.py +++ b/tensorly/contrib/decomposition/tests/test_tt_TTOI.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- """ Testing of applying TTOI diff --git a/tensorly/contrib/sparse/backend/numpy_backend.py b/tensorly/contrib/sparse/backend/numpy_backend.py index 9f61e1017..897c98c23 100644 --- a/tensorly/contrib/sparse/backend/numpy_backend.py +++ b/tensorly/contrib/sparse/backend/numpy_backend.py @@ -14,7 +14,7 @@ _MIN_SPARSE_VERSION = Version("0.4.1+10.g81eccee") if Version(sparse.__version__) < _MIN_SPARSE_VERSION: raise ImportError( - "numpy sparse backend requires `sparse` version >= %r" % _MIN_SPARSE_VERSION + f"NumPy sparse backend requires `sparse` version >= {_MIN_SPARSE_VERSION!r}" ) diff --git a/tensorly/random/base.py b/tensorly/random/base.py index 5fe0eef36..35c9e2bee 100644 --- a/tensorly/random/base.py +++ b/tensorly/random/base.py @@ -212,14 +212,10 @@ def random_tt(shape, rank, full=False, random_state=None, **context): # Initialization if rank[0] != 1: - message = "Provided rank[0] == {} but boundaring conditions dictatate rank[0] == rank[-1] == 1.".format( - rank[0] - ) + message = f"Provided rank[0] == {rank[0]} but boundaring conditions dictatate rank[0] == rank[-1] == 1." raise ValueError(message) if rank[-1] != 1: - message = "Provided rank[-1] == {} but boundaring conditions dictatate rank[0] == rank[-1] == 1.".format( - rank[-1] - ) + message = f"Provided rank[-1] == {rank[-1]} but boundaring conditions dictatate rank[0] == rank[-1] == 1." raise ValueError(message) rns = T.check_random_state(random_state) diff --git a/tensorly/tenalg/proximal.py b/tensorly/tenalg/proximal.py index c99655f70..d9a276a51 100644 --- a/tensorly/tenalg/proximal.py +++ b/tensorly/tenalg/proximal.py @@ -550,8 +550,8 @@ def unimodality_prox(tensor): ) # Next line finds mutual peak points values = tl.tensor( - tl.to_numpy((tensor - monotone_decreasing >= 0)) - * tl.to_numpy((tensor - monotone_increasing >= 0)), + tl.to_numpy(tensor - monotone_decreasing >= 0) + * tl.to_numpy(tensor - monotone_increasing >= 0), **tl.context(tensor), ) diff --git a/tensorly/tenalg/tests/test_batched_tensordot.py b/tensorly/tenalg/tests/test_batched_tensordot.py index cda25ee5f..25825d8b7 100644 --- a/tensorly/tenalg/tests/test_batched_tensordot.py +++ b/tensorly/tenalg/tests/test_batched_tensordot.py @@ -8,8 +8,8 @@ def test_batched_tensordot(): shape = [3, 4, 2] - vecs = [random.random_tensor((s)) for s in shape] - tensor = random.random_tensor((shape)) + vecs = [random.random_tensor(s) for s in shape] + tensor = random.random_tensor(shape) # Equivalence with inner product when contracting with self along all modes res = tensordot(tensor, tensor, modes=3) # [[0, 1, 2], [0, 1, 2]]) diff --git a/tensorly/tenalg/tests/test_outer_product.py b/tensorly/tenalg/tests/test_outer_product.py index 2282f2c58..7a372e0a3 100644 --- a/tensorly/tenalg/tests/test_outer_product.py +++ b/tensorly/tenalg/tests/test_outer_product.py @@ -12,7 +12,7 @@ def test_outer_product(): X = tl.tensor(rng.random_sample((4, 5, 6))) Y = tl.tensor(rng.random_sample((3, 4))) - Z = tl.tensor(rng.random_sample((2))) + Z = tl.tensor(rng.random_sample(2)) tdot = outer([X, Y, Z]) true_dot = tenalg.tensordot(X, Y, ()) true_dot = tenalg.tensordot(true_dot, Z, ()) diff --git a/tensorly/tt_tensor.py b/tensorly/tt_tensor.py index 73cd975de..98bc28cfb 100644 --- a/tensorly/tt_tensor.py +++ b/tensorly/tt_tensor.py @@ -260,14 +260,10 @@ def validate_tt_rank( # Initialization if rank[0] != 1: - message = "Provided rank[0] == {} but boundary conditions dictate rank[0] == rank[-1] == 1.".format( - rank[0] - ) + message = f"Provided rank[0] == {rank[0]} but boundary conditions dictate rank[0] == rank[-1] == 1." raise ValueError(message) if rank[-1] != 1: - message = "Provided rank[-1] == {} but boundary conditions dictate rank[0] == rank[-1] == 1.".format( - rank[-1] - ) + message = f"Provided rank[-1] == {rank[-1]} but boundary conditions dictate rank[0] == rank[-1] == 1." raise ValueError(message) if allow_overparametrization: diff --git a/tensorly/utils/deprecation.py b/tensorly/utils/deprecation.py index 59f3b45f1..556a7cb59 100644 --- a/tensorly/utils/deprecation.py +++ b/tensorly/utils/deprecation.py @@ -19,7 +19,7 @@ def deprecated(deprecated_by, msg="", use_deprecated=True): if False, the new class/function will be used along with the deprecation warning for the old name """ - class DeprecatedBy(object): + class DeprecatedBy: def __init__(self): self.deprecated_by = deprecated_by self.use_deprecated = use_deprecated @@ -67,7 +67,7 @@ def __init__(wrapped_self, *args, **kwargs): return DeprecatedBy() -class DefineDeprecated(object): +class DefineDeprecated: """Creates a dummy class or function that returns the class/fun it is deprecated by, along with a warning diff --git a/tensorly/utils/tests/test_deprecation.py b/tensorly/utils/tests/test_deprecation.py index ffbb93c4e..8ed21d30f 100644 --- a/tensorly/utils/tests/test_deprecation.py +++ b/tensorly/utils/tests/test_deprecation.py @@ -2,7 +2,7 @@ def test_deprecated(): - class Dummy(object): + class Dummy: def __init__(self, arg=1): self.arg = arg + 1