directedstructure
Infer communities, hierarchies, and their connection in directed graphs
Maximilian Jerdee, Elizabeth Bruch, Mark Newman
This Python package uses Bayesian inference to identify communities and hierarchies of nodes in a directed network, as well as measure the interaction between those structures.
We model community structure using a stochastic block model, hierarchy structure with a Bradley-Terry model, and their interaction according to our work (link forthcoming).
Installation
pip install directedstructure
Or build locally by cloning this repository and running
pip install .
in the base directory (requires a C++ compiler).
Usage
The public API has three objects: Config, fit, and Result.
Load a network
import directedstructure as ds
import networkx as nx
G = nx.read_gml("examples/data/networks/friends.gml")
Edges may carry a type attribute ('dominant' or 'neutral') to distinguish directed pairwise comparisons from symmetric ties. If no type information is provided all edges are treated as dominant.
Configure the model
config = ds.Config(
groups_model="general_canonical", # community structure preset
hierarchy_model="bradley_terry_ties", # auto-selected if omitted
interaction="coupled", # coupling between communities and hierarchy
)
Config is a frozen dataclass — see the API docs for the full list of parameters (mixing variation, degree correction, individual/group depth, etc.).
Run inference
result = ds.fit(
config, G,
num_samples=1000, # posterior samples to collect
sweeps_per_sample=10, # MCMC sweeps between samples
timeout=60.0, # wall-clock limit in seconds
seed=42,
)
Inspect results
# A concise summary is printed by the result itself
print(result)
# directedstructure.Result(n=62, samples=1000, mean_groups=3.2, mdl=412.100)
# Network-level posterior summary: columns parameter, mean, std, hdi_lo, hdi_hi
# Includes ICC (intraclass correlation) and sigma_T.
# Computed in C++ without materialising the full samples DataFrame.
npdf = result.network_properties_df() # default 90% HDI
npdf90 = result.network_properties_df(prob=0.90)
icc_row = npdf[npdf["parameter"] == "ICC"].iloc[0]
print(f"ICC = {icc_row['mean']:.3f} 90% HDI [{icc_row['hdi_lo']:.3f}, {icc_row['hdi_hi']:.3f}]")
# Per-node posterior summary: columns node, score_mean, score_std, group, group_score_mean
# For n ≤ 3000 uses the consensus partition (posterior summary);
# for larger networks falls back to the MDL partition with a warning.
node_df = result.node_properties_df() # auto
node_df = result.node_properties_df(partition="consensus") # always consensus
node_df = result.node_properties_df(partition="mdl") # always MDL (free)
print(node_df.sort_values("score_mean", ascending=False).head())
# Minimum description length value (model comparison)
print(result.mdl_value)
# n×n co-assignment frequency matrix (posterior)
comatrix = result.coincidence_matrix()
# Full posterior samples DataFrame (all parameters + per-node groups/scores)
samples_df = result.samples_df()
# Posterior-predictive probability of each directed outcome between two nodes.
# Returns {"a_to_b": ..., "tie": ..., "b_to_a": ...}, values sum to 1.
p = result.direction_probabilities("Spain", "Morocco")
# Set ties_allowed=False for standard Bradley-Terry (no tie term).
p = result.direction_probabilities("Spain", "Morocco", ties_allowed=False)
# {"a_to_b": ..., "b_to_a": ...}
Visualization
import matplotlib.pyplot as plt
# Node scores ranked within each inferred community (±1 std error bars,
# group mean line, communities labeled G1/G2/…)
fig, ax = ds.plot_node_properties(result)
plt.savefig("node_scores.png")
# Adjacency matrix of G reordered by inferred community, with colored
# community strips on the top and left edges.
# G can be any graph — it does not have to be the graph used in fit().
fig, ax = ds.plot_adjacency_matrix(result, G, cmap="Greens", title="Network")
plt.savefig("adjacency.png")
# Compose both panels side by side
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
ds.plot_node_properties(result, ax=axes[0])
ds.plot_adjacency_matrix(result, G, ax=axes[1])
fig.tight_layout()
plt.savefig("combined.png")
fig, ax = ds.plot_MCMC_entropy(result) # convergence diagnostic
Export the graph with inferred attributes for use in Gephi or other tools:
ds.write_gml_with_inferences(G, "output.gml", result)
Fixing model components
Pass fixed values in Config to test submodels. For example, to fix group structure from node attributes and infer hierarchy only:
config = ds.Config(group_attribute="department", interaction="independent")
result = ds.fit(config, G)
Or fix the number of groups:
config = ds.Config(num_groups=4)
result = ds.fit(config, G)
Parallel tempering
For complex posteriors, enable parallel tempering:
result = ds.fit(config, G, num_tempering_chains=4, beta=1.0)
Further usage examples can be found in the examples/python/ directory of the
repository and the package documentation.
Metadata
Release files for directedstructure 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| directedstructure-0.3.1.tar.gz | 415.0 kB | Details |
Built distributions (wheels)
Total release size: 9.0 MB
Release files / directedstructure-0.3.1.tar.gz
| Download URL | directedstructure-0.3.1.tar.gz |
|---|---|
| Size | 415.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b05237a3ee4bcb95b059ba703382e29aa2d0e7b6177e57f2b79c33f820364345
|
|
BLAKE2b-256 checksum How to use checksums |
2d9869833c064ff40d2ce9728bfe3b673d3d99e9c5edcfe04de5526315b11994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp313-cp313-win_amd64.whl
| Download URL | directedstructure-0.3.1-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 273.6 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
484a76f55d19af4a53b16bca8d99f68c5ec6d0f2c4bd1f79286eabb33ce64173
|
|
BLAKE2b-256 checksum How to use checksums |
af4bcd72a7c4a19e6d4947e5f3903e2b7f28987d9dc94ed843351eafa268aadf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl
| Download URL | directedstructure-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.13 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
404dfd71d44cd1a05cc939c689f90f6837f3f58f77def581020886cfee1065a7
|
|
BLAKE2b-256 checksum How to use checksums |
b1c148bed5d13124d8fd94dcd912b709b47296f65410ce50c7b036283664ebb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | directedstructure-0.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 315.9 kB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
f14368ac8d82be7dbce8362eb59a9d590593a28272c0aa6cabfc778ed8f8e1be
|
|
BLAKE2b-256 checksum How to use checksums |
2a6369c8ea31fe7c7a365f3cea493e0b4a49e8d1f738d91cdab76ec0f3e5de5d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | directedstructure-0.3.1-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 246.3 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7ba38a0aa720e552ba93dbaa476b18934d31dc1179ac78c7b00519a4993da4cd
|
|
BLAKE2b-256 checksum How to use checksums |
9352bdd3164334008459e30bc72e659d96159f432c59f295fe34562b9d7d6686
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp312-cp312-win_amd64.whl
| Download URL | directedstructure-0.3.1-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 273.5 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c9be576f52c1b4afae63945c0b77e99344339bb7813becc9d59b397429e7c3bd
|
|
BLAKE2b-256 checksum How to use checksums |
258bea927f396281c6433931186b054b04ac86c1e7719b4477ec292106faaa00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl
| Download URL | directedstructure-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.12 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
e354d6d2b98442561de9fc3074ac35a63f3a52ddadaea25f24e7bf369f61c3e1
|
|
BLAKE2b-256 checksum How to use checksums |
d854bc7e66cfbc58ef9189393b189bc424caf18f2e917861eb6395c5c65a2db0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | directedstructure-0.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 315.9 kB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
9f63d69d89814cc6c266f1598ceda7c074b1643d5b27d7f97cdca432135246cc
|
|
BLAKE2b-256 checksum How to use checksums |
a02a57ea6b5976673cde8806e760ccef9e9c73c5413279750647b5a815a929c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | directedstructure-0.3.1-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 246.2 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8136ca2540c793009b9ded6c3e15bc5691708fb7bb6bbfe28da18ddfecc18e18
|
|
BLAKE2b-256 checksum How to use checksums |
f3b7b4cc82dd609ea480ee5a6956fe3927b8e945004d5669d131b26befe15d9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp311-cp311-win_amd64.whl
| Download URL | directedstructure-0.3.1-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 268.4 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
2b124b1c35e697e666fb4d8b310452e7f6f5742a67f7318c2aa74376944a3fc6
|
|
BLAKE2b-256 checksum How to use checksums |
8e1b6c83c0d3e9e050588d800373535336d86db7c217f85ff35c6f2ca5cfc6e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl
| Download URL | directedstructure-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.11 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
eff0359d727c4a12238d4b697c02a9a16d21928e2e1feab248a6fc25ef4e5022
|
|
BLAKE2b-256 checksum How to use checksums |
a60f798ed4e18203690d04c31c0164fe6e873be8961203a4c9a386ef6bc015c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | directedstructure-0.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 314.9 kB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
7270e855f3f61b23b457e2c09f00969607d8f119809afcd0a56b668258de3d10
|
|
BLAKE2b-256 checksum How to use checksums |
6e940a0f8c18b985e1edebf7d0887138940b67f7df50494761c3165645f0b23b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | directedstructure-0.3.1-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 245.2 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
022c1fff54d8bad066536874afb29a1fe03b9437ec1d386d42f647d9f4beaae8
|
|
BLAKE2b-256 checksum How to use checksums |
2ddb26e2655427542b6bc675d83be7c49e7ba43585f7f0e798339eb41f0cf837
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp310-cp310-win_amd64.whl
| Download URL | directedstructure-0.3.1-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 267.6 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
b668ccf41ff70e610d862e78a0a51a9e27ab6cedbbb99f7f302fda2471b45158
|
|
BLAKE2b-256 checksum How to use checksums |
3c2fb7411052b16b17bc3ecdbea5f56db14e7828e6b2697c13e6203beb2355e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp310-cp310-musllinux_1_2_x86_64.whl
| Download URL | directedstructure-0.3.1-cp310-cp310-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
39878de9da8b51d7f6fad52d704ecf84c99881600bf6a844f1923d53f1179c55
|
|
BLAKE2b-256 checksum How to use checksums |
dbd8c0b5e917face4b37deba73d7ba063eaf6ff2cd8760844e381319df19c517
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | directedstructure-0.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 313.2 kB |
| Tags | CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
19bea19af8a5af011ded4f3f70a3a9825d21f9bf933d905b633d1aa4014b8038
|
|
BLAKE2b-256 checksum How to use checksums |
3efcbe802db0a14dbe2a631564404e81a8d13d34637d7b90647f366c360f3e97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / directedstructure-0.3.1-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | directedstructure-0.3.1-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 243.9 kB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
691aa146121db44fdacc80dd11cf4f23ad8058ddcf06e99fa1077e57196311d3
|
|
BLAKE2b-256 checksum How to use checksums |
f4441b69f6a0a147e589131a928fd146a73d147eddc3d97c76275936e28bb6e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log