Skip to content

Config

sereto.cli.config

add_dates_config(config, version=None, non_interactive=False, date_type=None, start_date=None, end_date=None)

Add date to the configuration.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
version ProjectVersion | None

The version of the project. If not provided, the last version is used.

None
non_interactive bool

If True, run non-interactively; fail if required inputs are missing.

False
date_type DateType | None

The type of the date event.

None
start_date str | None

The start date str in DD-Mmm-YYYY format.

None
end_date str | None

The end date str in DD-Mmm-YYYY format.

None
Source code in sereto/cli/config.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
@validate_call
def add_dates_config(
    config: Config,
    version: ProjectVersion | None = None,
    non_interactive: bool = False,
    date_type: DateType | None = None,
    start_date: str | None = None,
    end_date: str | None = None,
) -> None:
    """Add date to the configuration.

    Args:
        config: Configuration of the project.
        version: The version of the project. If not provided, the last version is used.
        non_interactive: If True, run non-interactively; fail if required inputs are missing.
        date_type: The type of the date event.
        start_date: The start date str in DD-Mmm-YYYY format.
        end_date: The end date str in DD-Mmm-YYYY format.
    """
    if version is None:
        version = config.last_version

    if non_interactive:
        new_date = _build_date_from_options(date_type=date_type, start_date=start_date, end_date=end_date)
    else:
        new_date = _prompt_for_date()

    # Add the date to the configuration
    config.at_version(version).add_date(new_date)

    # Write the configuration
    config.save()

add_people_config(config, version=None, non_interactive=False, person_type=None, person_name=None, business_unit=None, email=None, role=None)

Add person to the configuration.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
version ProjectVersion | None

The version of the project. If not provided, the last version is used.

None
non_interactive bool

If True, run non-interactively; fail if required inputs are missing.

False
person_type PersonType | None

The type of the person.

None
person_name str | None

The name of the person.

None
business_unit str | None

The business unit of the person.

None
email str | None

The email address of the person.

None
role str | None

The role of the person.

None
Source code in sereto/cli/config.py
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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
@validate_call
def add_people_config(
    config: Config,
    version: ProjectVersion | None = None,
    non_interactive: bool = False,
    person_type: PersonType | None = None,
    person_name: str | None = None,
    business_unit: str | None = None,
    email: str | None = None,
    role: str | None = None,
) -> None:
    """Add person to the configuration.

    Args:
        config: Configuration of the project.
        version: The version of the project. If not provided, the last version is used.
        non_interactive: If True, run non-interactively; fail if required inputs are missing.
        person_type: The type of the person.
        person_name: The name of the person.
        business_unit: The business unit of the person.
        email: The email address of the person.
        role: The role of the person.
    """
    if version is None:
        version = config.last_version

    if non_interactive:
        new_person = _build_person_from_options(
            person_type=person_type,
            person_name=person_name,
            business_unit=business_unit,
            email=email,
            role=role,
        )
    else:
        new_person = _prompt_for_person()

    # Add the person to the configuration
    config.at_version(version).add_person(new_person)

    # Write the configuration
    config.save()

add_target(project_path, templates, config, categories, version=None, non_interactive=False, category=None, target_name=None, extra_json=None)

Add target to the configuration.

Parameters:

Name Type Description Default
project_path DirectoryPath

Path to the project directory.

required
templates DirectoryPath

Path to the templates directory.

required
config Config

Configuration of the project.

required
categories Iterable[str]

List of all categories.

required
version ProjectVersion | None

The version of the project. If not provided, the last version is used.

None
non_interactive bool

If True, run non-interactively; fail if required inputs are missing.

False
category str | None

Category of the target.

None
target_name str | None

Name of the target.

None
extra_json str | None

Extra target fields as a JSON string.

None
Source code in sereto/cli/config.py
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
@validate_call
def add_target(
    project_path: DirectoryPath,
    templates: DirectoryPath,
    config: Config,
    categories: Iterable[str],
    version: ProjectVersion | None = None,
    non_interactive: bool = False,
    category: str | None = None,
    target_name: str | None = None,
    extra_json: str | None = None,
) -> None:
    """Add target to the configuration.

    Args:
        project_path: Path to the project directory.
        templates: Path to the templates directory.
        config: Configuration of the project.
        categories: List of all categories.
        version: The version of the project. If not provided, the last version is used.
        non_interactive: If True, run non-interactively; fail if required inputs are missing.
        category: Category of the target.
        target_name: Name of the target.
        extra_json: Extra target fields as a JSON string.
    """
    if version is None:
        version = config.last_version

    if non_interactive:
        new_target_model = _build_target_from_options(
            category=category, target_name=target_name, categories=categories, extra_json=extra_json
        )
    else:
        new_target_model = prompt_user_for_target(categories=categories)

    # Create the target instance, including on the filesystem
    new_target = Target.new(data=new_target_model, project_path=project_path, templates=templates, version=version)

    # Add the target to the configuration
    config.at_version(version).add_target(new_target)

    # Write the configuration
    config.save()

