typed-ffmpeg-compatible 2.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. typed_ffmpeg/__init__.py +25 -0
  2. typed_ffmpeg/base.py +114 -0
  3. typed_ffmpeg/common/__init__.py +0 -0
  4. typed_ffmpeg/common/schema.py +308 -0
  5. typed_ffmpeg/common/serialize.py +132 -0
  6. typed_ffmpeg/dag/__init__.py +13 -0
  7. typed_ffmpeg/dag/compile.py +51 -0
  8. typed_ffmpeg/dag/context.py +221 -0
  9. typed_ffmpeg/dag/factory.py +31 -0
  10. typed_ffmpeg/dag/global_runnable/__init__.py +0 -0
  11. typed_ffmpeg/dag/global_runnable/global_args.py +178 -0
  12. typed_ffmpeg/dag/global_runnable/runnable.py +174 -0
  13. typed_ffmpeg/dag/io/__init__.py +0 -0
  14. typed_ffmpeg/dag/io/_input.py +197 -0
  15. typed_ffmpeg/dag/io/_output.py +320 -0
  16. typed_ffmpeg/dag/io/output_args.py +327 -0
  17. typed_ffmpeg/dag/nodes.py +479 -0
  18. typed_ffmpeg/dag/schema.py +210 -0
  19. typed_ffmpeg/dag/utils.py +41 -0
  20. typed_ffmpeg/dag/validate.py +172 -0
  21. typed_ffmpeg/exceptions.py +42 -0
  22. typed_ffmpeg/filters.py +3572 -0
  23. typed_ffmpeg/probe.py +43 -0
  24. typed_ffmpeg/py.typed +0 -0
  25. typed_ffmpeg/schema.py +29 -0
  26. typed_ffmpeg/streams/__init__.py +5 -0
  27. typed_ffmpeg/streams/audio.py +7358 -0
  28. typed_ffmpeg/streams/av.py +22 -0
  29. typed_ffmpeg/streams/channel_layout.py +39 -0
  30. typed_ffmpeg/streams/video.py +13469 -0
  31. typed_ffmpeg/types.py +119 -0
  32. typed_ffmpeg/utils/__init__.py +0 -0
  33. typed_ffmpeg/utils/escaping.py +49 -0
  34. typed_ffmpeg/utils/lazy_eval/__init__.py +0 -0
  35. typed_ffmpeg/utils/lazy_eval/operator.py +134 -0
  36. typed_ffmpeg/utils/lazy_eval/schema.py +211 -0
  37. typed_ffmpeg/utils/run.py +27 -0
  38. typed_ffmpeg/utils/snapshot.py +26 -0
  39. typed_ffmpeg/utils/typing.py +17 -0
  40. typed_ffmpeg/utils/view.py +64 -0
  41. typed_ffmpeg_compatible-2.4.1.dist-info/LICENSE +21 -0
  42. typed_ffmpeg_compatible-2.4.1.dist-info/METADATA +182 -0
  43. typed_ffmpeg_compatible-2.4.1.dist-info/RECORD +45 -0
  44. typed_ffmpeg_compatible-2.4.1.dist-info/WHEEL +4 -0
  45. typed_ffmpeg_compatible-2.4.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,221 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+ from dataclasses import dataclass
