"""Export the ast tree into an excecutable python file."""
import ast
import pathlib
import stat
import black
[docs]
def ast_to_file(module: ast.Module, filename: pathlib.Path | str | bytes):
'''Write the module into an excecutable python file.
Parameters
----------
module : ast.Module
The pre compiled graph, could be the output of the function
``cutcutcodec.core.compilation.graph_to_ast.graph_to_ast``.
filename : pathlib.Path
The name of the targeted file.
Examples
--------
>>> import os, tempfile
>>> from cutcutcodec.core.compilation.ast_to_file import ast_to_file
>>> from cutcutcodec.core.compilation.graph_to_ast import graph_to_ast
>>> from cutcutcodec.core.compilation.tree_to_graph import tree_to_graph
>>> from cutcutcodec.core.filter.audio.subclip import FilterAudioSubclip
>>> from cutcutcodec.core.filter.video.subclip import FilterVideoSubclip
>>> from cutcutcodec.core.generation.audio.noise import GeneratorAudioNoise
>>> from cutcutcodec.core.generation.video.noise import GeneratorVideoNoise
>>> from cutcutcodec.core.io.write_ffmpeg import ContainerOutputFFMPEG
>>> streams_settings = [
... {"encodec": "libopus", "rate": 8000},
... {"encodec": "libx264", "rate": 12, "shape": (2, 2)},
... ]
>>> container_settings = {"format": "matroska"}
>>> (stream_a,) = FilterAudioSubclip(GeneratorAudioNoise(0).out_streams, 0, 1).out_streams
>>> (stream_v,) = FilterVideoSubclip(GeneratorVideoNoise(0).out_streams, 0, 1).out_streams
>>> streams = (stream_a, stream_v)
>>> tree = ContainerOutputFFMPEG(streams, os.devnull, streams_settings, container_settings)
>>> filename = pathlib.Path(tempfile.gettempdir()) / "cutcutcodec.py"
>>> module = graph_to_ast(tree_to_graph(tree))
>>> ast_to_file(module, filename)
>>> with open(filename, "r", encoding="utf-8") as raw:
... print(raw.read()) # doctest: +ELLIPSIS
...
#!/usr/bin/env python3
<BLANKLINE>
"""Autogenerated project exportation script.
<BLANKLINE>
Creation: ...
Graph: MultiDiGraph with 5 nodes and 4 edges
"""
from cutcutcodec.core.classes.node import Node
from cutcutcodec.core.filter.audio.subclip import FilterAudioSubclip
from cutcutcodec.core.filter.video.subclip import FilterVideoSubclip
from cutcutcodec.core.generation.audio.noise import GeneratorAudioNoise
from cutcutcodec.core.generation.video.noise import GeneratorVideoNoise
from cutcutcodec.core.io.write_ffmpeg import ContainerOutputFFMPEG
<BLANKLINE>
<BLANKLINE>
def get_container_output_ffmpeg_1(
filter_audio_subclip_1: Node, filter_video_subclip_1: Node
) -> ContainerOutputFFMPEG:
"""Create the node 'container_output_ffmpeg_1'."""
container_output_ffmpeg_1 = ContainerOutputFFMPEG.__new__(ContainerOutputFFMPEG)
container_output_ffmpeg_1.setstate(
[filter_audio_subclip_1.out_streams[0], filter_video_subclip_1.out_streams[0]],
state={
"filename": "/dev/null",
"streams_settings": [
{"encodec": "libopus", "rate": "8000", "options": {}, "bitrate": None},
{
"encodec": "libx264",
"rate": "12",
"shape": (2, 2),
"options": {},
"bitrate": None,
"pix_fmt": None,
"range": "tv",
},
],
"container_settings": {
"format": "matroska",
"options": {},
"container_options": {},
},
},
)
return container_output_ffmpeg_1
<BLANKLINE>
<BLANKLINE>
def get_filter_audio_subclip_1(generator_audio_noise_1: Node) -> FilterAudioSubclip:
"""Create the node 'filter_audio_subclip_1'."""
filter_audio_subclip_1 = FilterAudioSubclip.__new__(FilterAudioSubclip)
filter_audio_subclip_1.setstate(
[generator_audio_noise_1.out_streams[0]],
state={"delay": "0", "duration_max": "1"},
)
return filter_audio_subclip_1
<BLANKLINE>
<BLANKLINE>
def get_filter_video_subclip_1(generator_video_noise_1: Node) -> FilterVideoSubclip:
"""Create the node 'filter_video_subclip_1'."""
filter_video_subclip_1 = FilterVideoSubclip.__new__(FilterVideoSubclip)
filter_video_subclip_1.setstate(
[generator_video_noise_1.out_streams[0]],
state={"delay": "0", "duration_max": "1"},
)
return filter_video_subclip_1
<BLANKLINE>
<BLANKLINE>
def get_generator_audio_noise_1() -> GeneratorAudioNoise:
"""Create the node 'generator_audio_noise_1'."""
generator_audio_noise_1 = GeneratorAudioNoise.__new__(GeneratorAudioNoise)
generator_audio_noise_1.setstate([], state={"seed": 0.0, "layout": "stereo"})
return generator_audio_noise_1
<BLANKLINE>
<BLANKLINE>
def get_generator_video_noise_1() -> GeneratorVideoNoise:
"""Create the node 'generator_video_noise_1'."""
generator_video_noise_1 = GeneratorVideoNoise.__new__(GeneratorVideoNoise)
generator_video_noise_1.setstate([], state={"seed": 0.0})
return generator_video_noise_1
<BLANKLINE>
<BLANKLINE>
def get_complete_tree() -> ContainerOutputFFMPEG:
"""Retrive the complete assembly graph."""
generator_audio_noise_1 = get_generator_audio_noise_1()
filter_audio_subclip_1 = get_filter_audio_subclip_1(generator_audio_noise_1)
generator_video_noise_1 = get_generator_video_noise_1()
filter_video_subclip_1 = get_filter_video_subclip_1(generator_video_noise_1)
container_output_ffmpeg_1 = get_container_output_ffmpeg_1(
filter_audio_subclip_1, filter_video_subclip_1
)
return container_output_ffmpeg_1
<BLANKLINE>
<BLANKLINE>
if __name__ == "__main__":
get_complete_tree().write()
<BLANKLINE>
>>> filename.unlink()
>>>
'''
assert isinstance(module, ast.Module), module.__class__.__name__
filename = pathlib.Path(filename)
assert filename.suffix == ".py", filename
code = ast.unparse(module)
code = "#!/usr/bin/env python3\n\n" + code
code = black.format_str(code, mode=black.Mode())
# write file and give execution permission
with open(filename, "w", encoding="utf-8") as code_file:
code_file.write(code)
filename.chmod(filename.stat().st_mode | stat.S_IEXEC)