API¶
Code Docstrings¶
Actions¶
Prune YAML¶
Provides functions for ‘pruning’ yaml of extra and empty fields.
- brassy.actions.prune_yaml.direct_pruning_of_files(input_files_or_folders: list[str], console: Any, working_dir: str, error_console: Any = None) None[source]¶
Prune empty values from YAML files specified by input paths.
- Parameters:
input_files_or_folders (list[str]) – A list of file paths or directories containing YAML files to prune.
console (Any) – An object used for printing status messages to the console.
working_dir (str) – The working directory path.
error_console (Any) – An object used for printing errors. Defaults to
consolewhen None.
Notes
This function collects YAML files from the specified input paths and prunes each file using prune_yaml_file.
Examples
>>> direct_pruning_of_files(['configs/'], console, '/home/user') Pruned configs/config1.yaml Pruned configs/config2.yaml
- brassy.actions.prune_yaml.prune_empty(data: Any, prune_lists: bool = True, key: str = '') Any[source]¶
Recursively remove empty values from a nested dictionary or list.
- Parameters:
data (Any) – The data structure to prune.
prune_lists (bool) – Indicates whether to prune empty lists. Currently unused.
key (str) – The key associated with the current data item, used for special cases.
- Returns:
The pruned data structure, or None if it is empty.
- Return type:
Any
Notes
The function considers the following values as empty: None, empty strings, empty dictionaries, and empty lists. If a value is 0 and the key is “number”, it is also considered empty to address the related issues field which was previously set to 0 instead of null.
Examples
>>> data = {'a': None, 'b': '', 'c': {'d': [], 'e': 'value'}} >>> prune_empty(data) {'c': {'e': 'value'}}
- brassy.actions.prune_yaml.prune_yaml_file(yaml_file_path: str, console: Any) None[source]¶
Prune empty values from a YAML file and overwrite it with the pruned content.
- Parameters:
yaml_file_path (str) – The file path to the YAML file to be pruned.
console (Any) – An object used for printing messages to the console.
Notes
This function reads the YAML file, prunes empty values using prune_empty, and writes the pruned content back to the same file.
Examples
>>> prune_yaml_file('config.yaml', console) Pruned config.yaml
Build Release Notes¶
Build release note output.
- brassy.actions.build_release_notes.build_release_notes(input_files_or_folders: list[str], console: Any, rich_open: Callable[..., Any], version: str | None = None, release_date: str | None = None, header_file: str | None = None, footer_file: str | None = None, working_dir: str = '.', error_console: Any = None) str[source]¶
Build release notes by reading YAML files and templates.
- Parameters:
input_files_or_folders (list[str]) – CLI-supplied file or directory paths.
console (Any) – Console for status and warning output.
rich_open (Callable[..., Any]) – Context manager factory for reading files.
version (str | None) – Release version string.
release_date (str | None) – Release date override in ISO format.
header_file (str | None) – Path to an optional header file.
footer_file (str | None) – Path to an optional footer file.
working_dir (str) – Base directory for relative paths.
error_console (Any) – Console for error output. Defaults to
consolewhen None.
- Returns:
Rendered release notes in RST.
- Return type:
str
- brassy.actions.build_release_notes.find_duplicate_titles(data: dict[str, list[dict[str, Any]]]) bool[source]¶
Detect duplicate titles across changelog entries.
- Parameters:
data (dict[str, list[dict[str, Any]]]) – Mapping of categories to lists of changelog entries.
- Returns:
True if any title occurs more than once.
- Return type:
bool
- brassy.actions.build_release_notes.format_files_changed_entry(detailed: bool, entry: dict[str, Any]) str[source]¶
Format an RST block describing changed files for an entry.
- Parameters:
detailed (bool) – Unused flag kept for compatibility.
entry (dict[str, Any]) – Changelog entry containing file changes.
- Returns:
RST formatted file change listing.
- Return type:
str
- brassy.actions.build_release_notes.format_release_notes(data: dict[str, list[dict[str, Any]]], version: str | None, release_date: str | None = None, header: str | None = None, footer: str | None = None) str[source]¶
Generate release notes content from parsed changelog data.
- Parameters:
data (dict[str, list[dict[str, Any]]]) – Parsed changelog entries grouped by category.
version (str | None) – Release version string.
release_date (str | None) – Release date override in ISO format. Defaults to today’s date.
header (str | None) – Optional header content.
footer (str | None) – Optional footer content.
- Returns:
Release notes rendered in RST.
- Return type:
str
- brassy.actions.build_release_notes.generate_file_change_section_list_of_strings(entry: dict[str, Any], line: str, category: str, title: str, description: str) list[str][source]¶
Create file-specific section lines for a changelog entry.
- Parameters:
entry (dict[str, Any]) – Changelog entry with file change data.
line (str) – Template string for the section line.
category (str) – Entry category name.
title (str) – Resolved entry title.
description (str) – Resolved entry description.
- Returns:
Section lines formatted per file change.
- Return type:
list[str]
- brassy.actions.build_release_notes.generate_section_string(section_lines: list[str], changelog_entries: dict[str, list[dict[str, Any]]], release_date: str, version: str, footer: str | None, header: str | None) str[source]¶
Render a changelog section from templates and entries.
- Parameters:
section_lines (list[str]) – Template lines for the section.
changelog_entries (dict[str, list[dict[str, Any]]]) – Mapping of categories to changelog entries.
release_date (str) – Release date string.
version (str) – Release version string.
footer (str | None) – Footer content appended to templates.
header (str | None) – Header content prepended to templates.
- Returns:
Rendered section content.
- Return type:
str
Read optional header and footer content.
- Parameters:
rich_open (Callable[..., Any]) – Context manager factory for reading files.
header_file (str | None) – Path to header file.
footer_file (str | None) – Path to footer file.
- Returns:
str | None – Header content or None.
str | None – Footer content or None.
Initialize¶
Initialize brassy with config file.
Create Note¶
Create a release-note YAML template and optionally open it in an editor.
- brassy.actions.create_note.create_note(file_path_arg: str | None, console: Any, working_dir: str = '.', open_editor: bool = False, editor_override: str | None = None, error_console: Any = None, force: bool = False) None[source]¶
Create a blank release-note YAML template and optionally open it.
The template is always created via
brassy.utils.file_handler.create_blank_template_yaml_file(). Whenopen_editorisTrue, the resulting file is then launched in the user’s editor (resolved git-style bybrassy.utils.editor_handler.resolve_editor()).- Parameters:
file_path_arg (str | None) – The file path of the YAML template as passed via the CLI.
Nonederives a name from the current git branch.console (Any) – A Rich console used for status messages.
working_dir (str) – The working directory path. Defaults to the current directory “.”.
open_editor (bool) – Whether to launch the editor on the created file.
False(the default) preserves the historical behaviour of-t.editor_override (str | None) – An editor command that bypasses resolution, typically sourced from the
--editorCLI flag.Noneresolves the editor normally.error_console (Any) – A Rich console used for error messages. Defaults to
consolewhen None.force (bool) – Whether to overwrite an existing template file. Defaults to False.
Notes
The editor is launched in the foreground so that interactive editors (
vim,nano, etc.) work correctly. A nonzero editor exit code is reported as a warning rather than propagated, since the file creation itself succeeded.
Templates¶
Release YAML¶
Release note YAML validation logic.
- class brassy.templates.release_yaml_template.ChangeItem(*, title: Annotated[str | None, MinLen(min_length=1)], description: Annotated[str | None, MinLen(min_length=1)], files: Files, related_issue: RelatedIssue | RelatedInternalIssue | None = None, date: DateRange | None = None)[source]¶
Bases:
BaseModelA model representing a change “item”, or an atomic change.
This class provides a structured way to represent changes with associated metadata such as title, description, affected files, related issues, and date range.
- Variables:
model_config (ConfigDict) – Pydantic configuration. Forbids unknown fields so that misspelled keys are reported rather than silently ignored.
title (str | None) – The title of the change item. Must be at least 1 character long if provided. Whitespace is stripped.
description (str | None) – A detailed description of the change. Must be at least 1 character long if provided. Whitespace is stripped.
files (Files) – The files affected by this change.
related_issue (RelatedIssue | RelatedInternalIssue | None) – An issue related to this change. Aliased as “related-issue” in serialized form. Default is None.
date (DateRange | None) – The date range associated with this change. Default is None.
Notes
Empty strings for ‘title’ and ‘description’ are automatically converted to None during validation.
- description: str | None¶
- classmethod empty_str_to_none(data: Any) Any[source]¶
Convert empty ‘title’/’description’ strings to None, mutating in place.
The in-place mutation is load-bearing, not an accident: callers keep using the same parsed mapping after validation, and the blank-entry filter in
read_yaml_filestreats""(drop the entry) andNone(keep it, render with defaults) differently.- Parameters:
data (Any) – The raw input for the change item, typically a mapping.
- Returns:
The input with empty ‘title’/’description’ strings converted to None.
- Return type:
Any
- model_config: ConfigDict = {'extra': 'forbid'}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- classmethod strip_whitespace_to_none(value: Any) Any[source]¶
Strip whitespace from strings and convert empty results to None.
- title: str | None¶
- class brassy.templates.release_yaml_template.DateRange(*, start: date | None = None, finish: date | None = None)[source]¶
Bases:
BaseModelDate range model for pydantic validation.
- finish: Date | None¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- classmethod parse_date(value: Any) date | None[source]¶
Parse and validate date values.
Converts various date formats to a Date object, handling strings, Date objects, and None values.
- Parameters:
value (Any) – Input to parse (Date, None, or string).
- Returns:
Parsed date or None for empty values.
- Return type:
Date | None
- Raises:
InvalidDateValueError – If the value cannot be parsed as a valid date
- start: Date | None¶
- class brassy.templates.release_yaml_template.Files(*, deleted: list[str] = [], moved: list[str] = [], added: list[str] = [], modified: list[str] = [])[source]¶
Bases:
BaseModelFiles model for validating files impacted in the changelog.
- added: list[str]¶
- deleted: list[str]¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- modified: list[str]¶
- moved: list[str]¶
- exception brassy.templates.release_yaml_template.InvalidDateValueError(date_string: str)[source]¶
Bases:
ValueErrorError for invalid date strings.
- class brassy.templates.release_yaml_template.RelatedInternalIssue(*, internal: Annotated[str | None, _PydanticGeneralMetadata(pattern='[A-Za-z]+#\\d+ - .+')] = None)[source]¶
Bases:
BaseModelPydantic class for ‘internal’ or non-public related issue.
- internal: str | None¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class brassy.templates.release_yaml_template.RelatedIssue(*, number: int | list[int] | None = None, repo_url: HttpUrl | None = None)[source]¶
Bases:
BaseModelPydantic class for validating related issue (eg. GitHub issue).
- classmethod convert_empty_to_none(value: Any) Any | None[source]¶
Convert empty strings to None for URL validation.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- number: int | list[int] | None¶
- repo_url: HttpUrl | None¶
- class brassy.templates.release_yaml_template.ReleaseNote(root: RootModelRootType = PydanticUndefined)[source]¶
Bases:
RootModel[Dict[str, List[ChangeItem]]]ReleaseNote is a root model for Release Notes.
It contains a dictionary that maps category names to lists of ChangeItems.
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Settings¶
Pydantic models for validating settings files.
- class brassy.templates.settings_template.ReleaseTemplate(*, release_template: list[dict[str, list[str]]] | None = None)[source]¶
Bases:
BaseModelBase pydantic model for release notes.
- class Config[source]¶
Bases:
objectRequired by pydantic for configuration.
- populate_by_name = True¶
- model_config = {'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- release_template: list[dict[str, list[str]]] | None¶
- class brassy.templates.settings_template.SettingsTemplate(*, use_color: bool = True, base_branch: str | None = None, default_yaml_path: Path | None = None, change_categories: list[str] = ['bug fix', 'enhancement', 'deprecation', 'removal', 'performance', 'documentation', 'continuous integration'], default_title: str = 'NO TITLE', default_description: str = 'NO DESCRIPTION', fail_on_empty_dir: bool = True, description_populates_with_pipe: bool = False, valid_fields: list[str] = ['title', 'description', 'files', 'related-issue'], valid_changes: list[str] = ['deleted', 'moved', 'added', 'modified'], enable_experimental_features: bool = False, templates: ReleaseTemplate | None = ReleaseTemplate(release_template=[{'header': ['{prefix_file}', '']}, {'title': ['', 'Version {release_version} ({release_date})', '**************************', '']}, {'summary': [' * *{change_type}*: {title}']}, {'entry': ['', '{change_type}', '===========', '', '{title}', '-------------------------', '', '{description}', '', '{issue}', '', '::', '', ' {file_change}: {file}']}, {'footer': ['', '{suffix_file}']}]), default_editor: str | None = None, auto_open_editor: bool = False)[source]¶
Bases:
BaseModelPydantic model for settings file.
- auto_open_editor: bool¶
- base_branch: str | None¶
- change_categories: list[str]¶
- default_description: str¶
- default_editor: str | None¶
- default_title: str¶
- default_yaml_path: pathlib.Path | None¶
- description_populates_with_pipe: bool¶
- enable_experimental_features: bool¶
- fail_on_empty_dir: bool¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- templates: ReleaseTemplate | None¶
- use_color: bool¶
- valid_changes: list[str]¶
- valid_fields: list[str]¶
Utils¶
CLI¶
The CLI only portions of brassy.
Brassy can be run without this file, and importing it brassy without it should allow users to call brassy without the CLI
- brassy.utils.CLI.exit_on_invalid_arguments(args: argparse.Namespace, parser: argparse.ArgumentParser, console: Console) None[source]¶
Validate the argparse arguments.
This function validates the provided argparse arguments to ensure that the required input files/folders and output file are provided. If arguments are invalid, it prints an error message and exits the program.
- Parameters:
args (argparse.Namespace) – Parsed arguments.
parser (argparse.ArgumentParser) – The ArgumentParser object used to parse the command-line arguments.
console (Console) – The rich console errors are reported on.
- Returns:
Exits the program if arguments are invalid, otherwise returns None.
- Return type:
None
- brassy.utils.CLI.get_file_list_from_cli_input(input_files_or_folders: list[str], console: Console, working_dir: str = '.', error_console: Console | None = None) list[Path][source]¶
Parse CLI input strings into full file paths.
- Parameters:
input_files_or_folders (list[str]) – Paths to input files or folders provided on the command line.
console (Console) – The rich console non-error output (such as the
fail_on_empty_dirwarning) is written to.working_dir (str) – The working directory used to resolve relative paths. Defaults to “.”.
error_console (Console | None) – The rich console errors are written to. Defaults to
consolewhen None.
- Returns:
Resolved paths to the YAML files found.
- Return type:
list[Path]
- brassy.utils.CLI.get_parser() ArgumentParser[source]¶
Return ArgumentParser for CLI.
- Returns:
The ArgumentParser object with predefined arguments.
- Return type:
argparse.ArgumentParser
- brassy.utils.CLI.get_yaml_files_from_input(input_files_or_folders: list[Path]) list[Path][source]¶
Get a list of YAML files from the given input files or folders.
- Parameters:
input_files_or_folders (list[Path]) – List of paths to input files or folders.
- Returns:
List of paths to YAML files.
- Return type:
list[Path]
- Raises:
ValueError – If a file is not a YAML file.
FileExistsError – If no YAML files are found in a directory.
FileNotFoundError – If the provided path does not exist.
git_handler¶
Handle Git-related functionality.
- brassy.utils.git_handler.get_current_git_branch(sanitize: bool = True) str[source]¶
Get the current dirs git branch name.
- Parameters:
sanitize (bool) – If True, sanitize branch name as a valid file name before returning.
- Returns:
The name of the current git branch.
- Return type:
str
- brassy.utils.git_handler.get_git_status(repo_path: str = '.', base_branch: str | None = None) dict[str, list[Any]][source]¶
Retrieve the status of files in the specified Git repository.
- Parameters:
repo_path (str) – The path to the Git repository. Defaults to the current directory.
base_branch (str | None) – The branch to diff the current branch against. When None, brassy tries
main,master, thentrunk.
- Returns:
A dictionary with the following keys:
- addedlist of str
List of file paths for files that have been added.
- modifiedlist of str
List of file paths for files that have been modified.
- deletedlist of str
List of file paths for files that have been deleted.
- movedlist of tuple
List of (old_path, new_path) tuples for renamed files.
- Return type:
dict[str, list[Any]]
- Raises:
pygit2.GitError – If the repository path is not a git repository, has no HEAD, or no base branch could be resolved.
- brassy.utils.git_handler.print_out_git_changed_files(print_function: Callable[[str], None], repo_path: str = '.', base_branch: str | None = None) None[source]¶
Print out changes as detected by Git in format Brassy expects in changlogs.
- Parameters:
print_function (Callable[[str], None]) – A callable that takes a string and prints it.
repo_path (str) – The path to the Git repository. Defaults to the current directory.
base_branch (str | None) – The branch to diff against. When None, brassy tries
main,master, thentrunk.
Messages¶
Handle outputs/inputs to the CLI.
The CLI writes through three channels, set up by setup_messages():
RichConsole– ordinary status and warnings, on stdout. Silenced by--quiet.error_console– errors, on stderr. Never silenced, so failures remain visible under--quiet.payload_print()– data the user explicitly asked for (--output-to-console,-c,--version), on stdout, unformatted and never silenced.
- brassy.utils.messages.get_boolean_prompt_function(enable_format: bool = True) Callable[[str], bool][source]¶
Return a function that prompts Y/N and returns True/False.
- Parameters:
enable_format (bool) – If True, uses rich’s Confirm.ask. If False, uses a plain input prompt.
- Returns:
A function that takes a question string and returns a boolean.
- Return type:
Callable[[str], bool]
- brassy.utils.messages.get_rich_opener(console: rich.console.Console | None = None, disable: bool = False) Callable[..., Any][source]¶
Return a file opener that renders a rich progress bar on
console.- Parameters:
console (rich.console.Console | None) – Console the progress bar is rendered on.
Nonelets rich fall back to its global console, which is unaware of brassy’s output settings. Defaults to None.disable (bool) – Whether to suppress the progress display entirely. Defaults to False.
- Returns:
A context-manager factory with the call signature of
rich.progress.open().- Return type:
Callable[…, Any]
- brassy.utils.messages.init_logger(use_rich: bool) Logger[source]¶
Initialize and configure the logger.
- Parameters:
use_rich (bool) – If True, sets up rich logging else use standard stream logging.
- Returns:
The configured logger instance.
- Return type:
logging.Logger
- brassy.utils.messages.payload_print(content: str) None[source]¶
Write requested program data to stdout, unformatted and never suppressed.
- Parameters:
content (str) – Text to write verbatim.
- brassy.utils.messages.setup_console(no_format: bool = False, quiet: bool = False, color: bool = True, stderr: bool = False) Console[source]¶
Set up and return a console for printing messages.
- Parameters:
no_format (bool) – Whether to disable rich formatting (markup rendering stays on so that markup tags are not printed literally). Defaults to False.
quiet (bool) – Whether to suppress this console’s output. Defaults to False.
color (bool) – Whether to allow ANSI colour and styling. When False, or when
no_formatis True, the console emits no escape sequences at all. Defaults to True.stderr (bool) – Whether the console writes to stderr instead of stdout. Defaults to False.
- Returns:
The configured rich console object.
- Return type:
rich.console.Console
- brassy.utils.messages.setup_messages(enable_format: bool, quiet: bool, color: bool = True) None[source]¶
Set up the module-level output channels used by the CLI.
- Parameters:
enable_format (bool) – Whether to enable rich formatting for output.
quiet (bool) – Whether to suppress ordinary (non-error) output.
color (bool) – Whether to allow ANSI colour and styling. Defaults to True.
Settings Manager¶
Manages getting and setting settings.
- brassy.utils.settings_manager.create_config_file(config_file: Path) None[source]¶
Create a configuration file with default settings.
- Parameters:
config_file (Path) – Path where the configuration file will be created.
- brassy.utils.settings_manager.get_config_files(app_name: str) list[Path][source]¶
Get configuration file paths in increasing precedence.
- Parameters:
app_name (str) – Name of the application.
- Returns:
List of configuration file paths. Site, user, then project.
- Return type:
list[Path]
- brassy.utils.settings_manager.get_git_repo_root(path: str = '.') Path[source]¶
Find the root directory of the Git repository for a path.
- Parameters:
path (str) – Path inside the repository. Defaults to “.”.
- Returns:
Absolute path to the repository root (the dir that contains .git).
- Return type:
Path
- brassy.utils.settings_manager.get_project_config_file_path(app_name: str) Path[source]¶
Return the path to the project’s configuration file.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the project’s configuration file. If the file does not exist locally, the path is resolved relative to the repository root when possible.
- Return type:
Path
- brassy.utils.settings_manager.get_settings(app_name: str) SettingsTemplate[source]¶
Return final application settings with file and env overrides.
- Parameters:
app_name (str) – Name of the application.
- Returns:
An instance containing the merged configuration.
- Return type:
- brassy.utils.settings_manager.get_settings_from_config_files(app_name: str) dict[str, Any][source]¶
Retrieve settings from configuration files without env overrides.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Configuration settings merged from files.
- Return type:
dict[str, Any]
- brassy.utils.settings_manager.get_site_config_file_path(app_name: str) Path[source]¶
Retrieve the site-wide configuration file path for the app.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the site’s configuration file.
- Return type:
Path
- brassy.utils.settings_manager.get_user_config_file_path(app_name: str) Path[source]¶
Retrieve the user-specific configuration file path for the app.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the user’s configuration file.
- Return type:
Path
- brassy.utils.settings_manager.merge_and_validate_config_files(config_files: list[Path]) dict[str, Any][source]¶
Merge settings from multiple config files and validate them.
- Parameters:
config_files (list[Path]) – Paths to configuration files. Later files override earlier ones.
- Returns:
Merged and validated configuration settings.
- Return type:
dict[str, Any]
- Raises:
ValidationError – If any file’s settings fail to validate against the SettingsTemplate model.
- brassy.utils.settings_manager.override_dict_with_environmental_variables(input_dict: dict[str, Any]) dict[str, Any][source]¶
Override dict values with case insensitive environment variables when available.
Every field of
SettingsTemplateis considered, so an environment variable applies even when the setting is absent from the input dictionary (for example when no configuration file exists).- Parameters:
input_dict (dict[str, Any]) – Original settings dictionary.
- Returns:
Updated settings dictionary with environment variable overrides.
- Return type:
dict[str, Any]
- brassy.utils.settings_manager.read_config_file(config_file: Path | str, create_file_if_not_exist: bool = False) dict[str, Any][source]¶
Read and parse a YAML configuration file.
- Parameters:
config_file (Path | str) – Path to the configuration file.
create_file_if_not_exist (bool) – Creates file if it doesn’t exist
- Returns:
Parsed configuration settings as a dictionary. A missing or empty file contributes an empty dictionary.
- Return type:
dict[str, Any]
- Raises:
ValueError – If the file exists but does not contain a YAML mapping.
File Handler¶
Handle file system I/O.
- brassy.utils.file_handler.create_blank_template_yaml_file(file_path_arg: str | None, error_console: Any, working_dir: str = '.', force: bool = False) Path[source]¶
Create a blank YAML template file with a predefined structure.
This function generates a YAML file at the specified path with a default template. It handles special characters required for YAML compatibility and writes the file to disk.
- Parameters:
file_path_arg (str | None) – The file path of the YAML template as passed via the CLI. An existing directory places a template named after the current git branch inside that directory.
error_console (Any) – A Rich Console object used for displaying errors to the user.
working_dir (str) – The working directory path. Defaults to the current directory “.”.
force (bool) – Whether to overwrite an existing file at the target path. When False (the default), an existing file is left untouched and the program exits with an error.
- Returns:
The path of the YAML template file that was created.
- Return type:
Path
Notes
This function performs a string replacement to insert a “|” due to an issue with YAML’s handling of pipe symbols. For more details, see: https://github.com/yaml/pyyaml/pull/822
- brassy.utils.file_handler.get_yaml_template_path(file_path_arg: str | None, working_dir: str | None = None) Path[source]¶
Return path of the YAML template file based on the given file path argument.
- Parameters:
file_path_arg (str | None) – The file path argument provided by the user.
working_dir (str | None) – The working directory path. Defaults to None, which uses the current working directory.
- Returns:
The path of the YAML template file.
- Return type:
Path
- brassy.utils.file_handler.read_yaml_files(input_files: list[str], rich_open: Any) dict[str, Any][source]¶
Read and parse the given list of YAML files.
- Parameters:
input_files (list[str]) – List of paths to the YAML files.
rich_open (Any) – A Rich progress-aware file open function (
rich.progress.open).
- Returns:
Parsed content of all YAML files categorized by type of change.
- Return type:
dict[str, Any]
Examples
>>> read_yaml_files(["file1.yaml", "file2.yaml"]) {'bug-fix': [ {'title': 'fixed explosions', 'description': 'This fixed the explosion mechanism'}, {'title': 'fixed cats not being cute', 'description': 'This made the cats WAY cuter'} ] }
- brassy.utils.file_handler.value_error_on_invalid_yaml(content: dict[str, Any] | None, file_path: str) None[source]¶
Check if the YAML content follows the correct schema.
- Parameters:
content (dict[str, Any] | None) – Parsed content of the YAML file.
file_path (str) – Path to the YAML file.
- Raises:
ValueError – If the YAML content does not follow the correct schema.
Editor Handler¶
Resolve and launch the user’s preferred text editor (git-style).
- brassy.utils.editor_handler.launch_editor(path: Path, editor: str, error_console: Any) int[source]¶
Launch
editoronpathin the foreground and return its exit code.The editor runs attached to the controlling terminal so that interactive editors such as
vimornanofunction correctly. Theeditorstring is split withshlex.split()so that flags (e.g.code --wait) are honoured.- Parameters:
path (Path) – Path to the file the editor should open.
editor (str) – The editor command (possibly with arguments) resolved by
resolve_editor().error_console (Any) – A Rich console used to report errors when the editor command cannot be executed.
- Returns:
The exit code returned by the editor process.
1is returned when the editor binary itself could not be found.- Return type:
int
- brassy.utils.editor_handler.open_file_in_editor(path: Path, error_console: Any, editor_override: str | None = None) int[source]¶
Resolve an editor and launch it on
path, returning the exit code.- Parameters:
path (Path) – Path to the file to open.
error_console (Any) – A Rich console used for error reporting.
editor_override (str | None) – Optional editor command that bypasses resolution.
Noneignores the argument and resolves the editor normally.
- Returns:
The editor process exit code (
1if the editor could not launch).- Return type:
int
- brassy.utils.editor_handler.resolve_editor(override: str | None = None) str[source]¶
Resolve which editor command to launch, in git-like priority order.
The lookup order is:
The
overrideargument (typically from the--editorCLI flag).The
default_editorsetting in the brassy configuration file.The
VISUALenvironment variable.The
EDITORenvironment variable.The
core.editorsetting from the git configuration.A platform default:
notepadon Windows,vielsewhere.
- Parameters:
override (str | None) – An editor command supplied by the caller. When provided and non-empty, it takes precedence over every other source.
Noneor an empty string is ignored.- Returns:
The editor command to launch, never empty.
- Return type:
str
YAML Handler¶
Load YAML safely, rejecting duplicate keys.
- exception brassy.utils.yaml_handler.DuplicateKeyError(key: Any, first_mark: Mark, second_mark: Mark)[source]¶
Bases:
ConstructorErrorRaised when a mapping declares the same key more than once.
- Parameters:
key (Any) – The key that was declared more than once.
first_mark (yaml.Mark) – Position of the first occurrence.
second_mark (yaml.Mark) – Position of the offending repeat occurrence.
- class brassy.utils.yaml_handler.UniqueKeySafeLoader(stream)[source]¶
Bases:
SafeLoaderA
yaml.SafeLoaderthat rejects mappings containing duplicate keys.PyYAML follows the permissive reading of the spec and keeps only the last of a set of duplicate keys, so a release note declaring
bug fix:twice silently loses the first block of entries. This loader raises instead.- construct_mapping(node: MappingNode, deep: bool = False) dict[Any, Any][source]¶
Construct a mapping, raising if any key appears more than once.
- Parameters:
node (yaml.MappingNode) – The mapping node being constructed.
deep (bool) – Whether to construct child nodes eagerly.
- Returns:
The constructed mapping.
- Return type:
dict[Any, Any]
- Raises:
DuplicateKeyError – If a key appears more than once in the mapping.
- brassy.utils.yaml_handler.load_yaml(stream: Any, file_path: str | Path) Any[source]¶
Parse a YAML document, rejecting duplicate keys and malformed syntax.
- Parameters:
stream (Any) – An open file object or string containing YAML.
file_path (str | Path) – Path to the source file, used in the error message.
- Returns:
The parsed YAML content.
- Return type:
Any
- Raises:
ValueError – If the document contains duplicate keys or is not valid YAML.
Main Module¶
Wrapper for CLI call and top-level functions.