Yet another URL library - comprehensive URL parsing and manipulation for Python
Methods for creating modified versions of URLs by changing individual components. All URL objects are immutable, so modification methods return new URL instances rather than modifying the original.
Replace individual URL components with new values while preserving other components.
def with_scheme(self, scheme: str) -> "URL":
"""
Return URL with new scheme.
Args:
scheme (str): New scheme (http, https, ftp, etc.)
Returns:
URL: New URL with updated scheme
Raises:
ValueError: If scheme is invalid
"""
def with_user(self, user: str | None) -> "URL":
"""
Return URL with new user component.
Args:
user (str, optional): Username for authentication, None to remove
Returns:
URL: New URL with updated user component
"""
def with_password(self, password: str | None) -> "URL":
"""
Return URL with new password component.
Args:
password (str, optional): Password for authentication, None to remove
Returns:
URL: New URL with updated password component
"""
def with_host(self, host: str) -> "URL":
"""
Return URL with new host.
Args:
host (str): New hostname or IP address
Returns:
URL: New URL with updated host
Raises:
ValueError: If host is invalid
"""
def with_port(self, port: int | None) -> "URL":
"""
Return URL with new port.
Args:
port (int, optional): Port number, None to remove explicit port
Returns:
URL: New URL with updated port
Raises:
ValueError: If port is out of valid range (1-65535)
"""
def with_path(self, path: str, *, encoded: bool = False,
keep_query: bool = False, keep_fragment: bool = False) -> "URL":
"""
Return URL with new path.
Args:
path (str): New path component
encoded (bool): Whether path is already encoded
keep_query (bool): Whether to preserve existing query parameters
keep_fragment (bool): Whether to preserve existing fragment
Returns:
URL: New URL with updated path
"""
def with_fragment(self, fragment: str | None) -> "URL":
"""
Return URL with new fragment.
Args:
fragment (str, optional): Fragment identifier, None to remove
Returns:
URL: New URL with updated fragment
"""Modify filename and extension components of the URL path.
def with_name(self, name: str, *, keep_query: bool = False,
keep_fragment: bool = False) -> "URL":
"""
Return URL with new filename component.
Args:
name (str): New filename (last path segment)
keep_query (bool): Whether to preserve existing query parameters
keep_fragment (bool): Whether to preserve existing fragment
Returns:
URL: New URL with updated filename
Raises:
ValueError: If name contains path separators
"""
def with_suffix(self, suffix: str, *, keep_query: bool = False,
keep_fragment: bool = False) -> "URL":
"""
Return URL with new file extension.
Args:
suffix (str): New file extension (should include leading dot)
keep_query (bool): Whether to preserve existing query parameters
keep_fragment (bool): Whether to preserve existing fragment
Returns:
URL: New URL with updated file extension
"""Replace, extend, or modify query parameters. See Query Parameter Handling for detailed query manipulation methods.
def with_query(self, query: Query = None, **kwargs: QueryVariable) -> "URL":
"""
Return URL with completely new query parameters.
Args:
query (Query, optional): Query parameters as dict, sequence, or string
**kwargs: Query parameters as keyword arguments
Returns:
URL: New URL with updated query parameters
"""
def extend_query(self, query: Query = None, **kwargs: QueryVariable) -> "URL":
"""
Return URL with additional query parameters.
Args:
query (Query, optional): Additional query parameters
**kwargs: Additional query parameters as keyword arguments
Returns:
URL: New URL with extended query parameters
"""
def update_query(self, query: Query = None, **kwargs: QueryVariable) -> "URL":
"""
Return URL with updated query parameters (merge with existing).
Args:
query (Query, optional): Query parameters to update
**kwargs: Query parameters as keyword arguments
Returns:
URL: New URL with updated query parameters
"""
def without_query_params(self, *query_params: str) -> "URL":
"""
Return URL without specified query parameters.
Args:
*query_params (str): Names of query parameters to remove
Returns:
URL: New URL with specified parameters removed
"""Convenient operators for common URL modifications.
def __truediv__(self, name: str) -> "URL":
"""
Join URL with path component using / operator.
Args:
name (str): Path component to append
Returns:
URL: New URL with appended path component
"""
def __mod__(self, query: Query) -> "URL":
"""
Add query parameters using % operator.
Args:
query (Query): Query parameters to add
Returns:
URL: New URL with added query parameters
"""from yarl import URL
base_url = URL('https://example.com:8080/api/v1/users?limit=10#section')
# Modify individual components
https_url = base_url.with_scheme('https')
new_host = base_url.with_host('api.example.com')
std_port = base_url.with_port(None) # Remove explicit port
new_path = base_url.with_path('/api/v2/users')
no_fragment = base_url.with_fragment(None)
print(new_host) # https://api.example.com:8080/api/v1/users?limit=10#sectionfrom yarl import URL
url = URL('https://example.com/api')
# Add authentication
auth_url = url.with_user('admin').with_password('secret')
print(auth_url) # https://admin:secret@example.com/api
# Remove authentication
no_auth = auth_url.with_user(None).with_password(None)
print(no_auth) # https://example.com/apifrom yarl import URL
file_url = URL('https://example.com/documents/report.pdf')
# Change filename
new_file = file_url.with_name('summary.pdf')
print(new_file) # https://example.com/documents/summary.pdf
# Change extension
txt_file = file_url.with_suffix('.txt')
print(txt_file) # https://example.com/documents/report.txt
# Change path entirely
api_url = file_url.with_path('/api/v1/data')
print(api_url) # https://example.com/api/v1/datafrom yarl import URL
api_url = URL('https://api.example.com/users?active=true&limit=10')
# Replace all query parameters
new_query = api_url.with_query({'status': 'pending', 'page': 1})
print(new_query) # https://api.example.com/users?status=pending&page=1
# Add query parameters
extended = api_url.extend_query({'sort': 'name'})
print(extended) # https://api.example.com/users?active=true&limit=10&sort=name
# Update specific parameters
updated = api_url.update_query({'limit': 50, 'offset': 20})
print(updated) # https://api.example.com/users?active=true&limit=50&offset=20
# Remove parameters
cleaned = api_url.without_query_params('limit', 'active')
print(cleaned) # https://api.example.com/usersfrom yarl import URL
base_url = URL('https://api.example.com')
# Use / operator to append paths
users_url = base_url / 'users' / '123' / 'profile'
print(users_url) # https://api.example.com/users/123/profile
# Use % operator to add query parameters
query_url = users_url % {'include': 'permissions', 'format': 'json'}
print(query_url) # https://api.example.com/users/123/profile?include=permissions&format=json
# Chain operations
final_url = (base_url
/ 'api' / 'v1' / 'users'
% {'active': True, 'limit': 50}
).with_fragment('results')
print(final_url) # https://api.example.com/api/v1/users?active=True&limit=50#resultsfrom yarl import URL
# Chain multiple modifications
result = (URL('http://old.example.com:8080/old/path?old=param')
.with_scheme('https')
.with_host('new.example.com')
.with_port(None)
.with_path('/new/api/endpoint')
.with_query({'version': '2', 'format': 'json'})
.with_fragment('response'))
print(result) # https://new.example.com/new/api/endpoint?version=2&format=json#responseInstall with Tessl CLI
npx tessl i tessl/pypi-yarl