delete_target(config, index, version=None, interactive=False)

Delete target from the configuration by its index.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
index int

Index to item which should be deleted. First item is 1.

required
version ProjectVersion | None

The version of the project. If not provided, the last version is used.

None
interactive bool

Whether to ask for confirmations.

False
Source code in sereto/cli/config.py
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
@validate_call
def delete_target(
    config: Config, index: int, version: ProjectVersion | None = None, interactive: bool = False
) -> None:
    """Delete target from the configuration by its index.

    Args:
        config: Configuration of the project.
        index: Index to item which should be deleted. First item is 1.
        version: The version of the project. If not provided, the last version is used.
        interactive: Whether to ask for confirmations.
    """
    if version is None:
        version = config.last_version

    # Extract the filesystem path before deleting the values
    version_config = config.at_version(version)
    target_path = version_config.targets[index - 1].path

    # Delete the date from the configuration
    version_config.delete_target(index=index)

    # Write the configuration
    config.save()

    # Delete target from the filesystem
    if (
        target_path.is_dir()
        and interactive
        and yes_no_dialog(title="Confirm", text=f"Delete '{target_path}' from the filesystem?").run()
    ):
        shutil.rmtree(target_path)

edit_config(project, non_interactive=False, extra_json=None)

Edit the configuration file in default CLI editor.

When non_interactive is True, the config is updated from extra_json without opening an editor. Otherwise, the config file is opened in the default editor.

Parameters:

Name Type Description Default
project Project

Project's representation.

required
non_interactive bool

If True, run non-interactively.

False
extra_json str | None

A JSON string with config fields to update.

None
Source code in sereto/cli/config.py
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
85
86
87
88
89
90
91
92
93
94
95
96
@validate_call
def edit_config(
    project: Project,
    non_interactive: bool = False,
    extra_json: str | None = None,
) -> None:
    """Edit the configuration file in default CLI editor.

    When `non_interactive` is True, the config is updated from `extra_json` without opening an editor.
    Otherwise, the config file is opened in the default editor.

    Args:
        project: Project's representation.
        non_interactive: If True, run non-interactively.
        extra_json: A JSON string with config fields to update.
    """

    sereto_ver = importlib.metadata.version("sereto")
    config = project.config_path

    # If the config file does not exist, create it with default values
    if not project.config_path.is_file():
        Config(
            sereto_version=SeretoVersion.from_str(sereto_ver),
            version_configs={
                ProjectVersion.from_str("v1.0"): VersionConfig(
                    version=ProjectVersion.from_str("v1.0"),
                    id="",
                    name="",
                    version_description="Initial",
                    risk_due_dates=project.settings.risk_due_dates,
                ),
            },
            path=project.config_path,
            risk_due_dates=project.settings.risk_due_dates,
        ).save()

    if non_interactive:
        if extra_json is None:
            raise SeretoValueError("'--extra' is required in non-interactive mode.")
        try:
            extra = json.loads(extra_json)
        except json.JSONDecodeError as e:
            raise SeretoValueError(f"Invalid JSON in '--extra': {e}") from e

        if not isinstance(extra, dict):
            raise SeretoValueError("Value of '--extra' must be a JSON object")

        version_config = project.config.last_config
        skip_fields = {"version_configs", "targets", "dates", "people"}

        for key, value in extra.items():
            if key in skip_fields:
                continue
            elif key in VersionConfigModel.model_fields:
                setattr(version_config, key, value)
            elif key in ConfigModel.model_fields:
                setattr(project.config, key, value)
            else:
                raise SeretoValueError(f"Unknown config field: '{key}'")

        project.config.save()
    else:
        # Interactive: open the config file in the default editor
        click.edit(filename=str(config))

show_config(config, output_format, all=False, version=None)

Display the configuration for a project.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
output_format OutputFormat

Format of the output.

required
all bool

Whether to show values from all versions or just the last one.

False
version ProjectVersion | None

Show config at specific version, e.g. 'v1.0'.

None
Source code in sereto/cli/config.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
@validate_call
def show_config(
    config: Config, output_format: OutputFormat, all: bool = False, version: ProjectVersion | None = None
) -> None:
    """Display the configuration for a project.

    Args:
        config: Configuration of the project.
        output_format: Format of the output.
        all: Whether to show values from all versions or just the last one.
        version: Show config at specific version, e.g. 'v1.0'.
    """
    if version is None:
        version = config.last_version

    version_config = config.at_version(version)

    match output_format:
        case OutputFormat.table:
            Console().print(f"\n\n[blue]{version_config.id} - {version_config.name}\n", justify="center")
            show_targets_config(config=config, output_format=OutputFormat.table, all=all, version=version)
            show_dates_config(config=config, output_format=OutputFormat.table, all=all, version=version)
            show_people_config(config=config, output_format=OutputFormat.table, all=all, version=version)
        case OutputFormat.json:
            if all:
                Console().print_json(config.to_model().model_dump_json())
            else:
                Console().print_json(version_config.to_model().model_dump_json())

show_dates_config(config, output_format, all, version)

