From fdb0d0b68fe037fd9646b2ac6fff82d22979505a Mon Sep 17 00:00:00 2001 From: Mateusz Szewczyk Date: Tue, 15 Sep 2026 12:55:00 +0200 Subject: [PATCH] fix(pipelines-components): improve title casing and consolidate wrap_text Signed-off-by: Mateusz Szewczyk --- .../yoda_data_processor/component.py | 2 +- scripts/generate_readme/constants.py | 16 +++++++- scripts/generate_readme/content_generator.py | 32 +-------------- scripts/generate_readme/utils.py | 41 +++++++++++++++---- .../validate_examples/validate_examples.py | 3 +- 5 files changed, 51 insertions(+), 43 deletions(-) diff --git a/components/data_processing/yoda_data_processor/component.py b/components/data_processing/yoda_data_processor/component.py index cfb95b987..aa6983a4d 100644 --- a/components/data_processing/yoda_data_processor/component.py +++ b/components/data_processing/yoda_data_processor/component.py @@ -44,7 +44,7 @@ def add_yoda_prefix(example): # Split the dataset into train and eval sets print( f"Splitting dataset with {len(dataset)} rows into train ({train_split_ratio:.1%}) " - f"and eval ({(1-train_split_ratio):.1%}) sets" + f"and eval ({(1 - train_split_ratio):.1%}) sets" ) split_dataset = dataset.train_test_split(test_size=1 - train_split_ratio, seed=42) diff --git a/scripts/generate_readme/constants.py b/scripts/generate_readme/constants.py index 209902167..ee98f77fd 100644 --- a/scripts/generate_readme/constants.py +++ b/scripts/generate_readme/constants.py @@ -14,4 +14,18 @@ EXIT_ERROR = 2 # Actual error (e.g., missing function, failed to write file) # Markdown formatting constraints (per .markdownlint.json) -MAX_LINE_LENGTH = 120 # Maximum line length for markdown content +MAX_LINE_LENGTH = 120 # Maximum line length for Markdown content + +# Words with non-standard capitalization that should be preserved as-is +# instead of being title-cased. Keys must be lowercase. +SPECIAL_CASE_WORDS = { + "kfp": "KFP", + "api": "API", + "url": "URL", + "id": "ID", + "ui": "UI", + "ci": "CI", + "cd": "CD", + "automl": "AutoML", + "autorag": "AutoRAG", +} diff --git a/scripts/generate_readme/content_generator.py b/scripts/generate_readme/content_generator.py index 8d27533e7..bc73737d8 100644 --- a/scripts/generate_readme/content_generator.py +++ b/scripts/generate_readme/content_generator.py @@ -1,46 +1,18 @@ """README content generator for KFP components and pipelines.""" import logging -import textwrap from pathlib import Path from typing import Any, Dict import yaml from jinja2 import Environment, FileSystemLoader -from scripts.generate_readme.constants import MAX_LINE_LENGTH, README_TEMPLATE -from scripts.generate_readme.utils import format_title +from scripts.generate_readme.constants import README_TEMPLATE +from scripts.generate_readme.utils import format_title, wrap_text logger = logging.getLogger(__name__) -def wrap_text(text: str, width: int = MAX_LINE_LENGTH) -> str: - """Wrap text to specified width while preserving paragraph breaks. - - Args: - text: The text to wrap. - width: Maximum line width. - - Returns: - Wrapped text with preserved paragraph structure. - """ - if not text: - return text - - # Split into paragraphs (separated by blank lines) - paragraphs = text.split("\n\n") - wrapped_paragraphs = [] - - for paragraph in paragraphs: - # Remove existing line breaks within paragraph - paragraph = " ".join(paragraph.split()) - # Wrap to width - wrapped = textwrap.fill(paragraph, width=width, break_long_words=False, break_on_hyphens=False) - wrapped_paragraphs.append(wrapped) - - return "\n\n".join(wrapped_paragraphs) - - class ReadmeContentGenerator: """Generates README.md documentation content for KFP components and pipelines.""" diff --git a/scripts/generate_readme/utils.py b/scripts/generate_readme/utils.py index ecc953db5..fc0ded69e 100644 --- a/scripts/generate_readme/utils.py +++ b/scripts/generate_readme/utils.py @@ -1,6 +1,36 @@ """Utility functions for README generation.""" import re +import textwrap + +from scripts.generate_readme.constants import MAX_LINE_LENGTH, SPECIAL_CASE_WORDS + + +def wrap_text(text: str, width: int = MAX_LINE_LENGTH) -> str: + """Wrap text to specified width while preserving paragraph breaks. + + Args: + text: The text to wrap. + width: Maximum line width. + + Returns: + Wrapped text with preserved paragraph structure. + """ + if not text: + return text + + # Split into paragraphs (separated by blank lines) + paragraphs = text.split("\n\n") + wrapped_paragraphs = [] + + for paragraph in paragraphs: + # Remove existing line breaks within paragraph + paragraph = " ".join(paragraph.split()) + # Wrap to width + wrapped = textwrap.fill(paragraph, width=width, break_long_words=False, break_on_hyphens=False) + wrapped_paragraphs.append(wrapped) + + return "\n\n".join(wrapped_paragraphs) def format_title(title: str) -> str: @@ -18,15 +48,8 @@ def format_title(title: str) -> str: # Replace underscores and hyphens with spaces title = title.replace("_", " ").replace("-", " ") - # Split into words and capitalize each + # Split into words and capitalize each, preserving known special-case words words = title.split() - formatted_words = [] - - for word in words: - # Keep known acronyms in uppercase - if word.upper() in ["KFP", "API", "URL", "ID", "UI", "CI", "CD"]: - formatted_words.append(word.upper()) - else: - formatted_words.append(word.capitalize()) + formatted_words = [SPECIAL_CASE_WORDS.get(word.lower(), word.capitalize()) for word in words] return " ".join(formatted_words) diff --git a/scripts/validate_examples/validate_examples.py b/scripts/validate_examples/validate_examples.py index da663fc9b..36aab923b 100644 --- a/scripts/validate_examples/validate_examples.py +++ b/scripts/validate_examples/validate_examples.py @@ -66,8 +66,7 @@ def discover_example_files(targets: Sequence[Path]) -> List[Path]: relative = candidate.relative_to(REPO_ROOT) except ValueError: warnings.warn( - f"Unable to determine relative path for {candidate} " - f"relative to repo root {REPO_ROOT}. Skipping.", + f"Unable to determine relative path for {candidate} relative to repo root {REPO_ROOT}. Skipping.", ) continue if relative.parts and relative.parts[0] in {"components", "pipelines"}: