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, console, working_dir)[source]

Prune empty values from YAML files specified by input paths.

Parameters:
  • input_files_or_folders (list of str) – A list of file paths or directories containing YAML files to prune.

  • console (Console) – An object used for printing messages to the console.

  • working_dir (str) – The working directory path.

Return type:

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, prune_lists=True, key='')[source]

Recursively remove empty values from a nested dictionary or list.

Parameters:
  • data (dict or list) – The data structure to prune.

  • prune_lists (bool, optional) – Indicates whether to prune empty lists. Currently unused.

  • key (str, optional) – 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:

dict or list or None

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, console)[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 (Console) – An object used for printing messages to the console.

Return type:

None

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, console, rich_open, version=None, release_date=None, header_file=None, footer_file=None, working_dir='.')[source]

Build release notes by reading YAML files and templates.

Parameters:
  • input_files_or_folders (list of str) – CLI-supplied file or directory paths.

  • console (Console) – Console for user feedback.

  • rich_open (Callable) – Context manager factory for reading files.

  • version (str or None, optional) – Release version string.

  • release_date (str or None, optional) – Release date override in ISO format.

  • header_file (str or None, optional) – Path to an optional header file.

  • footer_file (str or None, optional) – Path to an optional footer file.

  • working_dir (str, optional) – Base directory for relative paths.

Returns:

Rendered release notes in RST.

Return type:

str

brassy.actions.build_release_notes.find_duplicate_titles(data)[source]

Detect duplicate titles across changelog entries.

Parameters:

data (dict) – 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, entry)[source]

Format an RST block describing changed files for an entry.

Parameters:
  • detailed (bool) – Unused flag kept for compatibility.

  • entry (dict) – Changelog entry containing file changes.

Returns:

RST formatted file change listing.

Return type:

str

brassy.actions.build_release_notes.format_release_notes(data, version, release_date=None, header=None, footer=None)[source]

Generate release notes content from parsed changelog data.

Parameters:
  • data (dict) – Parsed changelog entries grouped by category.

  • version (str or None) – Release version string.

  • release_date (str or None, optional) – Release date override in ISO format. Defaults to today’s date.

  • header (str or None, optional) – Optional header content.

  • footer (str or None, optional) – 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, line, category, title, description)[source]

Create file-specific section lines for a changelog entry.

Parameters:
  • entry (dict) – 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 of str

brassy.actions.build_release_notes.generate_section_string(section_lines, changelog_entries, release_date, version, footer, header)[source]

Render a changelog section from templates and entries.

Parameters:
  • section_lines (list of str) – Template lines for the section.

  • changelog_entries (dict) – Mapping of categories to changelog entries.

  • release_date (str) – Release date string.

  • version (str) – Release version string.

  • footer (str or None) – Footer content appended to templates.

  • header (str or None) – Header content prepended to templates.

Returns:

Rendered section content.

Return type:

str

Read optional header and footer content.

Parameters:
  • rich_open (Callable) – Context manager factory for reading files.

  • header_file (str or None, optional) – Path to header file.

  • footer_file (str or None, optional) – Path to footer file.

Returns:

Header and footer content or None when unavailable.

Return type:

tuple of str or None

Initialize

Initialize brassy with config file.

brassy.actions.init.init()[source]

Initialize configuration files for the application.

This function creates site and user configuration files, and optionally a project configuration file based on user input.

Return type:

None

Examples

>>> init()
Do you want to create a project config file? [y/N]: y

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: BaseModel

A 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.

Parameters:
  • title (str or None, optional) – The title of the change item. Must be at least 1 character long if provided. Whitespace is stripped.

  • description (str or None, optional) – 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, or None, optional) – An issue related to this change. Aliased as “related-issue” in serialized form. Default is None.

  • date (DateRange or None, optional) – The date range associated with this change. Default is None.

Notes

Empty strings for ‘title’ and ‘description’ are automatically converted to None during validation.

date: DateRange | None
description: str | None
empty_str_to_none()[source]

Convert empty strings to None for ‘title’ and ‘description’ attributes.

This method checks if the ‘title’ or ‘description’ attributes of the object are empty strings and converts them to None if they are.

Returns:

  • self (object)

  • Returns the instance itself to allow for method chaining.

files: Files
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

related_issue: RelatedIssue | RelatedInternalIssue | None
title: str | None
class brassy.templates.release_yaml_template.DateRange(*, start: date | None = None, finish: date | None = None)[source]

Bases: BaseModel

Date range model for pydantic validation.

finish: Date | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod parse_date(value)[source]

Parse and validate date values.

Converts various date formats to a Date object, handling strings, Date objects, and None values.

Parameters:

value – Input to parse (Date, None, or string)

Returns:

Date or None

Return type:

Parsed date or None for empty values

Raises:

InvalidDateValue – If the value cannot be parsed as a valid date:

start: Date | None
validate_date_range()[source]

Validate that finish date is not before start date if both are set.

class brassy.templates.release_yaml_template.Files(*, deleted: List[str] = [], moved: List[str] = [], added: List[str] = [], modified: List[str] = [])[source]

Bases: BaseModel

Files model for validating files impacted in the changelog.

added: List[str]
check_at_least_one_field()[source]

Verify that at least one file is provided.

deleted: List[str]
model_config: ClassVar[ConfigDict] = {}

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: ValueError

Error for invalid date strings.

class brassy.templates.release_yaml_template.RelatedInternalIssue(*, internal: Annotated[str | None, _PydanticGeneralMetadata(pattern='[A-Za-z]+#\\d+ - .+')] = None)[source]

Bases: BaseModel

Pydantic class for ‘internal’ or non-public related issue.

internal: str | None
model_config: ClassVar[ConfigDict] = {}

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: BaseModel

Pydantic class for validating related issue (eg. GitHub issue).

classmethod convert_empty_to_none(value)[source]

Convert empty strings to None for URL validation.

model_config: ClassVar[ConfigDict] = {}

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: ClassVar[ConfigDict] = {}

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: BaseModel

Base pydantic model for release notes.

class Config[source]

Bases: object

Required by pydantic for configuration.

populate_by_name = True
model_config: ClassVar[ConfigDict] = {'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, 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}', '', '::', '', '     {file_change}: {file}']}, {'footer': ['', '{suffix_file}']}]))[source]

Bases: BaseModel

Pydantic model for settings file.

change_categories: list[str]
default_description: str
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: ClassVar[ConfigDict] = {}

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, parser, console)[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.

brassy.utils.CLI.get_file_list_from_cli_input(input_files_or_folders, console, working_dir='.')[source]

Parse CLI input string into full file paths.

brassy.utils.CLI.get_parser()[source]

Return ArgumentParser for CLI.

Returns:

argparse.ArgumentParser

Return type:

The ArgumentParser object with predefined arguments.

brassy.utils.CLI.get_yaml_files_from_input(input_files_or_folders)[source]

Get a list of YAML files from the given input files or folders.

Parameters:

input_files_or_folders (list) – List of paths to input files or folders.

Returns:

List of paths to YAML files.

Return type:

list

Raises:

ValueError – If a file is not a YAML file or if no YAML files are found in a directory.

brassy.utils.CLI.parse_arguments()[source]

Parse command line arguments for input folder and output file.

Returns:

Parsed arguments containing input_folder and output_file.

Return type:

argparse.Namespace

brassy.utils.CLI.print_version_and_exit()[source]

Print version and exit with status code 0.

brassy.utils.CLI.run_from_CLI()[source]

Generate release notes from YAML files and write output file.

git_handler

Handle Git-related functionality.

brassy.utils.git_handler.get_current_git_branch(sanitize=True)[source]

Get the current dirs git branch name.

Parameters:

sanitize (bool, optional) – 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='.')[source]

Retrieve the status of files in the specified Git repository.

Parameters:

repo_path (str, optional) – The path to the Git repository. Defaults to the current directory.

Returns:

A dictionary with the following keys:

  • ’added’: list of str

    List of file paths for files that have been added.

  • ’modified’: list of str

    List of file paths for files that have been modified.

  • ’deleted’: list of str

    List of file paths for files that have been deleted.

  • ’renamed’: list of str

    List of file paths for files that have been renamed.

