Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ruff formatter as pre-commit #149

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .flake8

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Set up Python 3.8
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: '3.8'
python-version: '3.10'

- name: Install pre-commit hooks
run: |
Expand Down
6 changes: 4 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
#
#
default_language_version:
python: python3.8
python: python3.10

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.276
rev: v0.1.8
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
- repo: https://github.com/codespell-project/codespell
rev: v2.2.4
hooks:
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Coding Convention
-----------------

We follow the PEP8_ convention for Python code
and check for correct syntax with ruff_.
and use ruff_ as a linter and code formatter.
In addition,
we check for common spelling errors with codespell_.
Both tools and possible exceptions
Expand All @@ -61,7 +61,8 @@ You can also install ruff_ and codespell_
and call it directly::

pip install ruff codespell # consider system wide installation
ruff check .
ruff check --fix . # lint all Python files, and fix any fixable errors
ruff format . # format code of all Python files
codespell

It can be restricted to specific folders::
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Code example for reading a file:

import audiofile

signal, sampling_rate = audiofile.read('signal.wav')
signal, sampling_rate = audiofile.read("signal.wav")

Under the hood it uses soundfile_ to read the audio files,
converting non-supported formats first to WAV files.
Expand Down
1 change: 1 addition & 0 deletions audiofile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# Dynamically get the version of the installed module
try:
import importlib.metadata

__version__ = importlib.metadata.version(__name__)
except Exception: # pragma: no cover
importlib = None # pragma: no cover
Expand Down
29 changes: 14 additions & 15 deletions audiofile/core/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,28 @@
np.random.seed(1)


@pytest.fixture(scope='session', autouse=True)
@pytest.fixture(scope="session", autouse=True)
def audio_file():
create_audio_files('.')
create_audio_files(".")

yield

# Clean up
for file in audeer.list_file_names('.', filetype='wav'):
for file in audeer.list_file_names(".", filetype="wav"):
if os.path.exists(file):
os.remove(file)
for file in audeer.list_file_names('.', filetype='flac'):
for file in audeer.list_file_names(".", filetype="flac"):
if os.path.exists(file):
os.remove(file)


