all2md.utils.inputs
Utilities for uniform input handling across all2md modules.
This module provides standardized input validation and conversion functions that are used across all conversion modules in all2md. This ensures consistent behavior when handling different input types (paths, file-like objects, bytes, etc.) and provides clear error messages for unsupported inputs.
The functions in this module handle the conversion between different input types and perform validation to ensure that inputs are suitable for the requested conversion operations.
Functions
validate_and_convert_input: Main input validation and conversion function
is_path_like: Check if input is path-like (string or Path object)
is_file_like: Check if input is a file-like object
escape_markdown_special: Escape special Markdown characters in text
format_special_text: Format special text (underline, superscript, subscript)
format_markdown_heading: Format headings in hash or underline style
- all2md.utils.inputs.is_path_like(obj: Any) bool
Check if an object is path-like (string or pathlib.Path).
- Parameters:
obj (Any) – Object to check
- Returns:
True if object is path-like, False otherwise
- Return type:
bool
Examples
>>> is_path_like("document.pdf") True >>> is_path_like(Path("document.pdf")) True >>> is_path_like(BytesIO(b"data")) False
- all2md.utils.inputs.is_file_like(obj: Any) bool
Check if an object is file-like (has read method).
- Parameters:
obj (Any) – Object to check
- Returns:
True if object appears to be file-like, False otherwise
- Return type:
bool
Examples
>>> from io import BytesIO >>> is_file_like(BytesIO(b"data")) True >>> is_file_like("not_file_like") False
- all2md.utils.inputs.validate_page_range(pages: list[int] | str | None, max_pages: int | None = None) list[int] | None
Validate and normalize a page range specification.
All page numbers are 1-based (like “page 1”, “page 2”) and converted to 0-based internally.
- Parameters:
pages (list[int], str, or None) – Page specification (1-based): - list[int]: List of page numbers [1, 2, 3] - str: Page range string, e.g. “1-3,5,10-” - None: Use all pages
max_pages (int or None, optional) – Maximum number of pages available for validation
- Returns:
Validated list of 0-based page indices, or None if input was None
- Return type:
list[int] or None
- Raises:
PageRangeError – If page numbers are invalid or out of range
Examples
>>> validate_page_range([1, 2, 3], max_pages=5) [0, 1, 2] >>> validate_page_range("1-3,5", max_pages=10) [0, 1, 2, 4] >>> validate_page_range("10-", max_pages=12) [9, 10, 11] >>> validate_page_range([0], max_pages=5) Traceback (most recent call last): ... all2md.exceptions.PageRangeError: Invalid page number: 0. Pages must be >= 1.
- all2md.utils.inputs.validate_and_convert_input(input_data: str | Path | BinaryIO | BytesIO | StringIO | bytes | Any, supported_types: list[str] | None = None, require_binary: bool = False) tuple[Any, str]
Validate input and convert to appropriate format for processing.
This function handles the common pattern of accepting different input types (paths, file-like objects, bytes, document objects) and converting them to a format suitable for the conversion functions.
- Parameters:
input_data (InputType) – Input data to validate and convert
supported_types (list[str] or None, optional) – List of supported input type names for error messages
require_binary (bool, default False) – Whether the input must be in binary mode (vs text mode)
- Returns:
Tuple of (converted_input, input_type_description) where input_type_description is one of: “path”, “file”, “bytes”, “object”
- Return type:
tuple[Any, str]
- Raises:
FileNotFoundError – If the file does not exist
ValidationError – If the input type is not supported
Examples
>>> # Path input >>> data, type_desc = validate_and_convert_input("document.pdf") >>> print(type_desc) path
>>> # File-like input >>> from io import BytesIO >>> data, type_desc = validate_and_convert_input(BytesIO(b"content")) >>> print(type_desc) file
- all2md.utils.inputs.escape_markdown_special(text: str, escape_chars: str | None = None) str
Escape special Markdown characters in text to prevent formatting.
- Parameters:
text (str) – Text containing potential Markdown special characters
escape_chars (str or None, optional) – Characters to escape. If None, uses default set from constants
- Returns:
Text with special characters escaped with backslashes
- Return type:
str
Examples
>>> escape_markdown_special("This *should* not be italic") 'This \\*should\\* not be italic' >>> escape_markdown_special("Link: [text](url)") 'Link: \\[text\\]\\(url\\)'
- all2md.utils.inputs.format_special_text(text: str, format_type: str, mode: str = 'html') str
Format special text (underline, superscript, subscript) according to mode.
- Parameters:
text (str) – Text content to format
format_type ({"underline", "superscript", "subscript"}) – Type of special formatting to apply
mode ({"html", "markdown", "ignore"}, default "html") – Output format mode: - “html”: Use HTML tags (<u>, <sup>, <sub>) - “markdown”: Use Markdown-style syntax (__, ^, ~) - “ignore”: Return plain text without formatting
- Returns:
Formatted text according to the specified mode
- Return type:
str
Examples
>>> format_special_text("underlined", "underline", "html") '<u>underlined</u>' >>> format_special_text("superscript", "superscript", "markdown") '^superscript^' >>> format_special_text("subscript", "subscript", "ignore") 'subscript'
- all2md.utils.inputs.format_markdown_heading(text: str, level: int, use_hash: bool = True) str
Format a heading in Markdown using either hash or underline style.
This function formats only the heading itself, without adding trailing blank lines. Block-level spacing should be handled by the caller (e.g., document renderers that add spacing between block elements).
- Parameters:
text (str) – The heading text content
level (int) – The heading level (1-6 for hash style, 1-2 for underline style)
use_hash (bool, default True) – Whether to use hash-style headings (# Heading) or underline style (Headingn=======)
- Returns:
Formatted heading string ending with a single newline
- Return type:
str
Examples
>>> format_markdown_heading("Main Title", 1, use_hash=True) '# Main Title\n' >>> format_markdown_heading("Main Title", 1, use_hash=False) 'Main Title\n==========\n' >>> format_markdown_heading("Subtitle", 2, use_hash=False) 'Subtitle\n--------\n'
Notes
For underline style: - Level 1 headings use ‘=’ characters for underline - Level 2+ headings use ‘-’ characters for underline - Only levels 1-2 are supported for underline style; higher levels fall back to hash style
For hash style: - Supports levels 1-6 (# to ######) - Levels beyond 6 are clamped to 6
Spacing between blocks should be handled externally. This function does NOT add trailing blank lines to avoid conflicts with document-level spacing logic.
- all2md.utils.inputs.parse_page_ranges(page_spec: str, total_pages: int) list[int]
Parse page range specification into list of 0-based page indices.
Supports various formats: - “1-3” → [0, 1, 2] - “5” → [4] - “10-” → [9, 10, …, total_pages-1] - “1-3,5,10-” → combined ranges - “5-3” → [2, 3, 4] (automatically swaps to “3-5”)
Reversed ranges (where start > end) are automatically corrected by swapping the values. For example, “10-5” is treated as “5-10”.
- Parameters:
page_spec (str) – Page range specification (1-based page numbers)
total_pages (int) – Total number of pages in document
- Returns:
Sorted list of 0-based page indices
- Return type:
list of int
Examples
>>> parse_page_ranges("1-3,5", 10) [0, 1, 2, 4] >>> parse_page_ranges("8-", 10) [7, 8, 9] >>> parse_page_ranges("10-5", 10) [4, 5, 6, 7, 8, 9]