Return type:

dict

brassy.utils.git_handler.print_out_git_changed_files(print_function, repo_path='.')[source]

Print out changes as detected by Git in format Brassy expects in changlogs.

Messages

Handle outputs/inputs to the CLI.

brassy.utils.messages.get_boolean_prompt_function(enable_format=True)[source]

Return a function that prompts Y/N and returns True/False.

brassy.utils.messages.get_rich_opener(no_format=False)[source]

Return opener function with or without a rich progress bar.

Parameters:

no_format (bool, optional) – If True, returns the opener function without any formatting. If False, returns the opener function with formatting. Defaults to False.

Returns:

function

Return type:

The opener function for rich progress bar.

brassy.utils.messages.init_logger(use_rich)[source]

Initialize and configure the logger.

Parameters:

use_rich (bool) – If True, sets up rich logging else use standard stream logging

Returns:

logger – The configured logger instance

Return type:

logging.Logger

brassy.utils.messages.setup_console(no_format=False, quiet=False)[source]

Set up and return the console for printing messages.

Parameters:
  • no_format (bool, optional) – Whether to disable formatting. Defaults to False.

  • quiet (bool, optional) – Whether to suppress console output. Defaults to False.

Returns:

Console

Return type:

The configured rich console object.

brassy.utils.messages.setup_messages(enable_format, quiet)[source]

Set up global objects for outputting messages to the CLI.

Settings Manager

Manages getting and setting settings.

brassy.utils.settings_manager.create_config_file(config_file)[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)[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='.')[source]

Find the root directory of the Git repository for a path.

Parameters:

path (str, optional) – 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)[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)[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:

SettingsTemplate

Raises:

ValidationError – If the final settings fail to validate against the model.

brassy.utils.settings_manager.get_settings_from_config_files(app_name)[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

brassy.utils.settings_manager.get_site_config_file_path(app_name)[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)[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)[source]

Merge settings from multiple config files and validate them.

Parameters:

config_files (list of Path) – Paths to configuration files. Later files override earlier ones.

Returns:

Merged and validated configuration settings.

Return type:

dict

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)[source]

Override dict values with case insensitive environment variables when available.

Parameters:

input_dict (dict) – Original settings dictionary.

Returns:

Updated settings dictionary with environment variable overrides.

Return type:

dict

brassy.utils.settings_manager.read_config_file(config_file, create_file_if_not_exist=False)[source]

Read and parse a YAML configuration file.

Parameters:
  • config_file (Path or 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.

Return type:

dict

File Handler

Handle file system I/O.

brassy.utils.file_handler.create_blank_template_yaml_file(file_path_arg, console, working_dir='.')[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) – The file path of the YAML template as passed via the CLI.

  • console (rich.console.Console) – A Rich Console object used for displaying messages and errors to the user.

  • working_dir (str, optional) – The working directory path. Defaults to the current directory “.”.

Raises:

SystemExit – If a Git repo is not found in the current working directory and no file path is provided, the program exits with an error message.

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, working_dir=None)[source]

Return path of the YAML template file based on the given file path argument.

Parameters:

file_path_arg (str) – The file path argument provided by the user.

Returns:

str

Return type:

The path of the YAML template file.

brassy.utils.file_handler.read_yaml_files(input_files, rich_open)[source]

Read and parse the given list of YAML files.

Parameters:

input_files (list) – List of paths to the YAML files.

Returns:

Parsed content of all YAML files categorized by type of change.

Return type:

dict

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, file_path)[source]

Check if the YAML content follows the correct schema.

Parameters:
  • content (dict) – 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.

brassy.utils.file_handler.write_output_file(output_file, content)[source]

Write the formatted release notes to the output file.

Parameters:
  • output_file (str) – Path to the output .rst file.

  • content (str) – Formatted release notes.

Main Module

Wrapper for CLI call and top-level functions.

brassy.brassy.run_from_CLI()[source]

Run brassy via the CLI.