Skip to content

Commit

Permalink
Switch to ruff. Use pypugrade on pre-commit (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ch00k authored Dec 19, 2024
1 parent 1a1f1d0 commit 6972473
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 319 deletions.
11 changes: 4 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@ jobs:
python-version: "3.12"
architecture: x64
- run: |
pip install poetry
poetry install --with dev
- run: poetry run flake8 .
- run: poetry run black --check --diff .
- run: poetry run isort --check --diff .
- run: poetry run mypy .
pip install pre-commit
pre-commit run --all-files
test:
runs-on: ubuntu-latest
Expand All @@ -38,6 +34,7 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "pypy3.8"
- "pypy3.9"
- "pypy3.10"
Expand All @@ -49,7 +46,7 @@ jobs:
python-version: ${{ matrix.python-version }}
architecture: x64
- run: |
pip install poetry
pip install "cryptography<44.0.0" poetry # cryptography 44.0.0 is not compatible with pypy3.8
poetry install --with dev
- run: poetry run pytest --cov=ffmpy --cov-report xml
- uses: codecov/codecov-action@v4
Expand Down
20 changes: 20 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
default_language_version:
python: python3.12

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
- id: ruff-format

- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
hooks:
- id: pyupgrade
args: [--py38-plus, --keep-runtime-typing]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
4 changes: 1 addition & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import datetime
from typing import Dict

extensions = [
"sphinx.ext.autodoc",
Expand Down Expand Up @@ -33,7 +31,7 @@

htmlhelp_basename = "ffmpydoc"

latex_elements: Dict = {}
latex_elements: dict = {}
latex_documents = [
(master_doc, "ffmpy.tex", "ffmpy Documentation", "Andrii Yurchuk", "manual"),
]
Expand Down
52 changes: 25 additions & 27 deletions ffmpy.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
from __future__ import annotations

import errno
import itertools
import shlex
import subprocess
from typing import IO, Any, List, Mapping, Optional, Sequence, Tuple, Union
from typing import IO, Any, Mapping, Sequence


class FFmpeg(object):
class FFmpeg:
"""Wrapper for various `FFmpeg <https://www.ffmpeg.org/>`_ related applications (ffmpeg,
ffprobe).
"""

def __init__(
self,
executable: str = "ffmpeg",
global_options: Optional[Union[Sequence[str], str]] = None,
inputs: Optional[Mapping[str, Optional[Union[Sequence[str], str]]]] = None,
outputs: Optional[Mapping[str, Optional[Union[Sequence[str], str]]]] = None,
global_options: Sequence[str] | str | None = None,
inputs: Mapping[str, Sequence[str] | str | None] | None = None,
outputs: Mapping[str, Sequence[str] | str | None] | None = None,
) -> None:
"""Initialize FFmpeg command line wrapper.
Expand Down Expand Up @@ -54,19 +56,19 @@ def __init__(
self._cmd += _merge_args_opts(outputs)

self.cmd = subprocess.list2cmdline(self._cmd)
self.process: Optional[subprocess.Popen] = None
self.process: subprocess.Popen | None = None

def __repr__(self) -> str:
return "<{0!r} {1!r}>".format(self.__class__.__name__, self.cmd)
return f"<{self.__class__.__name__!r} {self.cmd!r}>"

def run(
self,
input_data: Optional[bytes] = None,
stdout: Optional[Union[IO, int]] = None,
stderr: Optional[Union[IO, int]] = None,
env: Optional[Mapping[str, str]] = None,
**kwargs: Any
) -> Tuple[Optional[bytes], Optional[bytes]]:
input_data: bytes | None = None,
stdout: IO | int | None = None,
stderr: IO | int | None = None,
env: Mapping[str, str] | None = None,
**kwargs: Any,
) -> tuple[bytes | None, bytes | None]:
"""Execute FFmpeg command line.
``input_data`` can contain input for FFmpeg in case ``pipe`` protocol is used for input.
Expand Down Expand Up @@ -103,7 +105,7 @@ def run(
)
except OSError as e:
if e.errno == errno.ENOENT:
raise FFExecutableNotFoundError("Executable '{0}' not found".format(self.executable))
raise FFExecutableNotFoundError(f"Executable '{self.executable}' not found")
else:
raise

Expand All @@ -120,8 +122,8 @@ class FFprobe(FFmpeg):
def __init__(
self,
executable: str = "ffprobe",
global_options: Optional[Union[Sequence[str], str]] = None,
inputs: Optional[Mapping[str, Optional[Union[Sequence[str], str]]]] = None,
global_options: Sequence[str] | str | None = None,
inputs: Mapping[str, Sequence[str] | str | None] | None = None,
) -> None:
"""Create an instance of FFprobe.
Expand All @@ -136,9 +138,7 @@ def __init__(
:param dict inputs: a dictionary specifying one or more inputs as keys with their
corresponding options as values
"""
super(FFprobe, self).__init__(
executable=executable, global_options=global_options, inputs=inputs
)
super().__init__(executable=executable, global_options=global_options, inputs=inputs)


class FFExecutableNotFoundError(Exception):
Expand All @@ -158,17 +158,17 @@ def __init__(self, cmd: str, exit_code: int, stdout: bytes, stderr: bytes) -> No
self.stdout = stdout
self.stderr = stderr

message = "`{0}` exited with status {1}\n\nSTDOUT:\n{2}\n\nSTDERR:\n{3}".format(
message = "`{}` exited with status {}\n\nSTDOUT:\n{}\n\nSTDERR:\n{}".format(
self.cmd, exit_code, (stdout or b"").decode(), (stderr or b"").decode()
)

super(FFRuntimeError, self).__init__(message)
super().__init__(message)


def _merge_args_opts(
args_opts_dict: Mapping[str, Optional[Union[Sequence[str], str]]],
args_opts_dict: Mapping[str, Sequence[str] | str | None],
add_minus_i_option: bool = False,
) -> List[str]:
) -> list[str]:
"""Merge options with their corresponding arguments.
Iterates over the dictionary holding arguments (keys) and options (values). Merges each
Expand All @@ -179,7 +179,7 @@ def _merge_args_opts(
:return: merged list of strings with arguments and their corresponding options
:rtype: list
"""
merged: List[str] = []
merged: list[str] = []

for arg, opt in args_opts_dict.items():
merged += _normalize_options(opt)
Expand All @@ -195,9 +195,7 @@ def _merge_args_opts(
return merged


def _normalize_options(
options: Optional[Union[Sequence[str], str]], split_mixed: bool = False
) -> List[str]:
def _normalize_options(options: Sequence[str] | str | None, split_mixed: bool = False) -> list[str]:
"""Normalize options string or list of strings.
Splits `options` into a list of strings. If `split_mixed` is `True`, splits (flattens) mixed
Expand Down
Loading

0 comments on commit 6972473

Please sign in to comment.