diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6289d8bc0f3a633d884cfe099ea90d3575dd1c85..cf65206dbff37ad5cab3314b63bc08cb99a52e37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - "3.7" - "3.8" - "3.9" - # - "3.10" # FIXME: broken due to `collections.Iterable` issue; see #330 / #624 / etc. + - "3.10" steps: - uses: actions/checkout@v1 - name: Set up Python ${{ matrix.python-version }} diff --git a/examples/split_silence.py b/examples/split_silence.py index a889db101d9ebde254d4e286f3141395b2d9ece5..90b46d95a4966046368518fef135710cfb30128f 100755 --- a/examples/split_silence.py +++ b/examples/split_silence.py @@ -27,10 +27,10 @@ parser.add_argument('--start-time', type=float, help='Start time (seconds)') parser.add_argument('--end-time', type=float, help='End time (seconds)') parser.add_argument('-v', dest='verbose', action='store_true', help='Verbose mode') -silence_start_re = re.compile(' silence_start: (?P<start>[0-9]+(\.?[0-9]*))$') -silence_end_re = re.compile(' silence_end: (?P<end>[0-9]+(\.?[0-9]*)) ') +silence_start_re = re.compile(r' silence_start: (?P<start>[0-9]+(\.?[0-9]*))$') +silence_end_re = re.compile(r' silence_end: (?P<end>[0-9]+(\.?[0-9]*)) ') total_duration_re = re.compile( - 'size=[^ ]+ time=(?P<hours>[0-9]{2}):(?P<minutes>[0-9]{2}):(?P<seconds>[0-9\.]{5}) bitrate=') + r'size=[^ ]+ time=(?P<hours>[0-9]{2}):(?P<minutes>[0-9]{2}):(?P<seconds>[0-9\.]{5}) bitrate=') def _logged_popen(cmd_line, *args, **kwargs): diff --git a/ffmpeg/_run.py b/ffmpeg/_run.py index 5f25a347b68c3b21b4ee1a46ed11858643b0402d..f42d1d730917075fdd6bb7bfa949eed970139028 100644 --- a/ffmpeg/_run.py +++ b/ffmpeg/_run.py @@ -3,7 +3,6 @@ from .dag import get_outgoing_edges, topo_sort from ._utils import basestring, convert_kwargs_to_cmd_line_args from builtins import str from functools import reduce -import collections import copy import operator import subprocess @@ -18,6 +17,11 @@ from .nodes import ( output_operator, ) +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable + class Error(Exception): def __init__(self, cmd, stdout, stderr): @@ -136,9 +140,7 @@ def _get_output_args(node, stream_name_map): args += ['-b:a', str(kwargs.pop('audio_bitrate'))] if 'video_size' in kwargs: video_size = kwargs.pop('video_size') - if not isinstance(video_size, basestring) and isinstance( - video_size, collections.Iterable - ): + if not isinstance(video_size, basestring) and isinstance(video_size, Iterable): video_size = '{}x{}'.format(video_size[0], video_size[1]) args += ['-video_size', video_size] args += convert_kwargs_to_cmd_line_args(kwargs) diff --git a/ffmpeg/_utils.py b/ffmpeg/_utils.py index 94ef9d070cfc0431d6007264a466f492ecdba1ff..9baa2c78ce17b8698e38a0008346e31ce2a327c3 100644 --- a/ffmpeg/_utils.py +++ b/ffmpeg/_utils.py @@ -3,13 +3,17 @@ from builtins import str from past.builtins import basestring import hashlib import sys -import collections if sys.version_info.major == 2: # noinspection PyUnresolvedReferences,PyShadowingBuiltins str = str +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable + # `past.builtins.basestring` module can't be imported on Python3 in some environments (Ubuntu). # This code is copy-pasted from it to avoid crashes. @@ -92,7 +96,7 @@ def convert_kwargs_to_cmd_line_args(kwargs): args = [] for k in sorted(kwargs.keys()): v = kwargs[k] - if isinstance(v, collections.Iterable) and not isinstance(v, str): + if isinstance(v, Iterable) and not isinstance(v, str): for value in v: args.append('-{}'.format(k)) if value is not None: diff --git a/ffmpeg/tests/test_ffmpeg.py b/ffmpeg/tests/test_ffmpeg.py index ba1fa3612ca071c7b0f9cae084f50c9a0ff019c6..8dbc271a79a8946c2c3f254f0e47e0a817930634 100644 --- a/ffmpeg/tests/test_ffmpeg.py +++ b/ffmpeg/tests/test_ffmpeg.py @@ -30,7 +30,7 @@ subprocess.check_call(['ffmpeg', '-version']) def test_escape_chars(): - assert ffmpeg._utils.escape_chars('a:b', ':') == 'a\:b' + assert ffmpeg._utils.escape_chars('a:b', ':') == r'a\:b' assert ffmpeg._utils.escape_chars('a\\:b', ':\\') == 'a\\\\\\:b' assert ( ffmpeg._utils.escape_chars('a:b,c[d]e%{}f\'g\'h\\i', '\\\':,[]%') diff --git a/setup.py b/setup.py index 743deb22ab06766cddb61d04b62101d1b09d9760..72f381cb5339df8421a282e3c3439b67bcf7c04f 100644 --- a/setup.py +++ b/setup.py @@ -92,5 +92,9 @@ setup( 'Programming Language :: Python :: 3.4', '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', ], ) diff --git a/tox.ini b/tox.ini index e317207f4719ec2a42a5dc7c498e8010dcfe3bd1..98814078432d7995e30a2209123f7bac83e4dfec 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py35, py36, py37, py38, py39 +envlist = py27, py35, py36, py37, py38, py39, py310 [gh-actions] python = @@ -14,6 +14,7 @@ python = 3.7: py37 3.8: py38 3.9: py39 + 3.10: py310 [testenv] commands = py.test -vv