diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d350a1..80e20bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,23 +47,28 @@ jobs: channel-priority: "strict" envfile: ".github/environment-ci.yml" + - os: ubuntu-latest + python-version: "3.12" + channel-priority: "strict" + envfile: ".github/environment-ci.yml" + - os: macos-latest - python-version: "3.11" + python-version: "3.12" channel-priority: "strict" envfile: ".github/environment-ci.yml" - os: windows-latest - python-version: "3.11" + python-version: "3.12" channel-priority: "strict" envfile: ".github/environment-ci.yml" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Cache conda - uses: actions/cache@v3 + uses: actions/cache@v4 env: # Increase this value to reset cache if etc/example-environment.yml has not changed CACHE_NUMBER: 0 @@ -72,7 +77,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.python-version }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles( matrix.envfile ) }} - name: Install Conda environment - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index d84e06f..eca30c6 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -13,18 +13,18 @@ jobs: channel-priority: "flexible" envfile: ".github/environment-lint.yml" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Cache conda - uses: actions/cache@v3 + uses: actions/cache@v4 env: CACHE_NUMBER: 0 with: path: ~/conda_pkgs_dir key: ${{ runner.os }}-${{ matrix.python-version }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles( matrix.envfile ) }} - name: Install conda environmnent - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: false python-version: ${{ matrix.python-version }} diff --git a/docs/conf.py b/docs/conf.py index 89a853e..9b24777 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # pescador documentation build configuration file, created by # sphinx-quickstart on Fri Apr 3 10:03:34 2015. @@ -83,19 +82,14 @@ master_doc = 'index' # General information about the project. -project = u'pescador' -authors = u'Pescador development team' -copyright = u'2016, {}'.format(authors) +project = 'pescador' +authors = 'Pescador development team' +copyright = f'2016, {authors}' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. -import six - -if six.PY3: - from unittest.mock import MagicMock as Mock -else: - from mock import Mock +from unittest.mock import MagicMock as Mock MOCK_MODULES = ['numpy', 'scipy', 'joblib.parallel', 'joblib._parallel_backends', 'joblib', @@ -261,7 +255,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'pescador.tex', u'pescador Documentation', + ('index', 'pescador.tex', 'pescador Documentation', authors), ] @@ -291,7 +285,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pescador', u'pescador Documentation', + ('index', 'pescador', 'pescador Documentation', [authors], 1) ] @@ -305,7 +299,7 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'pescador', u'pescador Documentation', + ('index', 'pescador', 'pescador Documentation', authors, 'pescador', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/requirements.txt b/docs/requirements.txt index b7c7333..21cd3b4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,5 @@ matplotlib numpydoc>=0.6 -six sphinx sphinx-gallery sphinx_rtd_theme diff --git a/examples/frameworks/keras_example.py b/examples/frameworks/keras_example.py index 619440f..cb90503 100644 --- a/examples/frameworks/keras_example.py +++ b/examples/frameworks/keras_example.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ =============== A Keras Example @@ -14,7 +13,6 @@ # Setup and Definitions ############################################## -from __future__ import print_function import datetime import keras from keras.datasets import mnist @@ -204,7 +202,7 @@ def additive_noise(stream, key='X', scale=1e-1): model = build_model(input_shape) try: - print("Start time: {}".format(datetime.datetime.now())) + print(f"Start time: {datetime.datetime.now()}") model.fit_generator( pescador.tuples(batches, 'X', 'y'), steps_per_epoch=steps_per_epoch, @@ -214,7 +212,7 @@ def additive_noise(stream, key='X', scale=1e-1): except KeyboardInterrupt: print("Stopping early") finally: - print("Finished: {}".format(datetime.datetime.now())) + print(f"Finished: {datetime.datetime.now()}") scores = model.evaluate(X_test, Y_test, verbose=0) for val, name in zip(scores, model.metrics_names): - print('Test {}: {:0.4f}'.format(name, val)) + print(f'Test {name}: {val:0.4f}') diff --git a/examples/mux/chain_example.py b/examples/mux/chain_example.py index 085f345..3f917a9 100644 --- a/examples/mux/chain_example.py +++ b/examples/mux/chain_example.py @@ -1,4 +1,3 @@ -#! -*- coding: utf-8 -*- """ ===================================== Using ChainMux for repeatable streams diff --git a/examples/mux/epoch.py b/examples/mux/epoch.py index 9cdf444..4948f43 100644 --- a/examples/mux/epoch.py +++ b/examples/mux/epoch.py @@ -1,4 +1,3 @@ -#! -*- coding: utf-8 -*- """ Using cycle mode to create data epochs ====================================== diff --git a/examples/mux/mux_files_example.py b/examples/mux/mux_files_example.py index 5727c57..e690aaf 100644 --- a/examples/mux/mux_files_example.py +++ b/examples/mux/mux_files_example.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ ================================= Muxing Multiple Datasets Together diff --git a/examples/mux/shuffle.py b/examples/mux/shuffle.py index ca0d52c..abf3a5d 100644 --- a/examples/mux/shuffle.py +++ b/examples/mux/shuffle.py @@ -1,4 +1,3 @@ -#! -*- coding: utf-8 -*- """ Hierarchical sampling with ShuffledMux ====================================== @@ -26,7 +25,6 @@ # Code source: Brian McFee # License: BSD 3 Clause -from __future__ import print_function import pescador ##################### diff --git a/examples/zmq_example.py b/examples/zmq_example.py index 7181bd8..2ead69c 100644 --- a/examples/zmq_example.py +++ b/examples/zmq_example.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ ================== Parallel streaming diff --git a/pescador/core.py b/pescador/core.py index 7d56b74..a88e127 100644 --- a/pescador/core.py +++ b/pescador/core.py @@ -9,7 +9,7 @@ from .exceptions import PescadorError -class Streamer(object): +class Streamer: """A wrapper class for recycling iterables and generator functions, i.e. streamers. @@ -259,8 +259,7 @@ def __call__(self, max_iter=None, cycle=False): else: gen = self.iterate(max_iter=max_iter) - for obj in gen: - yield obj + yield from gen def __iter__(self): """Wrap the iterator interface""" diff --git a/pescador/exceptions.py b/pescador/exceptions.py index 0e9b7da..a747c7c 100644 --- a/pescador/exceptions.py +++ b/pescador/exceptions.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- encoding: utf-8 -*- """Exception classes for pescador""" diff --git a/pescador/mux.py b/pescador/mux.py index 496f01c..ec6fd0a 100644 --- a/pescador/mux.py +++ b/pescador/mux.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- encoding: utf-8 -*- """\ Defines the interface and several varieties of *mux*. A *mux* is a `Streamer` which wraps N other `Streamer` objects, and at every step yields a @@ -346,7 +345,7 @@ def __init__( self.rate = rate self.prune_empty_streams = prune_empty_streams - super(StochasticMux, self).__init__(streamers, random_state=random_state) + super().__init__(streamers, random_state=random_state) if not self.n_streams: raise PescadorError("Cannot mux an empty collection") @@ -565,7 +564,7 @@ def __init__(self, streamers, weights=None, random_state=None): If None, the random number generator is the RandomState instance used by np.random. """ - super(ShuffledMux, self).__init__(streamers, random_state=random_state) + super().__init__(streamers, random_state=random_state) if not self.n_streams: raise PescadorError("Cannot mux an empty collection") @@ -711,7 +710,7 @@ def __init__(self, streamers, mode="exhaustive", random_state=None): used by `np.random.` """ self.mode = mode - super(RoundRobinMux, self).__init__(streamers, random_state=random_state) + super().__init__(streamers, random_state=random_state) if not self.n_streams: raise PescadorError("Cannot mux an empty collection") @@ -886,7 +885,7 @@ def __init__(self, streamers, mode="exhaustive", random_state=None): # if inspect.isgeneratorfunction(streamers): # streamers = core.Streamer(streamers) - super(ChainMux, self).__init__(streamers, random_state=random_state) + super().__init__(streamers, random_state=random_state) if mode not in ["exhaustive", "cycle"]: raise PescadorError(f"Invalid ChainMux mode '{mode}'") diff --git a/pescador/util.py b/pescador/util.py index 9ad94cf..58c77ab 100644 --- a/pescador/util.py +++ b/pescador/util.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- encoding: utf-8 -*- """Deprecation utilities""" import inspect @@ -11,7 +10,7 @@ from .exceptions import PescadorError -class Deprecated(object): +class Deprecated: """A dummy class to catch usage of deprecated variable names""" def __repr__(self): diff --git a/pescador/version.py b/pescador/version.py index 070d9c5..5cf90be 100644 --- a/pescador/version.py +++ b/pescador/version.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """Version info""" short_version = "3.0" diff --git a/setup.cfg b/setup.cfg index cc2aa0e..74661f9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,6 +43,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 [options] packages = find: diff --git a/tests/test_core.py b/tests/test_core.py index 90e51e9..15d9f86 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,6 +1,5 @@ #!/usr/bin/env python '''Test the streamer object for reusable iterators''' -from __future__ import print_function import copy import pytest @@ -278,8 +277,7 @@ def test_decorator(): @pescador.streamable def my_generator(n): - for i in range(n): - yield i + yield from range(n) s = my_generator(5) assert isinstance(s, pescador.Streamer) diff --git a/tests/test_mux.py b/tests/test_mux.py index 0060c4c..2ab0d39 100644 --- a/tests/test_mux.py +++ b/tests/test_mux.py @@ -1,5 +1,4 @@ # This makes '/' do in python2 what you expect in python3. -from __future__ import division import pytest @@ -17,8 +16,7 @@ def _cycle(values): while True: - for v in values: - yield v + yield from values def _choice(vals, seed=11111):