Source code for shinto.general

"""Provides functions to handle configuration settings for the application."""

import mimetypes
import zlib
import json
from pathlib import Path
from datetime import datetime, timezone
from typing import Union, Optional

try:
    from dateutil.parser import parse as parse_datetime
except ImportError:
    parse_datetime = None

CHUNK_SIZE = 65536  # Default chunk size for CRC32 calculation

[docs]def calculate_crc32_for_file(filename: Path, chunk_size: int = CHUNK_SIZE) -> int: """Calculate the CRC32 checksum for a file.""" crc = 0 with filename.open("rb") as f: while chunk := f.read(chunk_size): crc = zlib.crc32(chunk, crc) return crc & 0xffffffff
[docs]def get_mimetype_for_file(file_path: str) -> str: """Get MIME type from file path using built-in mimetypes module.""" mime_type, _ = mimetypes.guess_type(file_path) return mime_type or "application/octet-stream"
[docs]def normalize_timestamp(timestamp: Optional[Union[datetime, str]]) -> Optional[datetime]: """ Normalize a timestamp argument to a timezone-aware datetime object. Accepts a datetime, ISO 8601 string, or None. If no timezone is present, assumes UTC. Returns None if input is None. Raises ValueError for invalid input. """ if timestamp is None: return None if isinstance(timestamp, str): if parse_datetime is not None: dt = parse_datetime(timestamp) else: dt = datetime.fromisoformat(timestamp) if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) return dt elif isinstance(timestamp, datetime): if timestamp.tzinfo is None: return timestamp.replace(tzinfo=timezone.utc) return timestamp else: raise ValueError("timestamp must be a datetime, ISO 8601 string, or None")
[docs]def compare_json(json1: dict, json2: dict) -> bool: """Compare two JSON objects for equality, ignoring key order.""" return json.dumps(json1, sort_keys=True) == json.dumps(json2, sort_keys=True)