From 6692587f74261a2121408f6e231d0ab46630ecc0 Mon Sep 17 00:00:00 2001 From: rpkak <67059904+rpkak@users.noreply.github.com> Date: Thu, 7 Oct 2021 10:55:25 +0200 Subject: [PATCH] Python 3.10 compatibility (#1563) * use shutil.get_terminal_size instead of click.get_terminal_size() resolves warning: rq/cli/helpers.py:107: DeprecationWarning: 'click.get_terminal_size()' is deprecated and will be removed in Click 8.1. Use 'shutil.get_terminal_size()' instead. termwidth, _ = click.get_terminal_size() * remove StrictVersion from rq * asyncio.get_event_loop -> asyncio.new_event_loop() resolves warning: tests/test_job.py::TestJob::test_create_job_with_async rq/rq/job.py:839: DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop() * Add python 3.10 to matrix Co-authored-by: rpkak --- .github/workflows/dependencies.yml | 4 ++-- .github/workflows/workflow.yml | 2 +- rq/cli/helpers.py | 3 ++- rq/job.py | 7 +++---- rq/queue.py | 3 +-- rq/utils.py | 8 +++----- rq/worker.py | 3 +-- tests/test_utils.py | 8 +++----- 8 files changed, 16 insertions(+), 22 deletions(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 958fa3e..24b24f6 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9] + python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9, 3.10] redis-version: [3, 4, 5, 6] redis-py-version: [3.5.0] @@ -49,7 +49,7 @@ jobs: strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9] + python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9, 3.10] redis-version: [3, 4, 5, 6] steps: diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index d5b3cdc..b0a574e 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9] + python-version: [3.5, 3.6, 3.7, 3.8.3, 3.9, 3.10] redis-version: [3, 4, 5, 6] redis-py-version: [3.5.0] diff --git a/rq/cli/helpers.py b/rq/cli/helpers.py index e3564dc..03c16c9 100644 --- a/rq/cli/helpers.py +++ b/rq/cli/helpers.py @@ -12,6 +12,7 @@ from enum import Enum from datetime import datetime, timezone, timedelta from json import loads, JSONDecodeError from ast import literal_eval +from shutil import get_terminal_size import click import redis @@ -104,7 +105,7 @@ def state_symbol(state): def show_queues(queues, raw, by_queue, queue_class, worker_class): num_jobs = 0 - termwidth, _ = click.get_terminal_size() + termwidth = get_terminal_size().columns chartwidth = min(20, termwidth - 20) max_count = 0 diff --git a/rq/job.py b/rq/job.py index fa895fe..d773250 100644 --- a/rq/job.py +++ b/rq/job.py @@ -11,7 +11,6 @@ import zlib import asyncio from collections.abc import Iterable from datetime import datetime, timedelta, timezone -from distutils.version import StrictVersion from enum import Enum from functools import partial from uuid import uuid4 @@ -661,7 +660,7 @@ class Job: mapping = self.to_dict(include_meta=include_meta) - if self.get_redis_server_version() >= StrictVersion("4.0.0"): + if self.get_redis_server_version() >= (4, 0, 0): connection.hset(key, mapping=mapping) else: connection.hmset(key, mapping) @@ -836,7 +835,7 @@ class Job: 'started_at': utcformat(self.started_at), 'worker_name': worker_name } - if self.get_redis_server_version() >= StrictVersion("4.0.0"): + if self.get_redis_server_version() >= (4, 0, 0): pipeline.hset(self.key, mapping=mapping) else: pipeline.hmset(self.key, mapping) @@ -844,7 +843,7 @@ class Job: def _execute(self): result = self.func(*self.args, **self.kwargs) if asyncio.iscoroutine(result): - loop = asyncio.get_event_loop() + loop = asyncio.new_event_loop() coro_result = loop.run_until_complete(result) return coro_result return result diff --git a/rq/queue.py b/rq/queue.py index c6bc512..5378607 100644 --- a/rq/queue.py +++ b/rq/queue.py @@ -8,7 +8,6 @@ import warnings from collections import namedtuple from datetime import datetime, timezone -from distutils.version import StrictVersion from redis import WatchError from .compat import as_text, string_types, total_ordering @@ -184,7 +183,7 @@ class Queue: """ job_id = job_or_id.id if isinstance(job_or_id, self.job_class) else job_or_id - if self.get_redis_server_version() >= StrictVersion("6.0.6"): + if self.get_redis_server_version() >= (6, 0, 6): try: return self.connection.lpos(self.key, job_id) except AttributeError: diff --git a/rq/utils.py b/rq/utils.py index e1cb412..d556e69 100644 --- a/rq/utils.py +++ b/rq/utils.py @@ -16,7 +16,6 @@ import numbers import sys from collections.abc import Iterable -from distutils.version import StrictVersion from redis.exceptions import ResponseError @@ -276,14 +275,13 @@ def parse_timeout(timeout): def get_version(connection): """ - Returns StrictVersion of Redis server version. + Returns tuple of Redis server version. This function also correctly handles 4 digit redis server versions. """ try: - version_string = connection.info("server")["redis_version"] + return tuple(int(i) for i in connection.info("server")["redis_version"].split('.')[:3]) except ResponseError: # fakeredis doesn't implement Redis' INFO command - version_string = "5.0.9" - return StrictVersion('.'.join(version_string.split('.')[:3])) + return (5, 0, 9) def ceildiv(a, b): diff --git a/rq/worker.py b/rq/worker.py index 0cede3d..11ea290 100644 --- a/rq/worker.py +++ b/rq/worker.py @@ -14,7 +14,6 @@ import traceback import warnings from datetime import timedelta -from distutils.version import StrictVersion from enum import Enum from uuid import uuid4 from random import shuffle @@ -317,7 +316,7 @@ class Worker: 'python_version': self.python_version, } - if self.get_redis_server_version() >= StrictVersion("4.0.0"): + if self.get_redis_server_version() >= (4, 0, 0): p.hset(key, mapping=mapping) else: p.hmset(key, mapping) diff --git a/tests/test_utils.py b/tests/test_utils.py index add2863..a1217ea 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,8 +5,6 @@ import re import datetime import mock -from distutils.version import StrictVersion - from redis import Redis from tests import RQTestCase, fixtures @@ -77,19 +75,19 @@ class TestUtils(RQTestCase): def test_get_redis_version(self): """Ensure get_version works properly""" redis = Redis() - self.assertTrue(isinstance(get_version(redis), StrictVersion)) + self.assertTrue(isinstance(get_version(redis), tuple)) # Parses 3 digit version numbers correctly class DummyRedis(Redis): def info(*args): return {'redis_version': '4.0.8'} - self.assertEqual(get_version(DummyRedis()), StrictVersion('4.0.8')) + self.assertEqual(get_version(DummyRedis()), (4, 0, 8)) # Parses 3 digit version numbers correctly class DummyRedis(Redis): def info(*args): return {'redis_version': '3.0.7.9'} - self.assertEqual(get_version(DummyRedis()), StrictVersion('3.0.7')) + self.assertEqual(get_version(DummyRedis()), (3, 0, 7)) def test_ceildiv_even(self): """When a number is evenly divisible by another ceildiv returns the quotient"""