from __future__ import annotations from collections.abc import Iterable from typing import Any def safe_text(value: Any, default: str | None = None) -> str | None: try: if value is None: return default return str(value) except Exception: return default def safe_count(collection: Any) -> int | None: """Return a collection count for Python or .NET-style collections.""" try: return len(collection) except Exception: pass try: return int(collection.Count) except Exception: return None def as_list(collection: Any) -> list[Any]: """Convert common Python.NET collections to a Python list.""" if collection is None: return [] try: return list(collection) except Exception: pass try: return list(collection.Values) except Exception: return [] def dictionary_items(collection: Any) -> list[tuple[Any, Any]]: """Return key/value pairs from PCSWMM's PythonDictionaryExt.""" if collection is None: return [] for method_name in ("items", "iteritems"): try: method = getattr(collection, method_name) return list(method()) except Exception: pass try: return [(key, collection[key]) for key in list(collection.Keys)] except Exception: return [] def public_names(obj: Any) -> list[str]: return sorted(name for name in dir(obj) if not name.startswith("_"))