Display the configured dates.

By default, if neither of version and all arguments are used, dates from the latest version are displayed.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
output_format OutputFormat

Select format of the output.

required
all bool

Show dates from all versions.

required
version ProjectVersion | None

Show dates from specific version.

required
Source code in sereto/cli/config.py
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
@validate_call
def show_dates_config(
    config: Config,
    output_format: OutputFormat,
    all: bool,
    version: ProjectVersion | None,
) -> None:
    """Display the configured dates.

    By default, if neither of `version` and `all` arguments are used, dates from the latest version are displayed.

    Args:
        config: Configuration of the project.
        output_format: Select format of the output.
        all: Show dates from all versions.
        version: Show dates from specific version.
    """
    if version is None:
        version = config.last_version

    match output_format:
        case OutputFormat.table:
            for ver in config.versions if all else [version]:
                Console().line()
                table = _get_dates_table(version_config=config.at_version(version=ver).to_model(), version=ver)
                Console().print(table, justify="center")
        case OutputFormat.json:
            DateList: TypeAdapter[list[Date]] = TypeAdapter(list[Date])
            DateAll: TypeAdapter[dict[str, list[Date]]] = TypeAdapter(dict[str, list[Date]])

            if all:
                all_dates = DateAll.validate_python(
                    {str(ver): config.at_version(version=ver).dates for ver in config.versions}
                )
                Console().print_json(DateAll.dump_json(all_dates).decode("utf-8"))
            else:
                dates = DateList.validate_python(config.at_version(version).dates)
                Console().print_json(DateList.dump_json(dates).decode("utf-8"))

show_people_config(config, output_format, all, version)

Display the configured people.

By default, if neither of version and all arguments are used, people from the latest version are displayed.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
output_format OutputFormat

Select format of the output.

required
all bool

Show people from all versions.

required
version ProjectVersion | None

Show people from specific version.

required
Source code in sereto/cli/config.py
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
@validate_call
def show_people_config(config: Config, output_format: OutputFormat, all: bool, version: ProjectVersion | None) -> None:
    """Display the configured people.

    By default, if neither of `version` and `all` arguments are used, people from the latest version are displayed.

    Args:
        config: Configuration of the project.
        output_format: Select format of the output.
        all: Show people from all versions.
        version: Show people from specific version.
    """
    if version is None:
        version = config.last_version

    match output_format:
        case OutputFormat.table:
            for ver in config.versions if all else [version]:
                Console().line()
                table = _get_person_table(version_config=config.at_version(version=ver).to_model(), version=ver)
                Console().print(table, justify="center")
        case OutputFormat.json:
            PersonList: TypeAdapter[list[Person]] = TypeAdapter(list[Person])
            PersonAll: TypeAdapter[dict[str, list[Person]]] = TypeAdapter(dict[str, list[Person]])

            if all:
                all_people = PersonAll.validate_python(
                    {str(ver): config.at_version(version=ver).people for ver in config.versions}
                )
                Console().print_json(PersonAll.dump_json(all_people).decode("utf-8"))
            else:
                people = PersonList.validate_python(config.at_version(version).people)
                Console().print_json(PersonList.dump_json(people).decode("utf-8"))

show_targets_config(config, output_format, all, version)

Display the configured targets.

By default, if neither of version and all arguments are used, targets from the latest version are displayed.

Parameters:

Name Type Description Default
config Config

Configuration of the project.

required
output_format OutputFormat

Select format of the output.

required
all bool

Show targets from all versions.

required
version ProjectVersion | None

Show targets from the specified project's version.

required
Source code in sereto/cli/config.py
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
@validate_call
def show_targets_config(
    config: Config, output_format: OutputFormat, all: bool, version: ProjectVersion | None
) -> None:
    """Display the configured targets.

    By default, if neither of `version` and `all` arguments are used, targets from the latest version are displayed.

    Args:
        config: Configuration of the project.
        output_format: Select format of the output.
        all: Show targets from all versions.
        version: Show targets from the specified project's version.
    """
    if version is None:
        version = config.last_version

    match output_format:
        case OutputFormat.table:
            for ver in config.versions if all else [version]:
                Console().line()
                table = _get_target_table(version_config=config.at_version(version=ver).to_model(), version=ver)
                Console().print(table, justify="center")
        case OutputFormat.json:
            TargetList: TypeAdapter[list[AnyTargetModel]] = TypeAdapter(list[AnyTargetModel])
            TargetAll: TypeAdapter[dict[str, list[AnyTargetModel]]] = TypeAdapter(dict[str, list[AnyTargetModel]])

            if all:
                all_targets = TargetAll.validate_python(
                    {
                        str(ver): [t.to_model() for t in config.at_version(version=ver).targets]
                        for ver in config.versions
                    }
                )
                Console().print_json(TargetAll.dump_json(all_targets).decode("utf-8"))
            else:
                target_models = [t.to_model() for t in config.at_version(version).targets]
                targets = TargetList.validate_python(target_models)
                Console().print_json(TargetList.dump_json(targets).decode("utf-8"))