API¶
Code Docstrings¶
Actions¶
Prune YAML¶
- 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¶
- 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 from YAML data.
- Parameters:
data (dict) – Parsed content of YAML files.
version (str, optional) – Version number of the release, by default ‘1.1’.
release_date (str, optional) – Release date, by default None, which uses today’s date.
header_file (str, optional) – A header file to prepend to the release notes.
footer_file (str, optional) – A footer file to suffix to the release notes.
- Returns:
Formatted release notes in .rst format.
- Return type:
str
- brassy.actions.build_release_notes.find_duplicate_titles(data)[source]¶
Check if there are any duplicate titles in dictionaries of lists of dictionaries.
- Parameters:
data (dict) – A dictionary containing lists of dictionaries with items indexed by “title”.
- Returns:
True if there are duplicate “title” values, False otherwise.
- Return type:
bool
- brassy.actions.build_release_notes.format_release_notes(data, version, release_date=None, header=None, footer=None)[source]¶
Format the parsed YAML data into release notes in .rst format.
- Parameters:
data (dict) – Parsed content of YAML files.
version (str, optional) – Version number of the release, by default ‘1.1’.
release_date (str, optional) – Release date, by default None, which uses today’s date.
- Returns:
Formatted release notes in .rst format.
- Return type:
str
- brassy.actions.build_release_notes.generate_file_change_section_list_of_strings(entry, line, category, title, description)[source]¶
- brassy.actions.build_release_notes.generate_section_string(section_lines, changelog_entries, release_date, version, footer, header)[source]¶
Adds a header and/or footer to the given content.
- Parameters:
content (str) – The content to which the header and/or footer will be added.
rich_open (function) – A function used to open files.
header_file (str, optional) – The file containing the header content. Defaults to None.
footer_file (str, optional) – The file containing the footer content. Defaults to None.
- Returns:
The content with the header and/or footer added.
- Return type:
str
Initialize¶
- 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¶
- 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
- description: str | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'date': FieldInfo(annotation=Union[DateRange, NoneType], required=False, default=None), 'description': FieldInfo(annotation=Union[str, NoneType], required=True, json_schema_extra={'strip_whitespace': True}, metadata=[MinLen(min_length=1)]), 'files': FieldInfo(annotation=Files, required=True), 'related_issue': FieldInfo(annotation=Union[RelatedIssue, RelatedInternalIssue, NoneType], required=False, default=None, alias='related-issue', alias_priority=2, json_schema_extra={'exclude_unset': True}), 'title': FieldInfo(annotation=Union[str, NoneType], required=True, json_schema_extra={'strip_whitespace': True}, metadata=[MinLen(min_length=1)])}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- title: str | None¶
- class brassy.templates.release_yaml_template.DateRange(*, start: date | None, finish: date | None)[source]¶
Bases:
BaseModel
- finish: date | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'finish': FieldInfo(annotation=Union[date, NoneType], required=True, validate_default=True), 'start': FieldInfo(annotation=Union[date, NoneType], required=True, validate_default=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- start: date | None¶
- class brassy.templates.release_yaml_template.Files(*, deleted: List[str] = [], moved: List[str] = [], added: List[str] = [], modified: List[str] = [])[source]¶
Bases:
BaseModel
- added: List[str]¶
- deleted: List[str]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'added': FieldInfo(annotation=List[str], required=False, default=[]), 'deleted': FieldInfo(annotation=List[str], required=False, default=[]), 'modified': FieldInfo(annotation=List[str], required=False, default=[]), 'moved': FieldInfo(annotation=List[str], required=False, default=[])}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- modified: List[str]¶
- moved: List[str]¶
- class brassy.templates.release_yaml_template.RelatedInternalIssue(*, internal: Annotated[str | None, _PydanticGeneralMetadata(pattern='[A-Za-z]+#\\d+ - .+')] = None)[source]¶
Bases:
BaseModel
- internal: str | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'internal': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, metadata=[_PydanticGeneralMetadata(pattern='[A-Za-z]+#\\d+ - .+')])}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- class brassy.templates.release_yaml_template.RelatedIssue(*, number: int | None = None, repo_url: Annotated[Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)] | None = None)[source]¶
Bases:
BaseModel
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'number': FieldInfo(annotation=Union[int, NoneType], required=False, default=None), 'repo_url': FieldInfo(annotation=Union[Annotated[Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)], NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- number: int | None¶
- repo_url: Annotated[Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)] | None¶
- class brassy.templates.release_yaml_template.ReleaseNote(root: RootModelRootType = PydanticUndefined)[source]¶
Bases:
RootModel[Dict[str, List[ChangeItem]]]
ReleaseNote is a root model containing a dictionary that maps category names to lists of ChangeItems.
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'root': FieldInfo(annotation=Dict[str, List[ChangeItem]], required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
Settings¶
- class brassy.templates.settings_template.ReleaseTemplate(*, release_template: List[Dict[str, List[str]]] | None = None)[source]¶
Bases:
BaseModel
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'populate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'release_template': FieldInfo(annotation=Union[List[Dict[str, List[str]]], NoneType], required=False, default=None, alias='release-template', alias_priority=2)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- 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
- change_categories: List[str]¶
- default_description: str¶
- default_title: str¶
- default_yaml_path: Path | None¶
- description_populates_with_pipe: bool¶
- enable_experimental_features: bool¶
- fail_on_empty_dir: bool¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'change_categories': FieldInfo(annotation=List[str], required=False, default=['bug fix', 'enhancement', 'deprecation', 'removal', 'performance', 'documentation', 'continuous integration']), 'default_description': FieldInfo(annotation=str, required=False, default='NO DESCRIPTION'), 'default_title': FieldInfo(annotation=str, required=False, default='NO TITLE'), 'default_yaml_path': FieldInfo(annotation=Union[Path, NoneType], required=False, default=None), 'description_populates_with_pipe': FieldInfo(annotation=bool, required=False, default=False), 'enable_experimental_features': FieldInfo(annotation=bool, required=False, default=False), 'fail_on_empty_dir': FieldInfo(annotation=bool, required=False, default=True), 'templates': FieldInfo(annotation=Union[ReleaseTemplate, NoneType], required=False, default=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}']}])), 'use_color': FieldInfo(annotation=bool, required=False, default=True), 'valid_changes': FieldInfo(annotation=List[str], required=False, default=['deleted', 'moved', 'added', 'modified']), 'valid_fields': FieldInfo(annotation=List[str], required=False, default=['title', 'description', 'files', 'related-issue'])}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- templates: ReleaseTemplate | None¶
- use_color: bool¶
- valid_changes: List[str]¶
- valid_fields: List[str]¶
Utils¶
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]¶
- brassy.utils.CLI.get_parser()[source]¶
Returns an ArgumentParser object with predefined arguments for generating release notes from YAML files.
- Returns:
The ArgumentParser object with predefined arguments.
- Return type:
argparse.ArgumentParser
- 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.
git_handler¶
- brassy.utils.git_handler.get_current_git_branch()[source]¶
Get the current dirs git branch name.
- 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
Messages¶
- brassy.utils.messages.get_rich_opener(no_format=False)[source]¶
Returns the appropriate opener function for 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:
The opener function for rich progress bar.
- Return type:
function
- 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:
The configured rich console object.
- Return type:
Console
Settings Manager¶
- brassy.utils.settings_manager.create_config_file(config_file)[source]¶
Create a configuration file with default settings.
- Parameters:
config_file (str) – Path where the configuration file will be created.
- brassy.utils.settings_manager.get_config_files(app_name)[source]¶
Get a list of configuration file paths in order of increasing precedence.
- Parameters:
app_name (str) – Name of the application.
- Returns:
List of configuration file paths.
- Return type:
list of str
- brassy.utils.settings_manager.get_git_repo_root(path='.')[source]¶
Get the root directory of the Git repository containing the given path.
- Parameters:
path (str, optional) – A path within the Git repository. Defaults to the current directory.
- Returns:
Absolute path to the root of the Git repository. This is usually the path containing the .git folder.
- Return type:
str
- brassy.utils.settings_manager.get_project_config_file_path(app_name)[source]¶
Retrieve the project-specific configuration file path for the application.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the project’s configuration file.
- Return type:
str
- brassy.utils.settings_manager.get_settings(app_name)[source]¶
Return application settings from config files and environment variables.
- Parameters:
app_name (str) – Name of the application.
- Returns:
An instance of the Settings model with all configurations applied.
- Return type:
Settings
- Raises:
ValidationError – If the final settings do not conform to the Settings model.
- brassy.utils.settings_manager.get_settings_from_config_files(app_name)[source]¶
Retrieve settings from configuration files without environment 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-specific configuration file path for the application.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the site’s configuration file.
- Return type:
str
- brassy.utils.settings_manager.get_user_config_file_path(app_name)[source]¶
Retrieve the user-specific configuration file path for the application.
- Parameters:
app_name (str) – Name of the application.
- Returns:
Path to the user’s configuration file.
- Return type:
str
- brassy.utils.settings_manager.merge_and_validate_config_files(config_files)[source]¶
Merge settings from multiple configuration files and validate them.
- Parameters:
config_files (list of str) – List of configuration file paths. The order of the files matters. Each file overwrites the values of the previous.
- Returns:
Merged and validated configuration settings.
- Return type:
dict
- Raises:
ValidationError – If any of the settings do not conform to the Settings 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 (str) – Path to the configuration file.
create_file_if_not_exist (bool) – Creates file if it doesn’t exist
- Returns:
Parsed configuration settings.
- Return type:
dict
File Handler¶
- brassy.utils.file_handler.create_blank_template_yaml_file(file_path_arg, console, working_dir='.')[source]¶
Creates 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='/workspaces/yaml-to-release-note/sphinx')[source]¶
Returns the 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:
The path of the YAML template file.
- Return type:
str
- 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.
Main Module¶
This module provides functionality to generate release notes from YAML files. It reads YAML files, parses their content, and formats the parsed data into release notes in .rst format. The release notes can be written to an output file.