diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index eda546f..bdcda55 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,52 +1,83 @@ name: Tests -on: [push, pull_request] +on: + push: + paths-ignore: + - '.gitignore' + - 'README.rst' + pull_request: + paths-ignore: + - '.gitignore' + - 'README.rst' jobs: - build: + build-package: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref_name }}-build + cancel-in-progress: true + timeout-minutes: 20 + container: + image: ghcr.io/thombashi/python-ci:3.11 + + steps: + - uses: actions/checkout@v3 + + - run: make build + + lint: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref_name }}-lint + cancel-in-progress: true + timeout-minutes: 20 + container: + image: ghcr.io/thombashi/python-ci:3.11 + + steps: + - uses: actions/checkout@v3 + + - run: make check + + unit-test: + timeout-minutes: 20 runs-on: ${{ matrix.os }} + concurrency: + group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref_name }}-ut-${{ matrix.os }}-${{ matrix.python-version }} + cancel-in-progress: true strategy: fail-fast: false matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9, 3.10.0-alpha.6, pypy3] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.10'] os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + cache: pip + cache-dependency-path: | + setup.py + **/*requirements.txt + tox.ini - - name: Get pip cache dir - id: pip-cache - run: | - python -m pip install --upgrade "pip>=20.1" - echo "::set-output name=dir::$(pip cache dir)" - - - name: Cache pip - uses: actions/cache@v2 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ matrix.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ matrix.os }}-${{ matrix.python-version }}-pip- + - name: Install pip + run: python -m pip install --upgrade --disable-pip-version-check "pip>=21.1" - - name: Install dependencies - run: | - python -m pip install --upgrade tox + - run: make setup-ci - - name: Run tox - run: | - tox -e cov + - name: Run tests + run: tox -e cov env: PYTEST_DISCORD_WEBHOOK: ${{ secrets.PYTEST_DISCORD_WEBHOOK }} - - name: Coverage report + - name: Upload coverage report + if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' run: | - python -m pip install --upgrade coveralls + python -m pip install --upgrade --disable-pip-version-check coveralls tomli coveralls --service=github env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' diff --git a/Makefile b/Makefile index f0af13a..051174a 100644 --- a/Makefile +++ b/Makefile @@ -3,44 +3,46 @@ PACKAGE := allpairspy BUILD_WORK_DIR := _work DIST_DIR := $(BUILD_WORK_DIR)/$(PACKAGE)/dist PKG_BUILD_DIR := $(BUILD_WORK_DIR)/$(PACKAGE) +PYTHON := python3 .PHONY: build -build: - @make clean - @tox -e build +build: clean + @$(PYTHON) -m tox -e build ls -lh dist/* .PHONY: build-remote -build-remote: -build-remote: - @rm -rf $(BUILD_WORK_DIR) +build-remote: clean @mkdir -p $(BUILD_WORK_DIR) @cd $(BUILD_WORK_DIR) && \ - git clone https://github.com/$(OWNER)/$(PACKAGE).git && \ + git clone --depth 1 https://github.com/$(OWNER)/$(PACKAGE).git && \ cd $(PACKAGE) && \ - tox -e build + $(PYTHON) -m tox -e build ls -lh $(PKG_BUILD_DIR)/dist/* .PHONY: check check: - @tox -e lint - travis lint + @$(PYTHON) -m tox -e lint .PHONY: clean clean: - @tox -e clean + @rm -rf $(BUILD_WORK_DIR) + @$(PYTHON) -m tox -e clean .PHONY: fmt fmt: - tox -e fmt + $(PYTHON) -m tox -e fmt .PHONY: release release: - @cd $(PKG_BUILD_DIR) && python setup.py release --sign - @make clean + cd $(PKG_BUILD_DIR) && $(PYTHON) setup.py release --verbose + $(MAKE) clean + +.PHONY: setup-ci +setup-ci: + @$(PYTHON) -m pip install -q --disable-pip-version-check --upgrade tox .PHONY: setup -setup: - @pip install --upgrade -e .[test] releasecmd tox - pip check +setup: setup-ci + @$(PYTHON) -m pip install -q --disable-pip-version-check --upgrade -e .[test] releasecmd + @$(PYTHON) -m pip check diff --git a/README.rst b/README.rst index a152701..9372725 100644 --- a/README.rst +++ b/README.rst @@ -90,7 +90,7 @@ Basic Usage Filtering ================== -You can restrict pairs by setting filtering function to ``filter_func`` at +You can restrict pairs by setting a filtering function to ``filter_func`` at ``AllPairs`` constructor. :Sample Code: @@ -198,10 +198,10 @@ Pairs will be returned as ``collections.namedtuple`` instances. 11: Pairs(brand='Brand X', os='2000', minute=15) -Parameterized testing with pairwise by using pytest +Parameterized testing pairwise by using pytest ==================================================================== -Parameterized testing: valee matrix +Parameterized testing: value matrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :Sample Code: .. code:: python @@ -319,14 +319,20 @@ Known issues Dependencies ------------ -Python 3.5+ +Python 3.7+ no external dependencies. Sponsors ------------ -.. image:: https://avatars0.githubusercontent.com/u/44389260?s=48&u=6da7176e51ae2654bcfd22564772ef8a3bb22318&v=4 +.. image:: https://avatars.githubusercontent.com/u/3658062?s=48&v=4 + :target: https://github.com/b4tman + :alt: Dmitry Belyaev (b4tman) +.. image:: https://avatars.githubusercontent.com/u/44389260?s=48&u=6da7176e51ae2654bcfd22564772ef8a3bb22318&v=4 :target: https://github.com/chasbecker - :alt: chasbecker + :alt: Charles Becker (chasbecker) +.. image:: https://avatars.githubusercontent.com/u/46711571?s=48&u=57687c0e02d5d6e8eeaf9177f7b7af4c9f275eb5&v=4 + :target: https://github.com/Arturi0 + :alt: Arturi0 `Become a sponsor `__ diff --git a/allpairspy/__version__.py b/allpairspy/__version__.py index 618e6d3..658369e 100644 --- a/allpairspy/__version__.py +++ b/allpairspy/__version__.py @@ -3,4 +3,4 @@ __maintainer__ = "Tsuyoshi Hombashi" __maintainer_email__ = "tsuyoshi.hombashi@gmail.com" __license__ = "MIT License" -__version__ = "2.5.0" +__version__ = "2.5.1" diff --git a/allpairspy/allpairs.py b/allpairspy/allpairs.py index b8b1a82..4d0422a 100644 --- a/allpairspy/allpairs.py +++ b/allpairspy/allpairs.py @@ -130,7 +130,7 @@ def __next__(self): continue direction = 0 else: - raise ValueError("next(): unknown 'direction' code '{}'".format(direction)) + raise ValueError(f"next(): unknown 'direction' code '{direction}'") chosen_item_list[i] = self.__working_item_matrix[i][indexes[i]] @@ -202,7 +202,7 @@ def __resort_working_array(self, chosen_item_list, num): def __get_working_item_matrix(self, parameter_matrix): return [ [ - Item("a{:d}v{:d}".format(param_idx, value_idx), value) + Item(f"a{param_idx:d}v{value_idx:d}", value) for value_idx, value in enumerate(value_list) ] for param_idx, value_list in enumerate(parameter_matrix) diff --git a/examples/example1.1.py b/examples/example1.1.py index 7dcbea4..7ae3599 100755 --- a/examples/example1.1.py +++ b/examples/example1.1.py @@ -19,4 +19,4 @@ print("PAIRWISE:") for i, pairs in enumerate(AllPairs(parameters)): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/example1.2.py b/examples/example1.2.py index 07ba5ed..bdae899 100755 --- a/examples/example1.2.py +++ b/examples/example1.2.py @@ -19,4 +19,4 @@ print("TRIPLEWISE:") for i, pairs in enumerate(AllPairs(parameters, n=3)): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/example1.3.py b/examples/example1.3.py index 64cb0dc..0228f7a 100755 --- a/examples/example1.3.py +++ b/examples/example1.3.py @@ -26,4 +26,4 @@ print("PAIRWISE:") for i, pairs in enumerate(AllPairs(parameters, previously_tested=tested)): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/example2.1.py b/examples/example2.1.py index ff8401a..1d1eac8 100755 --- a/examples/example2.1.py +++ b/examples/example2.1.py @@ -48,4 +48,4 @@ def is_valid_combination(row): print("PAIRWISE:") for i, pairs in enumerate(AllPairs(parameters, filter_func=is_valid_combination)): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/example2.2.py b/examples/example2.2.py index 43b9893..5ca6ba8 100755 --- a/examples/example2.2.py +++ b/examples/example2.2.py @@ -9,7 +9,6 @@ def is_valid_combination(values, names): - dictionary = dict(zip(names, values)) """ @@ -56,4 +55,4 @@ def is_valid_combination(values, names): print("PAIRWISE:") for i, pairs in enumerate(pairwise): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/example_ordered_dict.py b/examples/example_ordered_dict.py index e014865..38d0427 100644 --- a/examples/example_ordered_dict.py +++ b/examples/example_ordered_dict.py @@ -6,9 +6,13 @@ parameters = OrderedDict( - {"brand": ["Brand X", "Brand Y"], "os": ["98", "NT", "2000", "XP"], "minute": [15, 30, 60]} + { + "brand": ["Brand X", "Brand Y"], + "os": ["98", "NT", "2000", "XP"], + "minute": [15, 30, 60], + } ) print("PAIRWISE:") for i, pairs in enumerate(AllPairs(parameters)): - print("{:2d}: {}".format(i, pairs)) + print(f"{i:2d}: {pairs}") diff --git a/examples/test_parameterize.py b/examples/test_parameterize.py index 54ba82c..7ca1473 100644 --- a/examples/test_parameterize.py +++ b/examples/test_parameterize.py @@ -9,7 +9,7 @@ from allpairspy import AllPairs -def function_to_be_tested(brand, operating_system, minute): +def function_to_be_tested(brand: str, operating_system: str, minute: int) -> bool: # do something return True @@ -19,8 +19,8 @@ class TestParameterized: @pytest.mark.parametrize( ["brand", "operating_system", "minute"], [ - value_list - for value_list in AllPairs( + values + for values in AllPairs( [["Brand X", "Brand Y"], ["98", "NT", "2000", "XP"], [10, 15, 30, 60]] ) ], diff --git a/pyproject.toml b/pyproject.toml index 686ea2d..7c93b49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,6 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" [tool.black] line-length = 100 @@ -18,6 +19,7 @@ exclude = ''' )/ | docs/conf.py ''' +target-version = ['py37', 'py38', 'py39', 'py310'] [tool.coverage.run] source = ['allpairspy'] @@ -49,3 +51,12 @@ skip_glob = [ '*/.pytype/*', '*/.tox/*', ] + +[tool.pytest.ini_options] +testpaths = [ + "tests", +] + +md_report = true +md_report_verbose = 0 +md_report_color = "auto" diff --git a/requirements/test_requirements.txt b/requirements/test_requirements.txt index e079f8a..d2adc09 100644 --- a/requirements/test_requirements.txt +++ b/requirements/test_requirements.txt @@ -1 +1,2 @@ -pytest +pytest>=6.0.1 +pytest-md-report>=0.3 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 5a3f3eb..75e465b --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ MODULE_NAME = "allpairspy" -REPOSITORY_URL = "https://github.com/thombashi/{:s}".format(MODULE_NAME) +REPOSITORY_URL = f"https://github.com/thombashi/{MODULE_NAME:s}" REQUIREMENT_DIR = "requirements" pkg_info = {} @@ -44,8 +44,11 @@ def get_release_command_class(): maintainer=pkg_info["__maintainer__"], maintainer_email=pkg_info["__maintainer_email__"], packages=setuptools.find_packages(exclude=["tests*"]), - project_urls={"Source": REPOSITORY_URL, "Tracker": "{:s}/issues".format(REPOSITORY_URL)}, - python_requires=">=3.5", + project_urls={ + "Source": REPOSITORY_URL, + "Tracker": f"{REPOSITORY_URL:s}/issues", + }, + python_requires=">=3.7", install_requires=install_requires, extras_require={"test": tests_requires}, classifiers=[ @@ -59,12 +62,11 @@ def get_release_command_class(): "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", "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 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index 0c798f6..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# this file temporarily required to get coverage: -# pytest-dev/pytest-cov#391 -# https://github.com/pytest-dev/pytest-cov/issues/391 diff --git a/tests/test_allpairs.py b/tests/test_allpairs.py index c1d59c1..2886f79 100644 --- a/tests/test_allpairs.py +++ b/tests/test_allpairs.py @@ -210,7 +210,6 @@ def test_normal_example22(self): ] def is_valid_combination(values, names): - dictionary = dict(zip(names, values)) """ diff --git a/tox.ini b/tox.ini index b528cda..f8d1c0c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,50 +1,48 @@ [tox] envlist = - py{35,36,37,38,39,310} + py{37,38,39,310,311} pypy3 build - clean cov fmt lint [testenv] -deps = - .[test] +extras = + test commands = pytest {posargs} [testenv:build] -basepython = python3.8 deps = + build>=0.10 twine wheel commands = - python setup.py sdist bdist_wheel + python -m build twine check dist/*.whl dist/*.tar.gz - python setup.py clean --all [testenv:clean] skip_install = true deps = - cleanpy + cleanpy>=0.4 commands = cleanpy --all --exclude-envs . [testenv:cov] +extras = + test deps = - .[test] coverage[toml] commands = coverage run -m pytest {posargs:-vv} coverage report -m [testenv:fmt] -basepython = python3.8 skip_install = true deps = - autoflake - black + autoflake>=2 + black>=23.1 isort>=5 commands = black setup.py examples tests allpairspy @@ -52,12 +50,12 @@ commands = isort . [testenv:lint] -basepython = python3.8 skip_install = true deps = - codespell - pylama + black>=23.1 + codespell>=2 + pylama>=8.4.1 commands = - python setup.py check + black --check setup.py examples tests allpairspy codespell allpairspy examples tests -q2 --check-filenames pylama