Skip to content

Settings

sereto.models.settings

ConvertRecipe

Bases: RenderRecipe

Recipe for converting between file formats using RenderTools.

Attributes:

Name Type Description
name

name of the recipe

input_format FileFormat

input file format

tools FileFormat

list of RenderTool names to run

Source code in sereto/models/settings.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
class ConvertRecipe(RenderRecipe):
    """Recipe for converting between file formats using `RenderTool`s.

    Attributes:
        name: name of the recipe
        input_format: input file format
        tools: list of `RenderTool` names to run
    """

    input_format: FileFormat
    output_format: FileFormat

    @field_validator("input_format", "output_format", mode="before")
    @classmethod
    def load_file_format(cls, v: Any) -> FileFormat:
        match v:
            case FileFormat():
                return v
            case str():
                return FileFormat(v)
            case _:
                raise ValueError("invalid type for FileFormat")

Plugins

Bases: SeretoBaseModel

Plugins settings.

Attributes:

Name Type Description
enabled bool

whether plugins are enabled

directory str

path to the directory containing plugins (%TEMPLATES% will be replaced with the templates path`)

Source code in sereto/models/settings.py
274
275
276
277
278
279
280
281
282
283
class Plugins(SeretoBaseModel):
    """Plugins settings.

    Attributes:
        enabled: whether plugins are enabled
        directory: path to the directory containing plugins (`%TEMPLATES%` will be replaced with the templates path`)
    """

    enabled: bool = False
    directory: str = "%TEMPLATES%/plugins"

RenderRecipe

Bases: SeretoBaseModel

Recipe for rendering and converting files using RenderTools.

Attributes:

Name Type Description
name str

name of the recipe

tools Annotated[list[str], MinLen(1)]

list of RenderTool names to run

Source code in sereto/models/settings.py
87
88
89
90
91
92
93
94
95
96
class RenderRecipe(SeretoBaseModel):
    """Recipe for rendering and converting files using `RenderTool`s.

    Attributes:
        name: name of the recipe
        tools: list of `RenderTool` names to run
    """

    name: str
    tools: Annotated[list[str], MinLen(1)]

RenderTool

Bases: SeretoBaseModel

Commands used in recipes.

Attributes:

Name Type Description
name str

name of the tool

command str

command to run

args list[str]

list of arguments to pass to the command

Source code in sereto/models/settings.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class RenderTool(SeretoBaseModel):
    """Commands used in recipes.

    Attributes:
        name: name of the tool
        command: command to run
        args: list of arguments to pass to the command
    """

    name: str
    command: str
    args: list[str]

    @validate_call
    def run(
        self, cwd: DirectoryPath | None = None, input: bytes | None = None, replacements: dict[str, str] | None = None
    ) -> bytes:
        # Prepare the command
        command = [self.command] + self.args
        if replacements is not None:
            command = replace_strings(text=command, replacements=replacements)
        Console().log(
            Markdown(
                dedent(f"""\
                    Running command:
                    ```bash
                    {escape(' '.join(command))}
                    ```
                """)
            )
        )
        Console().line()

        # Run the command and measure the execution time
        start_time = time.time()
        result = subprocess.run(command, cwd=cwd, input=input, capture_output=True)
        end_time = time.time()

        # Check if the command failed
        if result.returncode != 0:
            Console().log(
                Markdown(f"""\
Command failed ({result.returncode}):
```text
{escape(result.stderr.decode("utf-8"))}
```
""")
            )
            Console().line()
            raise SeretoCalledProcessError("command execution failed")

        # Report success
        Console().log(f"Command finished in {end_time - start_time:.2f} s")

        # Return the command output
        return result.stdout

Settings

Bases: SeretoBaseSettings

Global settings:

Attributes:

Name Type Description
projects_path DirectoryPath

path to the directory containing all projects

templates_path DirectoryPath

path to the directory containing templates

render Render

rendering settings

categories TypeCategories

supported categories - list of strings (2-20 lower-alpha characters; also dash and underscore is possible in all positions except the first and last one)

Raises:

Type Description
SeretoPathError

If the file is not found or permission is denied.

SeretoValueError

If the JSON file is invalid.

Source code in sereto/models/settings.py
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
class Settings(SeretoBaseSettings):
    """Global settings:

    Attributes:
        projects_path: path to the directory containing all projects
        templates_path: path to the directory containing templates
        render: rendering settings
        categories: supported categories - list of strings (2-20 lower-alpha characters; also dash and underscore is
            possible in all positions except the first and last one)

    Raises:
        SeretoPathError: If the file is not found or permission is denied.
        SeretoValueError: If the JSON file is invalid.
    """

    projects_path: DirectoryPath
    templates_path: DirectoryPath
    render: Render = Field(default=DEFAULT_RENDER_CONFIG)
    categories: TypeCategories = Field(default=DEFAULT_CATEGORIES)
    plugins: Plugins = Field(default_factory=Plugins)

    @staticmethod
    def get_path() -> Path:
        return Path(get_app_dir(app_name="sereto")) / "settings.json"

    @classmethod
    def load_from(cls, file: FilePath) -> Self:
        try:
            return cls.model_validate_json(file.read_bytes())
        except FileNotFoundError:
            raise SeretoPathError(f"file not found at '{file}'") from None
        except PermissionError:
            raise SeretoPathError(f"permission denied for '{file}'") from None
        except ValidationError as e:
            raise SeretoValueError(f"invalid settings\n\n{e}") from e