generated from coulomb/repo-seed
Extract the first reusable slice (models, schemas, routers, MCP, migrations) from state-hub with INTENT/SCOPE, agent instructions, workplan, and aligned inter_hub capability registry index.
28 lines
883 B
Python
28 lines
883 B
Python
from urllib.parse import SplitResult, urlsplit, urlunsplit
|
|
|
|
|
|
def normalize_trailing_slash(path_or_url: str, *, trailing: bool = True) -> str:
|
|
"""Normalize the path component while preserving query and fragment."""
|
|
if not path_or_url:
|
|
return "/" if trailing else ""
|
|
|
|
parts = urlsplit(path_or_url)
|
|
path = parts.path or "/"
|
|
if trailing:
|
|
normalized_path = path if path.endswith("/") else f"{path}/"
|
|
elif path == "/":
|
|
normalized_path = "/"
|
|
else:
|
|
normalized_path = path.rstrip("/")
|
|
|
|
if parts.scheme or parts.netloc:
|
|
return urlunsplit(
|
|
SplitResult(parts.scheme, parts.netloc, normalized_path, parts.query, parts.fragment)
|
|
)
|
|
suffix = ""
|
|
if parts.query:
|
|
suffix += f"?{parts.query}"
|
|
if parts.fragment:
|
|
suffix += f"#{parts.fragment}"
|
|
return f"{normalized_path}{suffix}"
|