diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index e1ed369a..db8fc0f1 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -36,8 +36,8 @@ jobs: sudo apt-get install -yqq pandoc make - name: run code linters run: | - pip install -r requirements.txt -r dev_requirements.txt -r docs/requirements.txt - invoke build-docs + pip install tox + tox -e doc - name: upload docs uses: actions/upload-artifact@v4 diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 207aa4ba..38557b1b 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -47,8 +47,8 @@ jobs: cache: 'pip' - name: run code linters run: | - pip install -r dev_requirements.txt - invoke linters + pip install tox + tox -e lint populate-cache: runs-on: ubuntu-latest @@ -103,22 +103,24 @@ jobs: run: docker image load -i ./custom-cache/all.tar - name: run tests + env: + # Set CI to true to avoid pytest from truncating "short test summary info" + # (see https://github.com/pytest-dev/pytest/pull/9933) + CI: True run: | - pip install -U setuptools wheel - pip install -r requirements.txt - pip install -r dev_requirements.txt + pip install tox if [ "${{matrix.connection-type}}" == "libvalkey" ]; then pip install "libvalkey>=4.0.0" fi - invoke devenv + tox -e docker if [[ "${{matrix.test-type}}" == "standalone" ]]; then ./util/wait-for-it.sh localhost:6379 else ./util/wait-for-it.sh localhost:16379 fi - invoke ${{matrix.test-type}}-tests --protocol=${{ matrix.protocol-version }} + tox -e ${{matrix.test-type}}-nouvloop-protocol${{matrix.protocol-version}} if [[ "${{matrix.python-version}}" != pypy-* ]]; then - invoke ${{matrix.test-type}}-tests --uvloop --protocol=${{ matrix.protocol-version }} + tox -e ${{matrix.test-type}}-uvloop-protocol${{matrix.protocol-version}} fi - uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index 77eba107..b9948ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ vagrant/.vagrant env venv coverage.xml +.tox/ .venv* *.xml .coverage* diff --git a/dev_requirements.txt b/dev_requirements.txt index c56d2483..3d6901f7 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -4,7 +4,6 @@ click flake8-isort flake8 flynt -invoke mock packaging>=20.4 pytest diff --git a/tasks.py b/tasks.py deleted file mode 100644 index 8e5e094e..00000000 --- a/tasks.py +++ /dev/null @@ -1,94 +0,0 @@ -# https://github.com/pyinvoke/invoke/issues/833 -import inspect -import os -import shutil - -from invoke import run, task - -if not hasattr(inspect, "getargspec"): - inspect.getargspec = inspect.getfullargspec - - -@task -def devenv(c): - """Brings up the test environment, by wrapping docker compose.""" - clean(c) - cmd = "docker compose --profile all up -d" - run(cmd) - - -@task -def build_docs(c): - """Generates the sphinx documentation.""" - run("pip install -r docs/requirements.txt") - run("make -C docs html") - - -@task -def linters(c, color=False): - """Run code linters""" - run(f"flake8 --color {'always' if color else 'never'} tests valkey") - run(f"black {'--color' if color else ''} --target-version py37 --check --diff tests valkey") - run(f"isort {'--color' if color else ''} --check-only --diff tests valkey") - run("vulture valkey whitelist.py --min-confidence 80") - run("flynt --fail-on-change --dry-run tests valkey") - - -@task -def all_tests(c, color=False): - """Run all linters, and tests in valkey-py.""" - linters(c, color=color) - tests(c, color=color) - - -@task -def tests(c, uvloop=False, protocol=2, color=False): - """Run the valkey-py test suite against the current python, - with and without libvalkey. - """ - print("Starting Valkey tests") - standalone_tests(c, uvloop=uvloop, protocol=protocol, color=color) - cluster_tests(c, uvloop=uvloop, protocol=protocol, color=color) - - -@task -def standalone_tests(c, uvloop=False, protocol=2, color=False): - """Run tests against a standalone valkey instance""" - if uvloop: - run( - f"pytest --color={'yes' if color else 'no'} --protocol={protocol} --cov=./ --cov-report=xml:coverage_valkey.xml -W always -m 'not onlycluster' --uvloop --junit-xml=standalone-uvloop-results.xml" - ) - else: - run( - f"pytest --color={'yes' if color else 'no'} --protocol={protocol} --cov=./ --cov-report=xml:coverage_valkey.xml -W always -m 'not onlycluster' --junit-xml=standalone-results.xml" - ) - - -@task -def cluster_tests(c, uvloop=False, protocol=2, color=False): - """Run tests against a valkey cluster""" - cluster_url = "valkey://localhost:16379/0" - if uvloop: - run( - f"pytest --color={'yes' if color else 'no'} --protocol={protocol} --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not valkeymod' --valkey-url={cluster_url} --junit-xml=cluster-uvloop-results.xml --uvloop" - ) - else: - run( - f"pytest --color={'yes' if color else 'no'} --protocol={protocol} --cov=./ --cov-report=xml:coverage_clusteclient.xml -W always -m 'not onlynoncluster and not valkeymod' --valkey-url={cluster_url} --junit-xml=cluster-results.xml" - ) - - -@task -def clean(c): - """Stop all dockers, and clean up the built binaries, if generated.""" - if os.path.isdir("build"): - shutil.rmtree("build") - if os.path.isdir("dist"): - shutil.rmtree("dist") - run("docker compose --profile all rm -s -f") - - -@task -def package(c): - """Create the python packages""" - run("python setup.py sdist bdist_wheel") diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..d25f69a1 --- /dev/null +++ b/tox.ini @@ -0,0 +1,58 @@ +[tox] +env_list = lint, standalone-{uvloop,nouvloop}-protocol{2,3} + +[testenv:doc] +description = Build documentation +deps = -rdocs/requirements.txt +commands = + sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html + +[testenv:docker] +description = Set up development environment +allowlist_externals = docker +commands = + docker compose --profile all up -d + + +[testenv:lint] +description = Run linters +deps = + black + flake8 + flynt + isort + vulture +commands = + black --target-version py37 --check --diff tests valkey + flake8 tests valkey + isort --check-only --diff tests valkey + vulture valkey whitelist.py --min-confidence 80 + flynt --fail-on-change --dry-run tests valkey + +[testenv:standalone-{uvloop,nouvloop}-protocol{2,3}] +description = Run standalone tests +deps = + pytest + -rdev_requirements.txt +passenv = CI +setenv = + uvloop: VALKEY_UVLOOP=uvloop + nouvloop: VALKEY_UVLOOP=no-uvloop + protocol2: VALKEY_PROTOCOL=2 + protocol3: VALKEY_PROTOCOL=3 +commands = + pytest --protocol={env:VALKEY_PROTOCOL} --cov=./ --cov-report=xml:coverage_valkey.xml -W always -m 'not onlycluster' --junit-xml=standalone-{env:VALKEY_UVLOOP}-results.xml {posargs:tests} + +[testenv:cluster-{uvloop,nouvloop}-protocol{2,3}] +description = Run cluster tests +deps = + pytest + -rdev_requirements.txt +passenv = CI +setenv = + uvloop: VALKEY_UVLOOP=uvloop + nouvloop: VALKEY_UVLOOP=no-uvloop + protocol2: VALKEY_PROTOCOL=2 + protocol3: VALKEY_PROTOCOL=3 +commands = + pytest --protocol={env:VALKEY_PROTOCOL} --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not valkeymod' --valkey-url=valkey://localhost:16379/0 --junit-xml=cluster-{env:VALKEY_UVLOOP}-results.xml {posargs:tests}