From 69b4c334f5b3fd008f79c8dad03a55a4399b9017 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 5 Jan 2024 15:00:25 +0200 Subject: [PATCH 1/5] Bump GitHub Actions --- .github/workflows/python-publish.yml | 4 ++-- .github/workflows/run-tests.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 1a03a7b..2ac1f30 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 56d3790..9d160a4 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,9 +18,9 @@ jobs: python-version: [3.5, 3.6, 3.7, 3.8, 3.9] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} From 8e431d2dcdc5f00370db87a1c881f0aadabb4f4b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 5 Jan 2024 15:03:03 +0200 Subject: [PATCH 2/5] Modernise workflows --- .github/workflows/python-publish.yml | 1 + .github/workflows/run-tests.yml | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 2ac1f30..cb13319 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -18,6 +18,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: '3.x' + cache: pip - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9d160a4..840d9ff 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -3,17 +3,17 @@ name: Run Tests on PR -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] +on: [push, pull_request, workflow_dispatch] + +env: + FORCE_COLOR: 1 jobs: build: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: python-version: [3.5, 3.6, 3.7, 3.8, 3.9] @@ -23,6 +23,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + cache: pip - name: Install dependencies run: | From 5de5cdcefb2837bf5db212c5da8e1bfabbbe672e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 5 Jan 2024 15:07:02 +0200 Subject: [PATCH 3/5] Test Python 3.10-3.12 --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 840d9ff..81d073e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: [3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 From 85cd383bc9bc31d55f1009a0b80642e14fefa86e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 5 Jan 2024 15:08:31 +0200 Subject: [PATCH 4/5] Drop support for EOL Python <= 3.7 --- .github/workflows/run-tests.yml | 2 +- setup.cfg | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 81d073e..88ef6b8 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 diff --git a/setup.cfg b/setup.cfg index 88a39f0..b3a88d0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,3 @@ [metadata] description-file = README.md -[bdist_wheel] -universal = 1 +python_requires = >=3.8 From e66831d99c23a61aef5d108a39d5f141dc4810a8 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 5 Jan 2024 15:10:04 +0200 Subject: [PATCH 5/5] Upgrade Python syntax with pyupgrade --py38-plus --- docs/conf.py | 1 - setup.py | 2 +- sox/combine.py | 24 ++-- sox/core.py | 8 +- sox/file_info.py | 12 +- sox/transform.py | 280 +++++++++++++++++++++++------------------------ sox/version.py | 1 - 7 files changed, 161 insertions(+), 167 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index acb1487..981e5b2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # pysox documentation build configuration file, created by # sphinx-quickstart on Tue May 17 14:11:03 2016. diff --git a/setup.py b/setup.py index 5126a6a..844f498 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ version = imp.load_source('sox.version', 'sox/version.py') -with open("README.md", "r") as fh: +with open("README.md") as fh: long_description = fh.read() if __name__ == "__main__": diff --git a/sox/combine.py b/sox/combine.py index d289814..145f37b 100644 --- a/sox/combine.py +++ b/sox/combine.py @@ -1,11 +1,9 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- ''' Python wrapper around the SoX library. This module requires that SoX is installed. ''' -from __future__ import print_function from pathlib import Path from typing import Union, Optional, List @@ -41,7 +39,7 @@ class Combiner(Transformer): ''' def __init__(self): - super(Combiner, self).__init__() + super().__init__() def build(self, input_filepath_list: Union[str, Path], @@ -111,7 +109,7 @@ def build(self, if status != 0: raise SoxError( - "Stdout: {}\nStderr: {}".format(out, err) + f"Stdout: {out}\nStderr: {err}" ) else: logger.info( @@ -121,7 +119,7 @@ def build(self, " ".join(self.effects_log) ) if out is not None: - logger.info("[SoX] {}".format(out)) + logger.info(f"[SoX] {out}") return True def preview(self, @@ -306,19 +304,19 @@ def set_input_format(self, input_format.append([]) for i, f in enumerate(file_type): - input_format[i].extend(['-t', '{}'.format(f)]) + input_format[i].extend(['-t', f'{f}']) for i, r in enumerate(rate): - input_format[i].extend(['-r', '{}'.format(r)]) + input_format[i].extend(['-r', f'{r}']) for i, b in enumerate(bits): - input_format[i].extend(['-b', '{}'.format(b)]) + input_format[i].extend(['-b', f'{b}']) for i, c in enumerate(channels): - input_format[i].extend(['-c', '{}'.format(c)]) + input_format[i].extend(['-c', f'{c}']) for i, e in enumerate(encoding): - input_format[i].extend(['-e', '{}'.format(e)]) + input_format[i].extend(['-e', f'{e}']) for i, l in enumerate(ignore_length): if l is True: @@ -347,7 +345,7 @@ def _validate_sample_rates(input_filepath_list: List[Path], file_info.sample_rate(f) for f in input_filepath_list ] if not core.all_equal(sample_rates): - raise IOError( + raise OSError( "Input files do not have the same sample rate. The {} combine " "type requires that all files have the same sample rate" .format(combine_type) @@ -362,7 +360,7 @@ def _validate_num_channels(input_filepath_list: List[Path], file_info.channels(f) for f in input_filepath_list ] if not core.all_equal(channels): - raise IOError( + raise OSError( "Input files do not have the same number of channels. The " "{} combine type requires that all files have the same " "number of channels" @@ -441,7 +439,7 @@ def _build_input_format_list(input_filepath_list: List[Path], fmts = [f for f in input_format] for i, (vol, fmt) in enumerate(zip(vols, fmts)): - input_format_list[i].extend(['-v', '{}'.format(vol)]) + input_format_list[i].extend(['-v', f'{vol}']) input_format_list[i].extend(fmt) return input_format_list diff --git a/sox/core.py b/sox/core.py index 6860cb4..3439e1b 100644 --- a/sox/core.py +++ b/sox/core.py @@ -153,10 +153,10 @@ def soxi(filepath: Union[str, Path], argument: str) -> str: filepath = str(filepath) if argument not in SOXI_ARGS: - raise ValueError("Invalid argument '{}' to SoXI".format(argument)) + raise ValueError(f"Invalid argument '{argument}' to SoXI") args = ['sox', '--i'] - args.append("-{}".format(argument)) + args.append(f"-{argument}") args.append(filepath) try: @@ -165,8 +165,8 @@ def soxi(filepath: Union[str, Path], argument: str) -> str: stderr=subprocess.PIPE ) except CalledProcessError as cpe: - logger.info("SoXI error message: {}".format(cpe.output)) - raise SoxiError("SoXI failed with exit code {}".format(cpe.returncode)) + logger.info(f"SoXI error message: {cpe.output}") + raise SoxiError(f"SoXI failed with exit code {cpe.returncode}") shell_output = shell_output.decode("utf-8") diff --git a/sox/file_info.py b/sox/file_info.py index bafc92c..3fb48f9 100644 --- a/sox/file_info.py +++ b/sox/file_info.py @@ -250,14 +250,14 @@ def validate_input_file(input_filepath: Union[str, Path]) -> None: ''' input_filepath = Path(input_filepath) if not input_filepath.exists(): - raise IOError( - "input_filepath {} does not exist.".format(input_filepath) + raise OSError( + f"input_filepath {input_filepath} does not exist." ) ext = file_extension(input_filepath) if ext not in VALID_FORMATS: logger.info("Valid formats: %s", " ".join(VALID_FORMATS)) logger.warning( - "This install of SoX cannot process .{} files.".format(ext) + f"This install of SoX cannot process .{ext} files." ) @@ -304,15 +304,15 @@ def validate_output_file(output_filepath: Union[str, Path]) -> None: not os.access(os.path.dirname(output_filepath), os.W_OK)] if all(nowrite_conditions): - raise IOError( - "SoX cannot write to output_filepath {}".format(output_filepath) + raise OSError( + f"SoX cannot write to output_filepath {output_filepath}" ) ext = file_extension(output_filepath) if ext not in VALID_FORMATS: logger.info("Valid formats: %s", " ".join(VALID_FORMATS)) logger.warning( - "This install of SoX cannot process .{} files.".format(ext) + f"This install of SoX cannot process .{ext} files." ) if os.path.exists(output_filepath): diff --git a/sox/transform.py b/sox/transform.py index 83e0506..0559b64 100644 --- a/sox/transform.py +++ b/sox/transform.py @@ -1,11 +1,9 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- ''' Python wrapper around the SoX library. This module requires that SoX is installed. ''' -from __future__ import print_function import os import random @@ -148,7 +146,7 @@ def set_globals(self, dither: bool = False, global_args.append('--replay-gain') global_args.append('track') - global_args.append('-V{}'.format(verbosity)) + global_args.append(f'-V{verbosity}') self.globals = global_args return self @@ -165,7 +163,7 @@ def _validate_input_format(self, input_format): if file_type not in VALID_FORMATS + [None]: raise ValueError( - 'Invalid file_type. Must be one of {}'.format(VALID_FORMATS) + f'Invalid file_type. Must be one of {VALID_FORMATS}' ) if not is_number(rate) and rate is not None: @@ -210,19 +208,19 @@ def _input_format_args(self, input_format): input_format_args = [] if file_type is not None: - input_format_args.extend(['-t', '{}'.format(file_type)]) + input_format_args.extend(['-t', f'{file_type}']) if rate is not None: - input_format_args.extend(['-r', '{:f}'.format(rate)]) + input_format_args.extend(['-r', f'{rate:f}']) if bits is not None: - input_format_args.extend(['-b', '{}'.format(bits)]) + input_format_args.extend(['-b', f'{bits}']) if channels is not None: - input_format_args.extend(['-c', '{}'.format(channels)]) + input_format_args.extend(['-c', f'{channels}']) if encoding is not None: - input_format_args.extend(['-e', '{}'.format(encoding)]) + input_format_args.extend(['-e', f'{encoding}']) if ignore_length: input_format_args.append('--ignore-length') @@ -322,7 +320,7 @@ def _validate_output_format(self, output_format): if file_type not in VALID_FORMATS + [None]: raise ValueError( - 'Invalid file_type. Must be one of {}'.format(VALID_FORMATS) + f'Invalid file_type. Must be one of {VALID_FORMATS}' ) if not is_number(rate) and rate is not None: @@ -345,7 +343,7 @@ def _validate_output_format(self, output_format): if encoding not in ENCODING_VALS + [None]: raise ValueError( - 'Invalid encoding. Must be one of {}'.format(ENCODING_VALS) + f'Invalid encoding. Must be one of {ENCODING_VALS}' ) if comments is not None and not isinstance(comments, str): @@ -370,19 +368,19 @@ def _output_format_args(self, output_format): output_format_args = [] if file_type is not None: - output_format_args.extend(['-t', '{}'.format(file_type)]) + output_format_args.extend(['-t', f'{file_type}']) if rate is not None: - output_format_args.extend(['-r', '{:f}'.format(rate)]) + output_format_args.extend(['-r', f'{rate:f}']) if bits is not None: - output_format_args.extend(['-b', '{}'.format(bits)]) + output_format_args.extend(['-b', f'{bits}']) if channels is not None: - output_format_args.extend(['-c', '{}'.format(channels)]) + output_format_args.extend(['-c', f'{channels}']) if encoding is not None: - output_format_args.extend(['-e', '{}'.format(encoding)]) + output_format_args.extend(['-e', f'{encoding}']) if comments is not None: if append_comments: @@ -642,7 +640,7 @@ def build(self, status, out, err = sox(args, input_array, True) if status != 0: raise SoxError( - "Stdout: {}\nStderr: {}".format(out, err) + f"Stdout: {out}\nStderr: {err}" ) logger.info( @@ -855,7 +853,7 @@ def build_array(self, elif n_bits == 64: encoding_out = np.float64 else: - raise ValueError("invalid n_bits {}".format(n_bits)) + raise ValueError(f"invalid n_bits {n_bits}") args = [] args.extend(self.globals) @@ -873,7 +871,7 @@ def build_array(self, status, out, err = sox(args, input_array, False) if status != 0: raise SoxError( - "Stdout: {}\nStderr: {}".format(out, err) + f"Stdout: {out}\nStderr: {err}" ) out = np.frombuffer(out, dtype=encoding_out) @@ -933,7 +931,7 @@ def allpass(self, frequency: float, width_q: float = 2.0): raise ValueError("width_q must be a positive number.") effect_args = [ - 'allpass', '{:f}'.format(frequency), '{:f}q'.format(width_q) + 'allpass', f'{frequency:f}', f'{width_q:f}q' ] self.effects.extend(effect_args) @@ -976,7 +974,7 @@ def bandpass(self, frequency: float, width_q: float = 2.0, if constant_skirt: effect_args.append('-c') - effect_args.extend(['{:f}'.format(frequency), '{:f}q'.format(width_q)]) + effect_args.extend([f'{frequency:f}', f'{width_q:f}q']) self.effects.extend(effect_args) self.effects_log.append('bandpass') @@ -1018,7 +1016,7 @@ def bandreject(self, frequency: float, width_q: float = 2.0, if constant_skirt: effect_args.append('-c') - effect_args.extend(['{:f}'.format(frequency), '{:f}q'.format(width_q)]) + effect_args.extend([f'{frequency:f}', f'{width_q:f}q']) self.effects.extend(effect_args) self.effects_log.append('bandreject') @@ -1060,8 +1058,8 @@ def bass(self, gain_db: float, raise ValueError("width_q must be a positive number.") effect_args = [ - 'bass', '{:f}'.format(gain_db), '{:f}'.format(frequency), - '{:f}s'.format(slope) + 'bass', f'{gain_db:f}', f'{frequency:f}', + f'{slope:f}s' ] self.effects.extend(effect_args) @@ -1150,8 +1148,8 @@ def bend(self, effect_args = [ 'bend', - '-f', '{}'.format(frame_rate), - '-o', '{}'.format(oversample_rate) + '-f', f'{frame_rate}', + '-o', f'{oversample_rate}' ] last = 0 @@ -1159,7 +1157,7 @@ def bend(self, t_start = round(start_times[i] - last, 2) t_end = round(end_times[i] - start_times[i], 2) effect_args.append( - '{:f},{:f},{:f}'.format(t_start, cents[i], t_end) + f'{t_start:f},{cents[i]:f},{t_end:f}' ) last = end_times[i] @@ -1201,9 +1199,9 @@ def biquad(self, b: List[float], a: List[float]): raise ValueError('all elements of a must be numbers.') effect_args = [ - 'biquad', '{:f}'.format(b[0]), '{:f}'.format(b[1]), - '{:f}'.format(b[2]), '{:f}'.format(a[0]), - '{:f}'.format(a[1]), '{:f}'.format(a[2]) + 'biquad', f'{b[0]:f}', f'{b[1]:f}', + f'{b[2]:f}', f'{a[0]:f}', + f'{a[1]:f}', f'{a[2]:f}' ] self.effects.extend(effect_args) @@ -1230,7 +1228,7 @@ def channels(self, n_channels: int): if not isinstance(n_channels, int) or n_channels <= 0: raise ValueError('n_channels must be a positive integer.') - effect_args = ['channels', '{}'.format(n_channels)] + effect_args = ['channels', f'{n_channels}'] self.effects.extend(effect_args) self.effects_log.append('channels') @@ -1352,15 +1350,15 @@ def chorus(self, else: shapes = [random.choice(['t', 's']) for _ in range(n_voices)] - effect_args = ['chorus', '{}'.format(gain_in), '{}'.format(gain_out)] + effect_args = ['chorus', f'{gain_in}', f'{gain_out}'] for i in range(n_voices): effect_args.extend([ - '{:f}'.format(delays[i]), - '{:f}'.format(decays[i]), - '{:f}'.format(speeds[i]), - '{:f}'.format(depths[i]), - '-{}'.format(shapes[i]) + f'{delays[i]:f}', + f'{decays[i]:f}', + f'{speeds[i]:f}', + f'{depths[i]:f}', + f'-{shapes[i]}' ]) self.effects.extend(effect_args) @@ -1424,7 +1422,7 @@ def compand(self, raise ValueError("Tuples in tf_points must be pairs of numbers.") if any((p[0] > 0 or p[1] > 0) for p in tf_points): raise ValueError("Tuple values in tf_points must be <= 0 (dB).") - if len(tf_points) > len(set([p[0] for p in tf_points])): + if len(tf_points) > len({p[0] for p in tf_points}): raise ValueError("Found duplicate x-value in tf_points.") tf_points = sorted( @@ -1434,12 +1432,12 @@ def compand(self, transfer_list = [] for point in tf_points: transfer_list.extend([ - "{:f}".format(point[0]), "{:f}".format(point[1]) + f"{point[0]:f}", f"{point[1]:f}" ]) effect_args = [ 'compand', - "{:f},{:f}".format(attack_time, decay_time) + f"{attack_time:f},{decay_time:f}" ] if soft_knee_db is not None: @@ -1470,7 +1468,7 @@ def contrast(self, amount=75): if not is_number(amount) or amount < 0 or amount > 100: raise ValueError('amount must be a number between 0 and 100.') - effect_args = ['contrast', '{:f}'.format(amount)] + effect_args = ['contrast', f'{amount:f}'] self.effects.extend(effect_args) self.effects_log.append('contrast') @@ -1500,7 +1498,7 @@ def convert(self, if bitdepth is not None: if bitdepth not in bitdepths: raise ValueError( - "bitdepth must be one of {}.".format(str(bitdepths)) + f"bitdepth must be one of {str(bitdepths)}." ) self.output_format['bits'] = bitdepth if n_channels is not None: @@ -1531,7 +1529,7 @@ def dcshift(self, shift: float = 0.0): if not is_number(shift) or shift < -2 or shift > 2: raise ValueError('shift must be a number between -2 and 2.') - effect_args = ['dcshift', '{:f}'.format(shift)] + effect_args = ['dcshift', f'{shift:f}'] self.effects.extend(effect_args) self.effects_log.append('dcshift') @@ -1581,7 +1579,7 @@ def delay(self, positions: List[float]): raise ValueError("positions must be positive nubmers") effect_args = ['delay'] - effect_args.extend(['{:f}'.format(p) for p in positions]) + effect_args.extend([f'{p:f}' for p in positions]) self.effects.extend(effect_args) self.effects_log.append('delay') @@ -1610,7 +1608,7 @@ def downsample(self, factor: int = 2): if not isinstance(factor, int) or factor < 1: raise ValueError('factor must be a positive integer.') - effect_args = ['downsample', '{}'.format(factor)] + effect_args = ['downsample', f'{factor}'] self.effects.extend(effect_args) self.effects_log.append('downsample') @@ -1694,12 +1692,12 @@ def echo(self, "the elements of decays must be between 0 and 1" ) - effect_args = ['echo', '{:f}'.format(gain_in), '{:f}'.format(gain_out)] + effect_args = ['echo', f'{gain_in:f}', f'{gain_out:f}'] for i in range(n_echos): effect_args.extend([ - '{}'.format(delays[i]), - '{}'.format(decays[i]) + f'{delays[i]}', + f'{decays[i]}' ]) self.effects.extend(effect_args) @@ -1768,13 +1766,13 @@ def echos(self, ) effect_args = [ - 'echos', '{:f}'.format(gain_in), '{:f}'.format(gain_out) + 'echos', f'{gain_in:f}', f'{gain_out:f}' ] for i in range(n_echos): effect_args.extend([ - '{:f}'.format(delays[i]), - '{:f}'.format(decays[i]) + f'{delays[i]:f}', + f'{decays[i]:f}' ]) self.effects.extend(effect_args) @@ -1814,9 +1812,9 @@ def equalizer(self, effect_args = [ 'equalizer', - '{:f}'.format(frequency), - '{:f}q'.format(width_q), - '{:f}'.format(gain_db) + f'{frequency:f}', + f'{width_q:f}q', + f'{gain_db:f}' ] self.effects.extend(effect_args) self.effects_log.append('equalizer') @@ -1863,13 +1861,13 @@ def fade(self, fade_in_len: float = 0.0, if fade_in_len > 0: effect_args.extend([ - 'fade', '{}'.format(fade_shape), '{:f}'.format(fade_in_len) + 'fade', f'{fade_shape}', f'{fade_in_len:f}' ]) if fade_out_len > 0: effect_args.extend([ - 'reverse', 'fade', '{}'.format(fade_shape), - '{:f}'.format(fade_out_len), 'reverse' + 'reverse', 'fade', f'{fade_shape}', + f'{fade_out_len:f}', 'reverse' ]) if len(effect_args) > 0: @@ -1894,7 +1892,7 @@ def fir(self, coefficients: List[float]): raise ValueError("coefficients must be numbers.") effect_args = ['fir'] - effect_args.extend(['{:f}'.format(c) for c in coefficients]) + effect_args.extend([f'{c:f}' for c in coefficients]) self.effects.extend(effect_args) self.effects_log.append('fir') @@ -1952,14 +1950,14 @@ def flanger(self, effect_args = [ 'flanger', - '{:f}'.format(delay), - '{:f}'.format(depth), - '{:f}'.format(regen), - '{:f}'.format(width), - '{:f}'.format(speed), - '{}'.format(shape), - '{:f}'.format(phase), - '{}'.format(interp) + f'{delay:f}', + f'{depth:f}', + f'{regen:f}', + f'{width:f}', + f'{speed:f}', + f'{shape}', + f'{phase:f}', + f'{interp}' ] self.effects.extend(effect_args) @@ -2017,7 +2015,7 @@ def gain(self, effect_args = ['gain'] if balance is not None: - effect_args.append('-{}'.format(balance)) + effect_args.append(f'-{balance}') if normalize: effect_args.append('-n') @@ -2025,7 +2023,7 @@ def gain(self, if limiter: effect_args.append('-l') - effect_args.append('{:f}'.format(gain_db)) + effect_args.append(f'{gain_db:f}') self.effects.extend(effect_args) self.effects_log.append('gain') @@ -2064,11 +2062,11 @@ def highpass(self, raise ValueError("n_poles must be 1 or 2.") effect_args = [ - 'highpass', '-{}'.format(n_poles), '{:f}'.format(frequency) + 'highpass', f'-{n_poles}', f'{frequency:f}' ] if n_poles == 2: - effect_args.append('{:f}q'.format(width_q)) + effect_args.append(f'{width_q:f}q') self.effects.extend(effect_args) self.effects_log.append('highpass') @@ -2108,11 +2106,11 @@ def lowpass(self, raise ValueError("n_poles must be 1 or 2.") effect_args = [ - 'lowpass', '-{}'.format(n_poles), '{:f}'.format(frequency) + 'lowpass', f'-{n_poles}', f'{frequency:f}' ] if n_poles == 2: - effect_args.append('{:f}q'.format(width_q)) + effect_args.append(f'{width_q:f}q') self.effects.extend(effect_args) self.effects_log.append('lowpass') @@ -2143,7 +2141,7 @@ def hilbert(self, num_taps: Optional[int] = None): effect_args = ['hilbert'] if num_taps is not None: - effect_args.extend(['-n', '{}'.format(num_taps)]) + effect_args.extend(['-n', f'{num_taps}']) self.effects.extend(effect_args) self.effects_log.append('hilbert') @@ -2181,8 +2179,8 @@ def loudness(self, gain_db: float = -10.0, reference_level: float = 65.0): effect_args = [ 'loudness', - '{:f}'.format(gain_db), - '{:f}'.format(reference_level) + f'{gain_db:f}', + f'{reference_level:f}' ] self.effects.extend(effect_args) self.effects_log.append('loudness') @@ -2310,7 +2308,7 @@ def mcompand(self, raise ValueError( "Tuple values in tf_points lists must be <= 0 (dB)." ) - if len(tfp) > len(set([p[0] for p in tfp])): + if len(tfp) > len({p[0] for p in tfp}): raise ValueError("Found duplicate x-value in tf_points list.") if not isinstance(gain, list) or len(gain) != n_bands: @@ -2324,9 +2322,9 @@ def mcompand(self, for i in range(n_bands): if i > 0: - effect_args.append('{:f}'.format(crossover_frequencies[i - 1])) + effect_args.append(f'{crossover_frequencies[i - 1]:f}') - intermed_args = ["{:f},{:f}".format(attack_time[i], decay_time[i])] + intermed_args = [f"{attack_time[i]:f},{decay_time[i]:f}"] tf_points_band = tf_points[i] tf_points_band = sorted( @@ -2336,7 +2334,7 @@ def mcompand(self, transfer_list = [] for point in tf_points_band: transfer_list.extend([ - "{:f}".format(point[0]), "{:f}".format(point[1]) + f"{point[0]:f}", f"{point[1]:f}" ]) if soft_knee_db[i] is not None: @@ -2347,7 +2345,7 @@ def mcompand(self, intermed_args.append(",".join(transfer_list)) if gain[i] is not None: - intermed_args.append("{:f}".format(gain[i])) + intermed_args.append(f"{gain[i]:f}") effect_args.append(' '.join(intermed_args)) @@ -2377,7 +2375,7 @@ def noiseprof(self, ''' if os.path.isdir(profile_path): raise ValueError( - "profile_path {} is a directory.".format(profile_path)) + f"profile_path {profile_path} is a directory.") if os.path.dirname(profile_path) == '' and profile_path != '': _abs_profile_path = os.path.join(os.getcwd(), profile_path) @@ -2385,8 +2383,8 @@ def noiseprof(self, _abs_profile_path = profile_path if not os.access(os.path.dirname(_abs_profile_path), os.W_OK): - raise IOError( - "profile_path {} is not writeable.".format(_abs_profile_path)) + raise OSError( + f"profile_path {_abs_profile_path} is not writeable.") effect_args = ['noiseprof', profile_path] self.build(input_filepath, '-n', extra_args=effect_args) @@ -2416,8 +2414,8 @@ def noisered(self, profile_path: Union[str, Path], amount: float = 0.5): ''' if not os.path.exists(profile_path): - raise IOError( - "profile_path {} does not exist.".format(profile_path)) + raise OSError( + f"profile_path {profile_path} does not exist.") if not is_number(amount) or amount < 0 or amount > 1: raise ValueError("amount must be a number between 0 and 1.") @@ -2425,7 +2423,7 @@ def noisered(self, profile_path: Union[str, Path], amount: float = 0.5): effect_args = [ 'noisered', profile_path, - '{:f}'.format(amount) + f'{amount:f}' ] self.effects.extend(effect_args) self.effects_log.append('noisered') @@ -2451,7 +2449,7 @@ def norm(self, db_level: float = -3.0): effect_args = [ 'norm', - '{:f}'.format(db_level) + f'{db_level:f}' ] self.effects.extend(effect_args) self.effects_log.append('norm') @@ -2490,8 +2488,8 @@ def overdrive(self, gain_db: float = 20.0, colour: float = 20.0): effect_args = [ 'overdrive', - '{:f}'.format(gain_db), - '{:f}'.format(colour) + f'{gain_db:f}', + f'{colour:f}' ] self.effects.extend(effect_args) self.effects_log.append('overdrive') @@ -2522,8 +2520,8 @@ def pad(self, start_duration: float = 0.0, end_duration: float = 0.0): effect_args = [ 'pad', - '{:f}'.format(start_duration), - '{:f}'.format(end_duration) + f'{start_duration:f}', + f'{end_duration:f}' ] self.effects.extend(effect_args) self.effects_log.append('pad') @@ -2577,11 +2575,11 @@ def phaser(self, effect_args = [ 'phaser', - '{:f}'.format(gain_in), - '{:f}'.format(gain_out), - '{:f}'.format(delay), - '{:f}'.format(decay), - '{:f}'.format(speed) + f'{gain_in:f}', + f'{gain_out:f}', + f'{delay:f}', + f'{decay:f}', + f'{speed:f}' ] if modulation_shape == 'sinusoidal': @@ -2631,7 +2629,7 @@ def pitch(self, n_semitones: float, quick: bool = False): if quick: effect_args.append('-q') - effect_args.append('{:f}'.format(n_semitones * 100.)) + effect_args.append(f'{n_semitones * 100.:f}') self.effects.extend(effect_args) self.effects_log.append('pitch') @@ -2671,8 +2669,8 @@ def rate(self, samplerate: float, effect_args = [ 'rate', - '-{}'.format(quality), - '{:f}'.format(samplerate) + f'-{quality}', + f'{samplerate:f}' ] self.effects.extend(effect_args) self.effects_log.append('rate') @@ -2773,7 +2771,7 @@ def repeat(self, count: int = 1): if not isinstance(count, int) or count < 1: raise ValueError("count must be a postive integer.") - effect_args = ['repeat', '{}'.format(count)] + effect_args = ['repeat', f'{count}'] self.effects.extend(effect_args) self.effects_log.append('repeat') @@ -2845,12 +2843,12 @@ def reverb(self, effect_args.append('-w') effect_args.extend([ - '{:f}'.format(reverberance), - '{:f}'.format(high_freq_damping), - '{:f}'.format(room_scale), - '{:f}'.format(stereo_depth), - '{:f}'.format(pre_delay), - '{:f}'.format(wet_gain) + f'{reverberance:f}', + f'{high_freq_damping:f}', + f'{room_scale:f}', + f'{stereo_depth:f}', + f'{pre_delay:f}', + f'{wet_gain:f}' ]) self.effects.extend(effect_args) @@ -2928,15 +2926,15 @@ def silence(self, effect_args.extend([ '1', - '{:f}'.format(min_silence_duration), - '{:f}%'.format(silence_threshold) + f'{min_silence_duration:f}', + f'{silence_threshold:f}%' ]) if location == 0: effect_args.extend([ '-1', - '{:f}'.format(min_silence_duration), - '{:f}%'.format(silence_threshold) + f'{min_silence_duration:f}', + f'{silence_threshold:f}%' ]) if location == -1: @@ -3058,36 +3056,36 @@ def sinc(self, raise ValueError("phase response must be between 0 and 100") effect_args = ['sinc'] - effect_args.extend(['-a', '{:f}'.format(stop_band_attenuation)]) + effect_args.extend(['-a', f'{stop_band_attenuation:f}']) if phase_response is not None: - effect_args.extend(['-p', '{:f}'.format(phase_response)]) + effect_args.extend(['-p', f'{phase_response:f}']) if filter_type == 'high': if transition_bw is not None: - effect_args.extend(['-t', '{:f}'.format(transition_bw)]) - effect_args.append('{:f}'.format(cutoff_freq)) + effect_args.extend(['-t', f'{transition_bw:f}']) + effect_args.append(f'{cutoff_freq:f}') elif filter_type == 'low': - effect_args.append('-{:f}'.format(cutoff_freq)) + effect_args.append(f'-{cutoff_freq:f}') if transition_bw is not None: - effect_args.extend(['-t', '{:f}'.format(transition_bw)]) + effect_args.extend(['-t', f'{transition_bw:f}']) else: if is_number(transition_bw): - effect_args.extend(['-t', '{:f}'.format(transition_bw)]) + effect_args.extend(['-t', f'{transition_bw:f}']) elif isinstance(transition_bw, list): - effect_args.extend(['-t', '{:f}'.format(transition_bw[0])]) + effect_args.extend(['-t', f'{transition_bw[0]:f}']) if filter_type == 'pass': effect_args.append( - '{:f}-{:f}'.format(cutoff_freq[0], cutoff_freq[1]) + f'{cutoff_freq[0]:f}-{cutoff_freq[1]:f}' ) elif filter_type == 'reject': effect_args.append( - '{:f}-{:f}'.format(cutoff_freq[1], cutoff_freq[0]) + f'{cutoff_freq[1]:f}-{cutoff_freq[0]:f}' ) if isinstance(transition_bw, list): - effect_args.extend(['-t', '{:f}'.format(transition_bw[1])]) + effect_args.extend(['-t', f'{transition_bw[1]:f}']) self.effects.extend(effect_args) self.effects_log.append('sinc') @@ -3123,7 +3121,7 @@ def speed(self, factor: float): "Using an extreme factor. Quality of results will be poor" ) - effect_args = ['speed', '{:f}'.format(factor)] + effect_args = ['speed', f'{factor:f}'] self.effects.extend(effect_args) self.effects_log.append('speed') @@ -3165,7 +3163,7 @@ def stat(self, if scale is not None: if not is_number(scale) or scale <= 0: raise ValueError("scale must be a positive number.") - effect_args.extend(['-s', '{:f}'.format(scale)]) + effect_args.extend(['-s', f'{scale:f}']) if rms: effect_args.append('-rms') @@ -3310,7 +3308,7 @@ def stretch(self, factor: float, window: float = 20): "window must be a positive number." ) - effect_args = ['stretch', '{:f}'.format(factor), '{:f}'.format(window)] + effect_args = ['stretch', f'{factor:f}', f'{window:f}'] self.effects.extend(effect_args) self.effects_log.append('stretch') @@ -3391,9 +3389,9 @@ def tempo(self, factor: float, effect_args.append('-q') if audio_type is not None: - effect_args.append('-{}'.format(audio_type)) + effect_args.append(f'-{audio_type}') - effect_args.append('{:f}'.format(factor)) + effect_args.append(f'{factor:f}') self.effects.extend(effect_args) self.effects_log.append('tempo') @@ -3436,8 +3434,8 @@ def treble(self, gain_db: float, raise ValueError("width_q must be a positive number.") effect_args = [ - 'treble', '{:f}'.format(gain_db), '{:f}'.format(frequency), - '{:f}s'.format(slope) + 'treble', f'{gain_db:f}', f'{frequency:f}', + f'{slope:f}s' ] self.effects.extend(effect_args) @@ -3476,8 +3474,8 @@ def tremolo(self, speed: float = 6.0, depth: float = 40.0): effect_args = [ 'tremolo', - '{:f}'.format(speed), - '{:f}'.format(depth) + f'{speed:f}', + f'{depth:f}' ] self.effects.extend(effect_args) @@ -3501,7 +3499,7 @@ def trim(self, start_time: float, end_time: Optional[float] = None): effect_args = [ 'trim', - '{:f}'.format(start_time) + f'{start_time:f}' ] if end_time is not None: @@ -3510,7 +3508,7 @@ def trim(self, start_time: float, end_time: Optional[float] = None): if start_time >= end_time: raise ValueError("start_time must be smaller than end_time.") - effect_args.append('{:f}'.format(end_time - start_time)) + effect_args.append(f'{end_time - start_time:f}') self.effects.extend(effect_args) self.effects_log.append('trim') @@ -3537,7 +3535,7 @@ def upsample(self, factor: int = 2): if not isinstance(factor, int) or factor < 1: raise ValueError('factor must be a positive integer.') - effect_args = ['upsample', '{}'.format(factor)] + effect_args = ['upsample', f'{factor}'] self.effects.extend(effect_args) self.effects_log.append('upsample') @@ -3626,11 +3624,11 @@ def vad(self, effect_args.extend([ 'vad', - '-t', '{:f}'.format(activity_threshold), - '-T', '{:f}'.format(min_activity_duration), - '-s', '{:f}'.format(initial_search_buffer), - '-g', '{:f}'.format(max_gap), - '-p', '{:f}'.format(initial_pad) + '-t', f'{activity_threshold:f}', + '-T', f'{min_activity_duration:f}', + '-s', f'{initial_search_buffer:f}', + '-g', f'{max_gap:f}', + '-p', f'{initial_pad:f}' ]) if location == -1: @@ -3683,7 +3681,7 @@ def vol(self, gain: float, effect_args = ['vol'] - effect_args.append('{:f}'.format(gain)) + effect_args.append(f'{gain:f}') if gain_type == 'amplitude': effect_args.append('amplitude') @@ -3696,9 +3694,9 @@ def vol(self, gain: float, if limiter_gain is not None: if gain_type in ['amplitude', 'power'] and gain > 1: - effect_args.append('{:f}'.format(limiter_gain)) + effect_args.append(f'{limiter_gain:f}') elif gain_type == 'db' and gain > 0: - effect_args.append('{:f}'.format(limiter_gain)) + effect_args.append(f'{limiter_gain:f}') self.effects.extend(effect_args) self.effects_log.append('vol') diff --git a/sox/version.py b/sox/version.py index 53f42c1..6dcd265 100644 --- a/sox/version.py +++ b/sox/version.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """Version info""" short_version = '1.4'