A tiny project to avoid a major head ache.

This commit is contained in:
Leo Vasanko 2025-07-03 10:20:21 -06:00
commit 927148ee74
4 changed files with 100 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
__pycache__/
dist/
.*
!.gitignore

40
README.md Normal file
View File

@ -0,0 +1,40 @@
# URL-safe Base64 for Python
A simple module for encoding without padding, fixing Python standard library's flaws.
Replaces the standard library's `base64.urlsafe_b64encode` and `base64.urlsafe_b64decode` with a cleaner implementation that returns strings instead of bytes and avoids unnecessary padding.
## Features
- **URL safe**: Uses only characters that are safe for URLs and filenames
- **No padding**: Removes trailing `=` characters for cleaner output
- **String output**: Returns proper strings instead of bytes (unlike Python's standard library)
- **Fast**: Based on Python stdlib, with constant-time padding restoration
## Installation
```sh
pip install b64url
```
Or for your project using [uv](https://docs.astral.sh/uv/):
```sh
uv add b64url
```
## Usage
```python
import b64url
text = b64url.enc(bytes(4)) # Returns str "AAAAAA"
data = b64url.dec(text) # Recovers the bytes
```
### `enc(data: bytes) -> str`
Base64 encode bytes to a URL-safe string without padding.
### `dec(s: str) -> bytes`
Decode URL-safe Base64 into bytes. Padding optional.

26
b64url.py Normal file
View File

@ -0,0 +1,26 @@
"""URL-safe Base64 encoding without padding.
This format uses only characters that are safe for URLs, filenames etc.
Refer to Python's urlsafe_b64encode and base64.urlsafe_b64decode for more details.
Fixes Python base64 module's faults:
- Padding "==" is optional and not produced by b64url.enc
- Base64 type is str (stdlib is retarded and uses bytes)
- Otherwise identical to urlsafe_b64encode/urlsafe_b64decode
"""
from base64 import urlsafe_b64decode as _decode
from base64 import urlsafe_b64encode as _encode
__all__ = ["enc", "dec"]
def enc(data: bytes) -> str:
"""Base64 encode bytes to a URL-safe string without padding."""
return _encode(data).decode("ascii").rstrip("=")
def dec(s: str) -> bytes:
"""Decode URL-safe Base64 into bytes. Padding optional."""
# Testing whether needs padding is slower, this is the fastest way and constant time.
return _decode(s + "=" * (4 - (len(s) % 4)))

30
pyproject.toml Normal file
View File

@ -0,0 +1,30 @@
[project]
name = "b64url"
version = "1.0.0"
description = "Base64 encoding without Python's base64 flaws. No padding, str types."
readme = "README.md"
requires-python = ">=3.8"
dependencies = []
authors = [
{name = "Leo Vasanko"},
]
keywords = ["base64", "base64url", "urlsafe_b64encode", "urlsafe_b64decode"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"License :: Public Domain",
"Programming Language :: Python :: 3",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[project.urls]
Homepage = "https://github.com/LeoVasanko/b64url-python"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["b64url.py"]