Converts the output of popular command-line tools and file-types to JSON.
—
Utility functions for text processing, validation, and comprehensive type definitions used throughout the jc library. These provide the foundation for parser development and error handling.
Custom exception classes for jc-specific error handling.
class ParseError(Exception):
"""
General parsing error exception.
Raised when a parser encounters data it cannot process correctly.
Used by individual parsers to indicate parsing failures.
"""
class LibraryNotInstalled(Exception):
"""
Missing library dependency exception.
Raised when a parser requires an optional dependency that is not installed.
Allows parsers to gracefully handle missing optional libraries.
"""Comprehensive type system used throughout the jc library.
from typing import Dict, List, Union, Optional, Iterable, Iterator, TypedDict, Any, Tuple
from types import ModuleType
# Basic type aliases
JSONDictType = Dict[str, Any]
CustomColorType = Dict[Any, str]
StreamingOutputType = Iterator[Union[JSONDictType, Tuple[BaseException, str]]]
# Parser metadata structure (Python 3.8+)
ParserInfoType = TypedDict('ParserInfoType', {
"name": str, # Parser module name
"argument": str, # CLI argument form (--parser-name)
"version": str, # Parser version
"description": str, # Parser description
"author": str, # Parser author
"author_email": str, # Author email
"compatible": List[str], # Compatible platforms
"magic_commands": List[str], # Commands that trigger magic mode
"tags": List[str], # Parser categorization tags
"documentation": str, # Parser documentation
"streaming": bool, # Whether parser supports streaming
"plugin": bool, # Whether parser is a plugin
"hidden": bool, # Whether parser is hidden from lists
"deprecated": bool # Whether parser is deprecated
}, total=False)
# Timestamp format structure
TimeStampFormatType = TypedDict('TimeStampFormatType', {
'id': int, # Format identifier
'format': str, # strftime format string
'locale': Optional[str] # Locale for parsing
})Core utility functions for text manipulation and encoding handling.
def _asciify(string: str) -> str:
"""
Convert Unicode string to ASCII with simple character replacements.
Parameters:
- string: Input Unicode string
Returns:
- ASCII-compatible string with unicode characters converted
"""
def _safe_print(
string: str,
sep: str = ' ',
end: str = '\n',
file: TextIO = sys.stdout,
flush: bool = False
) -> None:
"""
Print output safely for both UTF-8 and ASCII encoding systems.
Parameters:
- string: String to print
- sep: Separator character
- end: End character
- file: Output file object
- flush: Whether to flush output
"""
def _safe_pager(string: str) -> None:
"""
Display output in pager safely for both UTF-8 and ASCII systems.
Parameters:
- string: String to display in pager
"""Helper functions and constants for developing custom parsers.
# Global quiet flag for suppressing warnings
CLI_QUIET: bool = False
def warning_message(message_lines: List[str]) -> None:
"""
Display warning message unless quiet mode is enabled.
Parameters:
- message_lines: List of warning message lines to display
"""
def error_message(message_lines: List[str]) -> None:
"""
Display error message to stderr.
Parameters:
- message_lines: List of error message lines to display
"""Functions for parsing and formatting timestamps and dates.
def timestamp_convert(
timestamp: Union[int, float, str],
format_hint: Optional[str] = None
) -> Dict[str, Any]:
"""
Convert various timestamp formats to structured datetime information.
Parameters:
- timestamp: Timestamp in various formats (epoch, ISO, etc.)
- format_hint: Optional format hint for parsing
Returns:
- Dictionary with parsed datetime components
"""
def iso_datetime_parse(
iso_string: str,
timezone_aware: bool = True
) -> Dict[str, Any]:
"""
Parse ISO 8601 datetime strings into structured format.
Parameters:
- iso_string: ISO 8601 formatted datetime string
- timezone_aware: Whether to include timezone information
Returns:
- Dictionary with parsed datetime components
"""Functions for validating and cleaning parser inputs and outputs.
def normalize_key(key: str) -> str:
"""
Normalize dictionary keys for consistent output formatting.
Parameters:
- key: Raw key string
Returns:
- Normalized key string (lowercase, underscores, etc.)
"""
def clean_json_output(data: Any) -> Any:
"""
Clean and normalize JSON output for consistency.
Parameters:
- data: Raw parsed data structure
Returns:
- Cleaned data structure suitable for JSON serialization
"""Functions supporting the plugin system for custom parser development.
def get_user_data_dir() -> str:
"""
Get user data directory for jc plugins and configuration.
Returns:
- Path to user-specific jc data directory
"""
def validate_plugin_parser(parser_module: ModuleType) -> bool:
"""
Validate that a module conforms to parser interface requirements.
Parameters:
- parser_module: Module to validate
Returns:
- True if module is a valid parser, False otherwise
"""from jc.exceptions import ParseError, LibraryNotInstalled
try:
data = jc.parse('dig', dig_output)
except ParseError as e:
print(f"Parsing failed: {e}")
except LibraryNotInstalled as e:
print(f"Missing dependency: {e}")from jc.jc_types import JSONDictType, ParserInfoType
from typing import List
def process_parser_output(data: JSONDictType) -> None:
# Process parsed data with proper typing
if 'timestamp' in data:
print(f"Timestamp: {data['timestamp']}")
def get_all_parser_metadata() -> List[ParserInfoType]:
# Function with proper return type annotation
return jc.all_parser_info()from jc.utils import _safe_print, _asciify
# Safe printing for different encodings
unicode_text = "Processing file: résumé.txt"
_safe_print(unicode_text)
# Convert unicode to ASCII when needed
ascii_text = _asciify(unicode_text)
print(ascii_text) # "Processing file: r\xe9sum\xe9.txt"from jc.jc_types import ParserInfoType
from jc.exceptions import ParseError
import jc.utils
# Parser metadata
info: ParserInfoType = {
'name': 'my_parser',
'description': 'Parse my custom format',
'author': 'Your Name',
'version': '1.0',
'compatible': ['linux', 'darwin'],
'tags': ['file']
}
def parse(data: str, quiet: bool = False, raw: bool = False) -> JSONDictType:
"""Parse custom data format"""
try:
# Parsing logic here
result = {'parsed': True, 'data': data.strip()}
return jc.utils.clean_json_output(result)
except Exception as e:
if not quiet:
jc.utils.warning_message([f"Parse error: {e}"])
raise ParseError(f"Failed to parse data: {e}")import os
from jc.utils import get_user_data_dir
# Set up plugin directory
plugin_dir = os.path.join(get_user_data_dir(), 'jcparsers')
os.makedirs(plugin_dir, exist_ok=True)
# Create custom parser file
parser_file = os.path.join(plugin_dir, 'my_custom_parser.py')
with open(parser_file, 'w') as f:
f.write(custom_parser_code)This utilities module provides the essential infrastructure for jc's extensible parser system, robust error handling, and cross-platform compatibility.
Install with Tessl CLI
npx tessl i tessl/pypi-jc