Skip to content

uuidhash — UUID v5

Every example on this page starts here

import polars as pl
import polars_hash as plh

Deterministic UUID version 5, on pl.Expr as .uuidhash.

A v5 UUID is a SHA-1 digest of a namespace UUID and a name, in UUID format. The result is deterministic: the same namespace and the same name always give the same UUID, so a v5 UUID is a key for a value you have. A null input gives a null output.

uuid5

uuid5(namespace: UUIDNamespace | str = DNS) -> Expr

Make a UUID v5 from a Utf8 or Binary column.

Parameters:

Name Type Description Default
namespace UUIDNamespace | str

A standard namespace: "dns", "url", "oid" or "x500". Uppercase and lowercase letters are equivalent. Every other string is a custom namespace UUID, and two different namespaces give two different UUIDs for the same input.

DNS

Returns:

Type Description
Expr

Utf8, the 36-character format with hyphens.

Raises:

Type Description
ComputeError

namespace is null (Namespace must be provided), or it is neither a standard name nor a correct UUID (Invalid namespace '{value}': {reason}).

Examples:

>>> df = pl.DataFrame({"literal": ["hello", None, "world"]})
>>> df.select(plh.col("literal").uuidhash.uuid5()).to_series().to_list()
['9342d47a-1bab-5709-9869-c840b2eac501', None, 'b3a4c24e-f57a-5448-b81b-a643f6768036']

A custom namespace:

>>> tenant = "0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0"
>>> df.select(plh.col("literal").uuidhash.uuid5(tenant)).item(0, 0)
'f9f6bc57-bc58-5993-8b8d-ee0ddf417610'

uuid5_concat

uuid5_concat(other: Expr, default: str | None = None) -> Expr

Concatenate two Utf8 columns and make a UUID v5 in the DNS namespace.

Use this to make a key from two columns with one expression, in place of a concat_str and a uuid5.

The two columns are not equivalent. A null in the first column gives null. A null in other gives the UUID of the first value and default, or of the first value alone when default is None.

Parameters:

Name Type Description Default
other Expr

The second column, which polars-hash puts after the first. It must be Utf8, and polars-hash casts it to Utf8 first if you set default.

required
default str | None

The value that replaces a null in other. With None, a null in other becomes an empty string.

None

Returns:

Type Description
Expr

Utf8.

Raises:

Type Description
ComputeError

default is null (Default value may not be null).

Note

This expression adds no separator, so ("ab", "c") and ("a", "bc") give the same UUID. If your data can have this condition, make the key with a separator that the data does not contain, with concat_str: plh.concat_str("id", "side", separator="|").uuidhash.uuid5(). That form also lets you select the namespace.

Examples:

>>> df = pl.DataFrame({"id": ["abc-123"], "side": ["a"]})
>>> df.select(plh.col("id").uuidhash.uuid5_concat(pl.col("side"))).item()
'e89d330c-f123-519c-a7a1-e48e46f30ccf'

default gives a null in other the same result as the value itself:

>>> df = pl.DataFrame(
...     {"id": ["abc-123"], "side": pl.Series([None], dtype=pl.Utf8)}
... )
>>> df.select(
...     plh.col("id").uuidhash.uuid5_concat(pl.col("side"), default="a")
... ).item()
'e89d330c-f123-519c-a7a1-e48e46f30ccf'

UUIDNamespace

Bases: str, Enum

The four RFC 4122 namespaces for a UUID v5.

This is a str enum, so a member and its value are equivalent arguments. DNS names a fully qualified domain name, URL a URL, OID an ISO object identifier, and X500 an X.500 distinguished name.

Examples:

>>> df = pl.DataFrame({"foo": ["https://example.com"]})
>>> df.select(plh.col("foo").uuidhash.uuid5(plh.UUIDNamespace.URL)).item()
'4fd35a71-71ef-5a55-a9d9-aa75c889a6d0'
>>> df.select(plh.col("foo").uuidhash.uuid5("url")).item()
'4fd35a71-71ef-5a55-a9d9-aa75c889a6d0'