5
+ from functools import cached_property
6
+ from typing import Any, TypeVar
7
+
8
+ from ..utils.typing import override
9
+ from .nodes import FilterNode, InputNode
10
+ from .schema import Node, Stream
11
+
12
+ T = TypeVar("T")
13
+
14
+
15
+ def _remove_duplicates(seq: list[T]) -> list[T]:
16
+ """
17
+ Remove duplicates from a list while preserving order.
18
+
19
+ Args:
20
+ seq: The list to remove duplicates from.
21
+
22
+ Returns:
23
+ The list with duplicates removed.
24
+ """
25
+ seen = set()
26
+ output = []
27
+
28
+ for x in seq:
29
+ if x not in seen:
30
+ output.append(x)
31
+ seen.add(x)
32
+
33
+ return output
34
+
35
+
36
+ def _collect(node: Node) -> tuple[list[Node], list[Stream]]:
37
+ """
38
+ Collect all nodes and streams that are upstreamed to the given node
39
+
40
+ Args:
41
+ node: The node to collect from.
42
+
43
+ Returns:
44
+ A tuple of all nodes and streams that are upstreamed to the given node.
45
+ """
46
+ nodes, streams = [node], [*node.inputs]
47
+
48
+ for stream in node.inputs:
49
+ _nodes, _streams = _collect(stream.node)
50
+ nodes += _nodes
51
+ streams += _streams
52
+
53
+ return nodes, streams
54
+
55
+
56
+ @dataclass(frozen=True, kw_only=True)
57
+ class DAGContext:
58
+ """
59
+ A context for a directed acyclic graph (DAG).
60
+ """
61
+
62
+ node: Node
63
+ """
64
+ The root node (the destination) of the DAG.
65
+ """
66
+
67
+ nodes: tuple[Node, ...]
68
+ """
69
+ All nodes in the graph.
70
+ """
71
+
72
+ streams: tuple[Stream, ...]
73
+ """
74
+ All streams in the graph.
75
+ """
76
+
77
+ @classmethod
78
+ def build(cls, node: Node) -> DAGContext:
79
+ """
80
+ create a DAG context based on the given node
81
+
82
+ Args:
83
+ node: The root node of the DAG.
84
+
85
+ Returns:
86
+ A DAG context based on the given node.
87
+ """
88
+ nodes, streams = _collect(node)
89
+
90
+ return cls(
91
+ node=node,
92
+ nodes=tuple(_remove_duplicates(nodes)),
93
+ streams=tuple(_remove_duplicates(streams)),
94
+ )
95
+
96
+ @cached_property
97
+ def all_nodes(self) -> list[Node]:
98
+ """
99
+ All nodes in the graph sorted by the number of upstream nodes.
100
+ """
101
+ return sorted(self.nodes, key=lambda node: len(node.upstream_nodes))
102
+
103
+ @cached_property
104
+ def all_streams(self) -> list[Stream]:
105
+ """
106
+ All streams in the graph sorted by the number of upstream nodes and the index of the stream.
107
+ """
108
+ return sorted(self.streams, key=lambda stream: (len(stream.node.upstream_nodes), stream.index))
109
+
110
+ @cached_property
111
+ def outgoing_nodes(self) -> dict[Stream, list[tuple[Node, int]]]:
112
+ """
113
+ A dictionary of outgoing nodes for each stream.
114
+ """
115
+ outgoing_nodes: dict[Stream, list[tuple[Node, int]]] = defaultdict(list)
116
+
117
+ for node in self.nodes:
118
+ for idx, stream in enumerate(node.inputs):
119
+ outgoing_nodes[stream].append((node, idx))
120
+
121
+ return outgoing_nodes
122
+
123
+ @cached_property
124
+ def outgoing_streams(self) -> dict[Node, list[Stream]]:
125
+ """
126
+ A dictionary of outgoing streams for each node.
127
+ """
128
+
129
+ outgoing_streams: dict[Node, list[Stream]] = defaultdict(list)
130
+
131
+ for stream in self.streams:
132
+ outgoing_streams[stream.node].append(stream)
133
+
134
+ return outgoing_streams
135
+
136
+ @cached_property
137
+ def node_labels(self) -> dict[Node, str]:
138
+ """
139
+ A dictionary of outgoing streams for each node.
140
+ """
141
+
142
+ input_node_index = 0
143
+ filter_node_index = 0
144
+ node_labels: dict[Node, str] = {}
145
+
146
+ for node in sorted(self.nodes, key=lambda node: node.max_depth):
147
+ if isinstance(node, InputNode):
148
+ node_labels[node] = str(input_node_index)
149
+ input_node_index += 1
150
+ elif isinstance(node, FilterNode):
151
+ node_labels[node] = f"s{filter_node_index}"
152
+ filter_node_index += 1
153
+ else:
154
+ node_labels[node] = "out"
155
+
156
+ return node_labels
157
+
158
+ @override
159
+ def get_outgoing_nodes(self, stream: Stream) -> list[tuple[Node, int]]:
160
+ """
161
+ Get all outgoing nodes of the stream.
162
+
163
+ Args:
164
+ stream: The stream to get the outgoing nodes of.
165
+
166
+ Returns:
167
+ The outgoing nodes of the stream.
168
+ """
169
+ return self.outgoing_nodes[stream]
170
+
171
+ @override
172
+ def get_node_label(self, node: Node) -> str:
173
+ """
174
+ Get the label of the node.
175
+
176
+ Args:
177
+ node: The node to get the label of.
178
+
179
+ Returns:
180
+ The label of the node.
181
+ """
182
+
183
+ assert isinstance(node, (InputNode, FilterNode)), "Only input and filter nodes have labels"
184
+ return self.node_labels[node]
185
+
186
+ @override
187
+ def get_outgoing_streams(self, node: Node) -> list[Stream]:
188
+ """
189
+ Extract all node's outgoing streams from the given set of streams, Because a node only know its incoming streams.
190
+
191
+ Args:
192
+ node: The node to get the outgoing streams of.
193
+
194
+ Returns:
195
+ The outgoing streams of the node.
196
+ """
197
+ return self.outgoing_streams[node]
198
+
199
+ def render(self, obj: Any) -> Any:
200
+ """
201
+ Render the object to a string.
202
+
203
+ Args:
204
+ obj: The object to render.
205
+
206
+ Returns:
207
+ The rendered object.
208
+ """
209
+
210
+ if isinstance(obj, (list, tuple)):
211
+ return [self.render(o) for o in obj]
212
+ elif isinstance(obj, dict):
213
+ return {self.render(k): self.render(v) for k, v in obj.items()}
214
+
215
+ if isinstance(obj, Node):
216
+ return f"Node({obj.repr()}#{self.node_labels[obj]})"
217
+
218
+ if isinstance(obj, Stream):
219
+ return f"Stream({self.render(obj.node)}#{obj.index})"
220
+
221
+ return obj
@@ -0,0 +1,31 @@
1
+ import re
2
+ from typing import Any
3
+
4
+ from ..common.schema import FFMpegFilterDef, StreamType
5
+ from ..schema import Auto
6
+ from ..utils.run import ignore_default
7
+ from .nodes import FilterableStream, FilterNode
8
+
9
+
10
+ def filter_node_factory(filter: FFMpegFilterDef, *inputs: FilterableStream, **kwargs: Any) -> FilterNode:
11
+ for k, v in kwargs.items():
12
+ if isinstance(v, Auto):
13
+ kwargs[k] = eval(v, {"StreamType": StreamType, "re": re, **kwargs, "streams": inputs})
14
+
15
+ if isinstance(filter.typings_input, str):
16
+ input_typings = tuple(eval(filter.typings_input, {"StreamType": StreamType, "re": re, **kwargs}))
17
+ else:
18
+ input_typings = tuple(StreamType.video if k == "video" else StreamType.audio for k in filter.typings_input)
19
+
20
+ if isinstance(filter.typings_output, str):
21
+ output_typings = tuple(eval(filter.typings_output, {"StreamType": StreamType, "re": re, **kwargs}))
22
+ else:
23
+ output_typings = tuple(StreamType.video if k == "video" else StreamType.audio for k in filter.typings_output)
24
+
25
+ return FilterNode(
26
+ name=filter.name,
27
+ input_typings=input_typings,
28
+ output_typings=output_typings,
29
+ inputs=inputs,
30
+ kwargs=ignore_default(kwargs),
31
+ )
File without changes
@@ -0,0 +1,178 @@
1
+ # NOTE: this file is auto-generated, do not modify
2
+ from __future__ import annotations
3
+
4
+ from abc import ABC, abstractmethod
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from ...types import Boolean, Float, Func, Int
8
+
9
+ if TYPE_CHECKING:
10
+ from ..nodes import GlobalNode, GlobalStream, OutputStream
11
+
12
+
13
+ class GlobalArgs(ABC):
14
+ @abstractmethod
15
+ def _global_node(self, *streams: OutputStream, **kwargs: Any) -> GlobalNode:
16
+ ...
17
+
18
+ def global_args(
19
+ self,
20
+ *,
21
+ loglevel: Func = None,
22
+ v: Func = None,
23
+ report: Func = None,
24
+ max_alloc: Func = None,
25
+ cpuflags: Func = None,
26
+ cpucount: Func = None,
27
+ hide_banner: Boolean = None,
28
+ y: Boolean = None,
29
+ n: Boolean = None,
30
+ ignore_unknown: Boolean = None,
31
+ copy_unknown: Boolean = None,
32
+ recast_media: Boolean = None,
33
+ benchmark: Boolean = None,
34
+ benchmark_all: Boolean = None,
35
+ progress: Func = None,
36
+ stdin: Boolean = None,
37
+ timelimit: Func = None,
38
+ dump: Boolean = None,
39
+ hex: Boolean = None,
40
+ frame_drop_threshold: Float = None,
41
+ copyts: Boolean = None,
42
+ start_at_zero: Boolean = None,
43
+ copytb: Int = None,
44
+ dts_delta_threshold: Float = None,
45
+ dts_error_threshold: Float = None,
46
+ xerror: Boolean = None,
47
+ abort_on: Func = None,
48
+ filter_threads: Func = None,
49
+ filter_complex: Func = None,
50
+ filter_complex_threads: Int = None,
51
+ lavfi: Func = None,
52
+ filter_complex_script: Func = None,
53
+ auto_conversion_filters: Boolean = None,
54
+ stats: Boolean = None,
55
+ stats_period: Func = None,
56
+ debug_ts: Boolean = None,
57
+ max_error_rate: Float = None,
58
+ vstats: Func = None,
59
+ vstats_file: Func = None,
60
+ vstats_version: Int = None,
61
+ init_hw_device: Func = None,
62
+ filter_hw_device: Func = None,
63
+ adrift_threshold: Func = None,
64
+ qphist: Func = None,
65
+ vsync: Func = None,
66
+ extra_options: dict[str, Any] = None,
67
+ ) -> GlobalStream:
68
+ """
69
+ Set global options.
70
+
71
+ Args:
72
+ loglevel: set logging level
73
+ v: set logging level
74
+ report: generate a report
75
+ max_alloc: set maximum size of a single allocated block
76
+ cpuflags: force specific cpu flags
77
+ cpucount: force specific cpu count
78
+ hide_banner: do not show program banner
79
+ y: overwrite output files
80
+ n: never overwrite output files
81
+ ignore_unknown: Ignore unknown stream types
82
+ copy_unknown: Copy unknown stream types
83
+ recast_media: allow recasting stream type in order to force a decoder of different media type
84
+ benchmark: add timings for benchmarking
85
+ benchmark_all: add timings for each task
86
+ progress: write program-readable progress information
87
+ stdin: enable or disable interaction on standard input
88
+ timelimit: set max runtime in seconds in CPU user time
89
+ dump: dump each input packet
90
+ hex: when dumping packets, also dump the payload
91
+ frame_drop_threshold: frame drop threshold
92
+ copyts: copy timestamps
93
+ start_at_zero: shift input timestamps to start at 0 when using copyts
94
+ copytb: copy input stream time base when stream copying
95
+ dts_delta_threshold: timestamp discontinuity delta threshold
96
+ dts_error_threshold: timestamp error delta threshold
97
+ xerror: exit on error
98
+ abort_on: abort on the specified condition flags
99
+ filter_threads: number of non-complex filter threads
100
+ filter_complex: create a complex filtergraph
101
+ filter_complex_threads: number of threads for -filter_complex
102
+ lavfi: create a complex filtergraph
103
+ filter_complex_script: deprecated, use -/filter_complex instead
104
+ auto_conversion_filters: enable automatic conversion filters globally
105
+ stats: print progress report during encoding
106
+ stats_period: set the period at which ffmpeg updates stats and -progress output
107
+ debug_ts: print timestamp debugging info
108
+ max_error_rate: ratio of decoding errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.
109
+ vstats: dump video coding statistics to file
110
+ vstats_file: dump video coding statistics to file
111
+ vstats_version: Version of the vstats format to use.
112
+ init_hw_device: initialise hardware device
113
+ filter_hw_device: set hardware device used when filtering
114
+ adrift_threshold: deprecated, does nothing
115
+ qphist: deprecated, does nothing
116
+ vsync: set video sync method globally; deprecated, use -fps_mode
117
+ extra_options: Additional options
118
+
119
+ Returns:
120
+ GlobalStream: GlobalStream instance
121
+ """
122
+
123
+ return self._global_node(
124
+ **(
125
+ {
126
+ k: v
127
+ for k, v in {
128
+ "loglevel": loglevel,
129
+ "v": v,
130
+ "report": report,
131
+ "max_alloc": max_alloc,
132
+ "cpuflags": cpuflags,
133
+ "cpucount": cpucount,
134
+ "hide_banner": hide_banner,
135
+ "y": y,
136
+ "n": n,
137
+ "ignore_unknown": ignore_unknown,
138
+ "copy_unknown": copy_unknown,
139
+ "recast_media": recast_media,
140
+ "benchmark": benchmark,
141
+ "benchmark_all": benchmark_all,
142
+ "progress": progress,
143
+ "stdin": stdin,
144
+ "timelimit": timelimit,
145
+ "dump": dump,
146
+ "hex": hex,
147
+ "frame_drop_threshold": frame_drop_threshold,
148
+ "copyts": copyts,
149
+ "start_at_zero": start_at_zero,
150
+ "copytb": copytb,
151
+ "dts_delta_threshold": dts_delta_threshold,
152
+ "dts_error_threshold": dts_error_threshold,
153
+ "xerror": xerror,
154
+ "abort_on": abort_on,
155
+ "filter_threads": filter_threads,
156
+ "filter_complex": filter_complex,
157
+ "filter_complex_threads": filter_complex_threads,
158
+ "lavfi": lavfi,
159
+ "filter_complex_script": filter_complex_script,
160
+ "auto_conversion_filters": auto_conversion_filters,
161
+ "stats": stats,
162
+ "stats_period": stats_period,
163
+ "debug_ts": debug_ts,
164
+ "max_error_rate": max_error_rate,
165
+ "vstats": vstats,
166
+ "vstats_file": vstats_file,
167
+ "vstats_version": vstats_version,
168
+ "init_hw_device": init_hw_device,
169
+ "filter_hw_device": filter_hw_device,
170
+ "adrift_threshold": adrift_threshold,
171
+ "qphist": qphist,
172
+ "vsync": vsync,
173
+ }.items()
174
+ if v is not None
175
+ }
176
+ | (extra_options or {})
177
+ ),
178
+ ).stream()
@@ -0,0 +1,174 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import subprocess
5
+ from typing import TYPE_CHECKING
6
+
7
+ from ...exceptions import FFMpegExecuteError
8
+ from ...utils.run import command_line
9
+ from .global_args import GlobalArgs
10
+
11
+ if TYPE_CHECKING:
12
+ from ..nodes import GlobalStream, OutputStream
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class GlobalRunable(GlobalArgs):
18
+ def merge_outputs(self, *streams: OutputStream) -> GlobalStream:
19
+ """
20
+ Merge multiple output streams into one.
21
+
22
+ Args:
23
+ *streams: The output streams to merge.
24
+
25
+ Returns:
26
+ The merged output stream.
27
+ """
28
+ return self._global_node(*streams).stream()
29
+
30
+ def overwrite_output(self) -> GlobalStream:
31
+ """
32
+ Overwrite output files without asking (ffmpeg `-y` option)
33
+
34
+ Returns:
35
+ the output stream
36
+ """
37
+ return self._global_node(y=True).stream()
38
+
39
+ def compile(
40
+ self,
41
+ cmd: str | list[str] = "ffmpeg",
42
+ overwrite_output: bool = None,
43
+ auto_fix: bool = True,
44
+ ) -> list[str]:
45
+ """
46
+ Build command-line for invoking ffmpeg.
47
+
48
+ Args:
49
+ cmd: the command to invoke ffmpeg
50
+ overwrite_output: whether to overwrite output files without asking
51
+ auto_fix: whether to automatically fix the stream
52
+
53
+ Returns:
54
+ the command-line
55
+ """
56
+ from ..compile import compile
57
+
58
+ if isinstance(cmd, str):
59
+ cmd = [cmd]
60
+
61
+ if overwrite_output is True:
62
+ return self.global_args(y=True).compile(cmd, auto_fix=auto_fix)
63
+ elif overwrite_output is False:
64
+ return self.global_args(n=True).compile(cmd, auto_fix=auto_fix)
65
+
66
+ return cmd + compile(self._global_node().stream(), auto_fix=auto_fix)
67
+
68
+ def compile_line(
69
+ self,
70
+ cmd: str | list[str] = "ffmpeg",
71
+ overwrite_output: bool = None,
72
+ auto_fix: bool = True,
73
+ ) -> str:
74
+ """
75
+ Build command-line for invoking ffmpeg.
76
+
77
+ Args:
78
+ cmd: the command to invoke ffmpeg
79
+ overwrite_output: whether to overwrite output files without asking
80
+ auto_fix: whether to automatically fix the stream
81
+
82
+ Returns:
83
+ the command-line
84
+ """
85
+ return command_line(self.compile(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix))
86
+
87
+ def run_async(
88
+ self,
89
+ cmd: str | list[str] = "ffmpeg",
90
+ pipe_stdin: bool = False,
91
+ pipe_stdout: bool = False,
92
+ pipe_stderr: bool = False,
93
+ quiet: bool = False,
94
+ overwrite_output: bool = None,
95
+ auto_fix: bool = True,
96
+ ) -> subprocess.Popen[bytes]:
97
+ """
98
+ Run ffmpeg asynchronously.
99
+
100
+ Args:
101
+ cmd: the command to invoke ffmpeg
102
+ pipe_stdin: whether to pipe stdin
103
+ pipe_stdout: whether to pipe stdout
104
+ pipe_stderr: whether to pipe stderr
105
+ quiet: whether to pipe stderr to stdout
106
+ overwrite_output: whether to overwrite output files without asking
107
+ auto_fix: whether to automatically fix the stream
108
+
109
+ Returns:
110
+ the process
111
+ """
112
+
113
+ args = self.compile(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix)
114
+ stdin_stream = subprocess.PIPE if pipe_stdin else None
115
+ stdout_stream = subprocess.PIPE if pipe_stdout or quiet else None
116
+ stderr_stream = subprocess.PIPE if pipe_stderr or quiet else None
117
+
118
+ logger.info(f"Running command: {self.compile_line(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix)}")
119
+
120
+ return subprocess.Popen(
121
+ args,
122
+ stdin=stdin_stream,
123
+ stdout=stdout_stream,
124
+ stderr=stderr_stream,
125
+ )
126
+
127
+ def run(
128
+ self,
129
+ cmd: str | list[str] = "ffmpeg",
130
+ capture_stdout: bool = False,
131
+ capture_stderr: bool = False,
132
+ input: bytes | None = None,
133
+ quiet: bool = False,
134
+ overwrite_output: bool = None,
135
+ auto_fix: bool = True,
136
+ ) -> tuple[bytes, bytes]:
137
+ """
138
+ Run ffmpeg synchronously.
139
+
140
+ Args:
141
+ cmd: the command to invoke ffmpeg
142
+ capture_stdout: whether to capture stdout
143
+ capture_stderr: whether to capture stderr
144
+ input: the input
145
+ quiet: whether to pipe stderr to stdout
146
+ overwrite_output: whether to overwrite output files without asking
147
+ auto_fix: whether to automatically fix the stream
148
+
149
+ Returns:
150
+ stdout: he stdout
151
+ stderr: the stderr
152
+ """
153
+
154
+ process = self.run_async(
155
+ cmd,
156
+ pipe_stdin=input is not None,
157
+ pipe_stdout=capture_stdout,
158
+ pipe_stderr=capture_stderr,
159
+ quiet=quiet,
160
+ overwrite_output=overwrite_output,
161
+ auto_fix=auto_fix,
162
+ )
163
+ stdout, stderr = process.communicate(input)
164
+ retcode = process.poll()
165
+
166
+ if retcode:
167
+ raise FFMpegExecuteError(
168
+ retcode=retcode,
169
+ cmd=self.compile_line(cmd, overwrite_output=overwrite_output, auto_fix=auto_fix),
170
+ stdout=stdout,
171
+ stderr=stderr,
172
+ )
173
+
174
+ return stdout, stderr
File without changes