def create_audio_files(
basedir,

basedir,
):
sampling_rate = 8000
mono_wav_file = audeer.path(basedir, 'mono.wav')
stereo_wav_file = audeer.path(basedir, 'stereo.wav')
stereo_flac_file = audeer.path(basedir, 'stereo.flac')
mono_wav_file = audeer.path(basedir, "mono.wav")
stereo_wav_file = audeer.path(basedir, "stereo.wav")
stereo_flac_file = audeer.path(basedir, "stereo.flac")
signal = am_fm_synth(1.5, 1, sampling_rate)
audiofile.write(mono_wav_file, signal, sampling_rate)
signal = am_fm_synth(1.5, 2, sampling_rate)
Expand All @@ -42,11 +41,11 @@ def create_audio_files(


def am_fm_synth(
duration: float,
num_channels: int = 1,
sampling_rate: int = 16000,
*,
dtype: type = np.float32,
duration: float,
num_channels: int = 1,
sampling_rate: int = 16000,
*,
dtype: type = np.float32,
) -> np.ndarray:
r"""Synthesise an AM/FM signal of given duration (sampled at given rate).

Expand Down Expand Up @@ -78,7 +77,7 @@ def am_fm_synth(
# No reinitialisation (to get true stereo)
for t in range(n_samples):
sig[ch_indx, t] = g * np.cos(ph_fm)
sig[ch_indx, t] *= ((1 - g_am) + g_am * np.square(np.cos(ph_am)))
sig[ch_indx, t] *= (1 - g_am) + g_am * np.square(np.cos(ph_am))
ph_am += omega_am / 2
ph_fm += omega0_car + omega_dev * np.cos(omega_mod * t)
return sig
10 changes: 5 additions & 5 deletions audiofile/core/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@


def convert(
infile: str,
outfile: str,
offset: float = 0,
duration: float = None,
infile: str,
outfile: str,
offset: float = 0,
duration: float = None,
):
"""Convert any audio/video file to WAV.

Expand All @@ -29,6 +29,6 @@ def convert(
# Convert to WAV file with ffmpeg
run_ffmpeg(infile, outfile, offset, duration)
except FileNotFoundError:
raise binary_missing_error('ffmpeg')
raise binary_missing_error("ffmpeg")
except subprocess.CalledProcessError:
raise broken_file_error(infile)
81 changes: 38 additions & 43 deletions audiofile/core/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,35 @@ def bit_depth(file: str) -> typing.Optional[int]:
broken or format is not supported

Examples:
>>> bit_depth('stereo.wav')
>>> bit_depth("stereo.wav")
16

"""
file = audeer.safe_path(file)
file_type = file_extension(file)
if file_type == 'wav':
if file_type == "wav":
precision_mapping = {
'PCM_16': 16,
'PCM_24': 24,
'PCM_32': 32,
'PCM_U8': 8,
'FLOAT': 32,
'DOUBLE': 64,
'ULAW': 8,
'ALAW': 8,
'IMA_ADPCM': 4,
'MS_ADPCM': 4,
'GSM610': 16, # not sure if this could be variable?
'G721_32': 4, # not sure if correct
"PCM_16": 16,
"PCM_24": 24,
"PCM_32": 32,
"PCM_U8": 8,
"FLOAT": 32,
"DOUBLE": 64,
"ULAW": 8,
"ALAW": 8,
"IMA_ADPCM": 4,
"MS_ADPCM": 4,
"GSM610": 16, # not sure if this could be variable?
"G721_32": 4, # not sure if correct
}
elif file_type == 'flac':
elif file_type == "flac":
precision_mapping = {
'PCM_16': 16,
'PCM_24': 24,
'PCM_32': 32,
'PCM_S8': 8,
"PCM_16": 16,
"PCM_24": 24,
"PCM_32": 32,
"PCM_S8": 8,
}
if file_extension(file) in ['wav', 'flac']:
if file_extension(file) in ["wav", "flac"]:
depth = precision_mapping[soundfile.info(file).subtype]
else:
depth = None
Expand All @@ -85,7 +85,7 @@ def channels(file: str) -> int:
broken or format is not supported

Examples:
>>> channels('stereo.wav')
>>> channels("stereo.wav")
2

"""
Expand All @@ -94,20 +94,16 @@ def channels(file: str) -> int:
return soundfile.info(file).channels
else:
try:
cmd = ['soxi', '-c', file]
cmd = ["soxi", "-c", file]
return int(run(cmd))
except (FileNotFoundError, subprocess.CalledProcessError):
# For MP4 stored and returned number of channels can be different
cmd1 = [
'mediainfo', '--Inform=Audio;%Channel(s)_Original%', file
]
cmd2 = [
'mediainfo', '--Inform=Audio;%Channel(s)%', file
]
cmd1 = ["mediainfo", "--Inform=Audio;%Channel(s)_Original%", file]
cmd2 = ["mediainfo", "--Inform=Audio;%Channel(s)%", file]
try:
return int(run(cmd1))
except FileNotFoundError:
raise binary_missing_error('mediainfo')
raise binary_missing_error("mediainfo")
except (ValueError, subprocess.CalledProcessError):
try:
return int(run(cmd2))
Expand Down Expand Up @@ -152,7 +148,7 @@ def duration(file: str, sloppy=False) -> float:
broken or format is not supported

Examples:
>>> duration('stereo.wav')
>>> duration("stereo.wav")
1.5

"""
Expand All @@ -162,17 +158,17 @@ def duration(file: str, sloppy=False) -> float:

if sloppy:
try:
cmd = ['soxi', '-D', file]
cmd = ["soxi", "-D", file]
duration = float(run(cmd))
except (FileNotFoundError, subprocess.CalledProcessError):
try:
cmd = ['mediainfo', '--Inform=Audio;%Duration%', file]
cmd = ["mediainfo", "--Inform=Audio;%Duration%", file]
duration = run(cmd)
if duration:
# Convert to seconds, as mediainfo returns milliseconds
duration = float(duration) / 1000
except FileNotFoundError:
raise binary_missing_error('mediainfo')
raise binary_missing_error("mediainfo")
# Behavior for broken files is different on Windows
# where no error is raised,
# but an empty duration is returned.
Expand Down Expand Up @@ -206,22 +202,21 @@ def samples(file: str) -> int:
broken or format is not supported

Examples:
>>> samples('stereo.wav')
>>> samples("stereo.wav")
12000

"""

def samples_as_int(file):
return int(
soundfile.info(file).duration * soundfile.info(file).samplerate
)
return int(soundfile.info(file).duration * soundfile.info(file).samplerate)

file = audeer.safe_path(file)
if file_extension(file) in SNDFORMATS:
return samples_as_int(file)
else:
# Always convert to WAV for non SNDFORMATS
with tempfile.TemporaryDirectory(prefix='audiofile') as tmpdir:
tmpfile = os.path.join(tmpdir, 'tmp.wav')
with tempfile.TemporaryDirectory(prefix="audiofile") as tmpdir:
tmpfile = os.path.join(tmpdir, "tmp.wav")
convert_to_wav(file, tmpfile)
return samples_as_int(tmpfile)

Expand All @@ -242,7 +237,7 @@ def sampling_rate(file: str) -> int:
broken or format is not supported

Examples:
>>> sampling_rate('stereo.wav')
>>> sampling_rate("stereo.wav")
8000

"""
Expand All @@ -251,11 +246,11 @@ def sampling_rate(file: str) -> int:
return soundfile.info(file).samplerate
else:
try:
cmd = ['soxi', '-r', file]
cmd = ["soxi", "-r", file]
return int(run(cmd))
except (FileNotFoundError, subprocess.CalledProcessError):
try:
cmd = ['mediainfo', '--Inform=Audio;%SamplingRate%', file]
cmd = ["mediainfo", "--Inform=Audio;%SamplingRate%", file]
sampling_rate = run(cmd)
if sampling_rate:
return int(sampling_rate)
Expand All @@ -264,6 +259,6 @@ def sampling_rate(file: str) -> int:
# to align coverage under Windows and Linux
raise subprocess.CalledProcessError(-2, cmd)
except FileNotFoundError:
raise binary_missing_error('mediainfo')
raise binary_missing_error("mediainfo")
except subprocess.CalledProcessError:
raise broken_file_error(file)
Loading
Loading