MAC Address Generator — Python source
Generate random EUI-48 MAC addresses with a chosen separator, optional OUI prefix, uppercase formatting, and a locally-administered flag. Runs entirely in your browser with crypto-grade randomness.
This is the Python implementation — the same logic the interactive tool runs, in a shareable, citable form.
"""mac-address-generator — random EUI-48 MAC address generator.
Language: Python (3.9+, standard library only)
Source: CosmoDev polyglot showcase port of the MAC Address Generator tool,
ported from src/lib/mac-generator.ts (the canonical TypeScript
implementation), kept in lock-step with the Go twin at
cli/mac-address-generator/mac-address-generator.go.
License: display source — part of CosmoDev's polyglot tool pages.
Design goals:
- Pure + deterministic; raises only on a malformed OUI (never on randomness).
- Functionally equivalent to the TS reference: same inputs -> same outputs.
- Self-contained: stdlib only (no pip packages). The default RNG uses
``os.urandom`` — Python's cryptographic random source.
API note: this port mirrors the TS canonical lib's public API, the deterministic,
RNG-injectable superset of the Go twin's. The Go twin draws from crypto/rand
directly (non-injectable), so its own suite asserts only structural properties
(regex shape, OUI prefix, U/L bit). Like the TS lib, this port accepts an
injected ``rng`` returning a float in [0, 1), letting the showcase tests below
assert exact MAC strings.
Pipeline: (optional OUI -> 3 octets) -> 3 random octets -> (force U/L bit) ->
join 6 octets as %02x with the separator -> (uppercase). A malformed OUI (not
6 hex digits after stripping non-hex chars) raises ValueError.
"""
from __future__ import annotations
import os
import re
from dataclasses import dataclass
from typing import Callable, Optional
__all__ = ["generate_mac", "MacOptions"]
def _default_rng() -> float:
"""A 32-bit draw from ``os.urandom`` mapped to [0, 1) — mirrors the TS
default ``crypto.getRandomValues(new Uint32Array(1))[0] / 2**32``."""
return int.from_bytes(os.urandom(4), "big") / 2 ** 32
def _hex(n: int) -> str:
"""Two-digit lowercase hex, mirroring TS ``n.toString(16).padStart(2, '0')``."""
return format(n, "02x")
@dataclass
class MacOptions:
"""Options mirror the TS ``MacOptions`` interface.
Every field defaults to the TS default, so callers construct incrementally
with keyword args.
"""
separator: Optional[str] = None
"""Joining chars. ``None`` -> default ':'. Empty string concatenates."""
uppercase: bool = False
"""Uppercase the hex letters in the result."""
oui: Optional[str] = None
"""Optional 6-hex-digit OUI prefix (separators tolerated, stripped first)."""
locally_administered: bool = False
"""Force the U/L bit (0x02) of the first octet."""
rng: Callable[[], float] = _default_rng
"""Random source returning a float in [0, 1). Defaults to a secure draw."""
_NON_HEX_RE = re.compile(r"[^0-9a-fA-F]")
def generate_mac(opts: Optional[MacOptions] = None) -> str:
"""Build a random EUI-48 MAC address.
The Python twin of ``generateMac()`` in src/lib/mac-generator.ts. Raises
``ValueError`` on a malformed OUI; never raises otherwise.
"""
if opts is None:
opts = MacOptions()
sep = opts.separator if opts.separator is not None else ":"
octets: list[int] = []
# Octets 0..2 — OUI (validated) or random. TS `if (opts.oui)` truthiness:
# None and "" both take the random path.
if opts.oui:
clean = _NON_HEX_RE.sub("", opts.oui)
if len(clean) != 6:
raise ValueError(f'OUI must be 6 hex digits, got "{opts.oui}"')
octets.append(int(clean[0:2], 16))
octets.append(int(clean[2:4], 16))
octets.append(int(clean[4:6], 16))
else:
octets.append(int(opts.rng() * 256))
octets.append(int(opts.rng() * 256))
octets.append(int(opts.rng() * 256))
# Octets 3..5 — always random.
octets.append(int(opts.rng() * 256))
octets.append(int(opts.rng() * 256))
octets.append(int(opts.rng() * 256))
if opts.locally_administered:
octets[0] = (octets[0] & 0b11111101) | 0b00000010 # set U/L bit, clear multicast
mac = sep.join(_hex(o) for o in octets)
if opts.uppercase:
mac = mac.upper()
return mac
# ---------- showcase tests (mirror src/lib/mac-generator.test.ts) ----------
# Run: python python.py
if __name__ == "__main__":
assert generate_mac(MacOptions(rng=lambda: 0.0)) == "00:00:00:00:00:00"
# separators: dash and concatenate
assert generate_mac(MacOptions(rng=lambda: 0.0, separator="-")) == "00-00-00-00-00-00"
assert generate_mac(MacOptions(rng=lambda: 0.0, separator="")) == "000000000000"
# floor(0.7 * 256) == 179 == 0xb3
assert generate_mac(MacOptions(rng=lambda: 0.7, uppercase=True)) == "B3:B3:B3:B3:B3:B3"
# OUI prefix (embedded separators stripped)
assert generate_mac(MacOptions(rng=lambda: 0.0, oui="aa-bb-cc")) == "aa:bb:cc:00:00:00"
# locally administered U/L bit: floor(0.5 * 256) == 0x80 -> 0x82
assert generate_mac(MacOptions(rng=lambda: 0.5, locally_administered=True)) == "82:80:80:80:80:80"
# malformed OUI -> ValueError
try:
generate_mac(MacOptions(rng=lambda: 0.0, oui="abc"))
raise AssertionError("expected ValueError for short OUI")
except ValueError:
pass
print("ok")
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →