Skip to content

URL Utilities

The url module in escudeiro provides a modern, object-oriented interface for parsing, constructing, and manipulating URLs. It supports all standard URL components and offers a fluent, immutable API for safe and expressive URL handling.


Why?

Manipulating URLs with the Python standard library can be verbose and error-prone:

from urllib.parse import urlparse, urlunparse

parsed = urlparse("https://user:pass@host:8080/path?query=1#frag")
new_url = urlunparse(parsed._replace(path="/newpath"))

With escudeiro.url, you get a high-level, immutable URL object with convenient accessors and modifiers:

from escudeiro.url import URL

url = URL("https://user:pass@host:8080/path?query=1#frag")
print(url.path)  # "/path"
new_url = url.add(path="newpath")
print(str(new_url))  # "https://user:pass@host:8080/path/newpath?query=1#frag"

Features

  • Full URL parsing and construction (scheme, userinfo, host, port, path, query, fragment)
  • Immutable, chainable API for safe modifications
  • Component-wise access and modification via .add() and properties
  • Convenient helpers for query, path, fragment, and netloc manipulation
  • Type-safe and dataclass-friendly

Usage

Adding Query Parameters

from escudeiro.url import URL

url = URL("https://www.example.com/path?key1=value1").add(
    query={"key2": "value2", "key3": "value3"}
)
print(url.query)  # "key1=value1&key2=value2&key3=value3"
print(str(url))   # "https://www.example.com/path?key1=value1&key2=value2&key3=value3"

Adding Path Segments

url = URL("https://www.example.com/path").add(path="subpath")
print(url.path)  # "/path/subpath"
print(str(url))  # "https://www.example.com/path/subpath"

Adding a Fragment

url = URL("https://www.example.com/path").add(fragment="section1")
print(url.fragment)  # "section1"
print(str(url))      # "https://www.example.com/path#section1"

Modifying Netloc (Host, Userinfo, Port)

from escudeiro.url import Netloc

url = URL("https://www.example.com/path").add(netloc="www.example2.com")
print(url.netloc)  # "www.example2.com"
print(str(url))    # "https://www.example2.com/path"

url = URL("https://www.example.com/path").add(
    netloc_obj=Netloc.from_args(
        host="www.example2.com",
        username="username",
        password="password",
    )
)
print(url.netloc)  # "username:password@www.example2.com"
print(str(url))    # "https://username:password@www.example2.com/path"

url = URL("https://www.example.com/path").add(
    netloc_obj=Netloc.from_args(host="www.example2.com", port=8080)
)
print(url.netloc)  # "www.example2.com:8080"
print(str(url))    # "https://www.example2.com:8080/path"

Composing Multiple Components

url = URL("https://www.example.com/path?key1=value1").add(
    path="subpath",
    query={"key2": "value2", "key3": "value3"},
    fragment="section1",
    netloc_obj=Netloc.from_args(
        host="www.example2.com",
    username="username",
    password="password",
    port=8080,
        )
    )
    print(url.path)      # "/path/subpath"
    print(url.query)     # "key1=value1&key2=value2&key3=value3"
    print(url.fragment)  # "section1"
    print(url.netloc)    # "username:password@www.example2.com:8080"
    print(str(url))
    # "https://username:password@www.example2.com:8080/path/subpath?key1=value1&key2=value2&key3=value3#section1"

Immutability and Copying

All operations on URL objects return new instances. You can safely copy and compare URLs:

url = URL("https://www.example.com/path?key1=value1").add(
    query={"key2": "value2", "key3": "value3"}
)
url2 = url.copy()
assert url2 is not url
assert url2 == url

API Reference

URL class

  • Construction: URL(str_or_url)
  • Properties: .scheme, .netloc, .path, .query, .fragment
  • Methods:
    • .add(...): Return a new URL with updated components (path, query, fragment, netloc, netloc_obj)
    • .copy(): Return a new identical URL instance
    • .encode(): Return the URL as a string

Netloc, Path, Query, Fragment

  • Helper classes for manipulating respective URL components.
  • Netloc.from_args(host, username=None, password=None, port=None): Construct a netloc string from components.
  • Path, Query, and Fragment can be used similarly for their respective components.

Notes

  • All modifications are immutable and chainable.
  • Query parameters can be provided as dicts or strings.
  • Use netloc_obj for advanced netloc construction (user, password, port).
  • The API is type-safe and works well with dataclasses.

See Also