Skip to content

Commit

Permalink
first format
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemia committed Feb 11, 2025
1 parent 6c2d4a4 commit 858e63b
Show file tree
Hide file tree
Showing 23 changed files with 2,728 additions and 816 deletions.
33 changes: 8 additions & 25 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,16 @@ repos:
- id: pretty-format-json
args: [--autofix]
exclude: "__snapshots__/"
# this is not technically always safe but usually is
# use comments `# isort: off` and `# isort: on` to disable/re-enable isort
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: [--line-length=120, --profile=black]

# this is slightly dangerous because python imports have side effects
# and this tool removes unused imports, which may be providing
# necessary side effects for the code to run
- repo: https://github.com/PyCQA/autoflake
rev: v1.6.1
hooks:
- id: autoflake
args:
- "--in-place"
- "--expand-star-imports"
- "--remove-duplicate-keys"
- "--remove-unused-variables"
- "--remove-all-unused-imports"

- repo: https://github.com/psf/black
rev: 22.8.0
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.9.1
hooks:
- id: black
args: [--line-length=120, --exclude=""]
# Run the linter.
- id: ruff
args: [--fix]
# Run the formatter.
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
Expand Down
14 changes: 6 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ src = ["src"]
[tool.ruff.lint] # https://docs.astral.sh/ruff/settings/#lint
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
# "W", # pycodestyle warnings
# "F", # pyflakes
# "I", # isort
# "B", # flake8-bugbear
"B006", # flake8-bugbear: Do not use mutable data structures for argument defaults
"C4", # flake8-comprehensions
"UP", # pyupgrade
# "B006", # flake8-bugbear: Do not use mutable data structures for argument defaults
# "C4", # flake8-comprehensions
# "UP", # pyupgrade
]
ignore = [
"E741", # Ambiguous variable name: `I`
Expand All @@ -126,8 +126,6 @@ ignore = [
"E712", # not work for pandas
"F811", # FIXME: we relay on it to share fixture across app
]
[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]

[tool.ruff.format] # https://docs.astral.sh/ruff/settings/#format
quote-style = "double" # 引號風格,雙引號是預設值
Expand Down
29 changes: 24 additions & 5 deletions src/ffmpeg/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

from .dag.io._input import input
from .dag.io._output import output
from .dag.nodes import FilterableStream, FilterNode, GlobalNode, GlobalStream, OutputStream
from .dag.nodes import (
FilterableStream,
FilterNode,
GlobalNode,
GlobalStream,
OutputStream,
)
from .schema import StreamType
from .streams.audio import AudioStream
from .streams.video import VideoStream
Expand All @@ -26,7 +32,10 @@ def merge_outputs(*streams: OutputStream) -> GlobalStream:


def vfilter(
*streams: FilterableStream, name: str, input_typings: tuple[StreamType, ...] = (StreamType.video,), **kwargs: Any
*streams: FilterableStream,
name: str,
input_typings: tuple[StreamType, ...] = (StreamType.video,),
**kwargs: Any,
) -> VideoStream:
"""
Apply a custom video filter which has only one output to this stream
Expand All @@ -53,7 +62,10 @@ def vfilter(


def afilter(
*streams: FilterableStream, name: str, input_typings: tuple[StreamType, ...] = (StreamType.audio,), **kwargs: Any
*streams: FilterableStream,
name: str,
input_typings: tuple[StreamType, ...] = (StreamType.audio,),
**kwargs: Any,
) -> AudioStream:
"""
Apply a custom audio filter which has only one output to this stream
Expand Down Expand Up @@ -84,7 +96,7 @@ def filter_multi_output(
name: str,
input_typings: tuple[StreamType, ...] = (),
output_tyings: tuple[StreamType, ...] = (),
**kwargs: Any
**kwargs: Any,
) -> FilterNode:
"""
Apply a custom filter which has multiple outputs to this stream
Expand All @@ -111,4 +123,11 @@ def filter_multi_output(
)


__all__ = ["input", "output", "merge_outputs", "vfilter", "afilter", "filter_multi_output"]
__all__ = [
"input",
"output",
"merge_outputs",
"vfilter",
"afilter",
"filter_multi_output",
]
9 changes: 7 additions & 2 deletions src/ffmpeg/dag/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ def all_streams(self) -> list[Stream]:
"""
All streams in the graph sorted by the number of upstream nodes and the index of the stream.
"""
return sorted(self.streams, key=lambda stream: (len(stream.node.upstream_nodes), stream.index))
return sorted(
self.streams,
key=lambda stream: (len(stream.node.upstream_nodes), stream.index),
)

@cached_property
def outgoing_nodes(self) -> dict[Stream, list[tuple[Node, int]]]:
Expand Down Expand Up @@ -180,7 +183,9 @@ def get_node_label(self, node: Node) -> str:
The label of the node.
"""

assert isinstance(node, (InputNode, FilterNode)), "Only input and filter nodes have labels"
assert isinstance(node, (InputNode, FilterNode)), (
"Only input and filter nodes have labels"
)
return self.node_labels[node]

@override
Expand Down
4 changes: 3 additions & 1 deletion src/ffmpeg/dag/io/_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,7 @@ def output(
}

return OutputNode(
inputs=streams, filename=str(filename), kwargs=tuple((options | (extra_options or {})).items())
inputs=streams,
filename=str(filename),
kwargs=tuple((options | (extra_options or {})).items()),
).stream()
15 changes: 11 additions & 4 deletions src/ffmpeg/dag/io/tests/test_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@
def test_input(snapshot: SnapshotAssertion) -> None:
assert (
snapshot(extension_class=JSONSnapshotExtension)
== input("input.mp4", c="copy", accurate_seek=True, display_vflip=False, ss=5, display_rotation=1.0)
== input(
"input.mp4",
c="copy",
accurate_seek=True,
display_vflip=False,
ss=5,
display_rotation=1.0,
)
.output(filename="output.mp4")
.compile()
)


def test_input_with_filter(snapshot: SnapshotAssertion) -> None:
assert input("anullsrc", f="lavfi", t=10).output(filename="output.mp4").compile() == snapshot(
extension_class=JSONSnapshotExtension
)
assert input("anullsrc", f="lavfi", t=10).output(
filename="output.mp4"
).compile() == snapshot(extension_class=JSONSnapshotExtension)
7 changes: 6 additions & 1 deletion src/ffmpeg/dag/io/tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ def test_output(snapshot: SnapshotAssertion) -> None:
assert (
snapshot(extension_class=JSONSnapshotExtension)
== output(
input("input.mp4"), filename="output.mp4", c="copy", shortest=True, force_fps=False, ar=44100
input("input.mp4"),
filename="output.mp4",
c="copy",
shortest=True,
force_fps=False,
ar=44100,
).compile()
)
53 changes: 41 additions & 12 deletions src/ffmpeg/dag/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ def video(self, index: int) -> "VideoStream":
"""
from ..streams.video import VideoStream

video_outputs = [i for i, k in enumerate(self.output_typings) if k == StreamType.video]
video_outputs = [
i for i, k in enumerate(self.output_typings) if k == StreamType.video
]
if not len(video_outputs) > index:
raise FFMpegValueError(f"Specified index {index} is out of range for video outputs {len(video_outputs)}")
raise FFMpegValueError(
f"Specified index {index} is out of range for video outputs {len(video_outputs)}"
)
return VideoStream(node=self, index=video_outputs[index])

def audio(self, index: int) -> "AudioStream":
Expand All @@ -84,9 +88,13 @@ def audio(self, index: int) -> "AudioStream":
"""
from ..streams.audio import AudioStream

audio_outputs = [i for i, k in enumerate(self.output_typings) if k == StreamType.audio]
audio_outputs = [
i for i, k in enumerate(self.output_typings) if k == StreamType.audio
]
if not len(audio_outputs) > index:
raise FFMpegValueError(f"Specified index {index} is out of range for audio outputs {len(audio_outputs)}")
raise FFMpegValueError(
f"Specified index {index} is out of range for audio outputs {len(audio_outputs)}"
)

return AudioStream(node=self, index=audio_outputs[index])

Expand All @@ -97,12 +105,16 @@ def __post_init__(self) -> None:
super().__post_init__()

if len(self.inputs) != len(self.input_typings):
raise FFMpegValueError(f"Expected {len(self.input_typings)} inputs, got {len(self.inputs)}")
raise FFMpegValueError(
f"Expected {len(self.input_typings)} inputs, got {len(self.inputs)}"
)

stream: FilterableStream
expected_type: StreamType

for i, (stream, expected_type) in enumerate(zip(self.inputs, self.input_typings)):
for i, (stream, expected_type) in enumerate(
zip(self.inputs, self.input_typings)
):
if expected_type == StreamType.video:
if not isinstance(stream, VideoStream):
raise FFMpegTypeError(
Expand Down Expand Up @@ -132,7 +144,9 @@ def get_args(self, context: DAGContext = None) -> list[str]:

commands = []
for key, value in self.kwargs:
assert not isinstance(value, LazyValue), f"LazyValue should have been evaluated: {key}={value}"
assert not isinstance(value, LazyValue), (
f"LazyValue should have been evaluated: {key}={value}"
)

# Note: the -nooption syntax cannot be used for boolean AVOptions, use -option 0/-option 1.
if isinstance(value, bool):
Expand All @@ -142,7 +156,12 @@ def get_args(self, context: DAGContext = None) -> list[str]:
commands += [f"{key}={escape(value)}"]

if commands:
return [incoming_labels] + [f"{self.name}="] + [escape(":".join(commands), "\\'[],;")] + [outgoing_labels]
return (
[incoming_labels]
+ [f"{self.name}="]
+ [escape(":".join(commands), "\\'[],;")]
+ [outgoing_labels]
)
return [incoming_labels] + [f"{self.name}"] + [outgoing_labels]


Expand All @@ -155,7 +174,9 @@ class FilterableStream(Stream, OutputArgs):
node: "FilterNode | InputNode"

@override
def _output_node(self, *streams: FilterableStream, filename: str | Path, **kwargs: Any) -> OutputNode:
def _output_node(
self, *streams: FilterableStream, filename: str | Path, **kwargs: Any
) -> OutputNode:
"""
Output the streams to a file URL
Expand All @@ -167,7 +188,11 @@ def _output_node(self, *streams: FilterableStream, filename: str | Path, **kwarg
Returns:
the output stream
"""
return OutputNode(inputs=(self, *streams), filename=str(filename), kwargs=tuple(kwargs.items()))
return OutputNode(
inputs=(self, *streams),
filename=str(filename),
kwargs=tuple(kwargs.items()),
)

def vfilter(
self,
Expand Down Expand Up @@ -277,13 +302,17 @@ def label(self, context: DAGContext = None) -> str:
return f"{context.get_node_label(self.node)}:v"
elif isinstance(self, AudioStream):
return f"{context.get_node_label(self.node)}:a"
raise FFMpegValueError(f"Unknown stream type: {self.__class__.__name__}") # pragma: no cover
raise FFMpegValueError(
f"Unknown stream type: {self.__class__.__name__}"
) # pragma: no cover

if isinstance(self.node, FilterNode):
if len(self.node.output_typings) > 1:
return f"{context.get_node_label(self.node)}#{self.index}"
return f"{context.get_node_label(self.node)}"
raise FFMpegValueError(f"Unknown node type: {self.node.__class__.__name__}") # pragma: no cover
raise FFMpegValueError(
f"Unknown node type: {self.node.__class__.__name__}"
) # pragma: no cover

def __post_init__(self) -> None:
if isinstance(self.node, InputNode):
Expand Down
9 changes: 6 additions & 3 deletions src/ffmpeg/dag/tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ def test_filter_node_factory(snapshot: SnapshotAssertion) -> None:
in_file = input("foo.mp4")

f = filter_node_factory(
FFMpegFilterDef(name="foo", typings_input="[StreamType.video]*n"), **{"n": Auto("len(streams)")}
FFMpegFilterDef(name="foo", typings_input="[StreamType.video]*n"),
**{"n": Auto("len(streams)")},
)
assert snapshot == f
assert f.kwargs == tuple({"n": 0}.items())

f = filter_node_factory(
FFMpegFilterDef(name="foo", typings_input="[StreamType.video]*n"), in_file.video, **{"n": Auto("len(streams)")}
FFMpegFilterDef(name="foo", typings_input="[StreamType.video]*n"),
in_file.video,
**{"n": Auto("len(streams)")},
)
assert snapshot == f
assert f.kwargs == tuple({"n": 1}.items())
Expand All @@ -25,7 +28,7 @@ def test_filter_node_factory(snapshot: SnapshotAssertion) -> None:
FFMpegFilterDef(name="foo", typings_input="[StreamType.video]*n"),
in_file.video,
in_file.video,
**{"n": Auto("len(streams)")}
**{"n": Auto("len(streams)")},
)
assert snapshot == f
assert f.kwargs == tuple({"n": 2}.items())
Loading

0 comments on commit 858e63b

Please sign in to comment.