Skip to main content

structguru

A native structured logging library with a loguru-style API.

Combines a loguru-style API — brace formatting, bind, contextualize, opt, sink management — with a native Rust renderer for maximum performance. Since v1.0, the Rust extension is the default (and only) rendering path; structlog and orjson are no longer dependencies.

Features

  • Loguru-style API — logger.info("User {id} logged in", id=123)
  • Structured JSON output in production (rendered natively in Rust for speed)
  • Pretty colored console output in development
  • Context management — bind() for persistent context, contextualize() for request-scoped context
  • Sentry integration — redacted breadcrumbs/events with raw exception capture available by opt-in
  • stdlib interop — logger.add() sinks can also receive third-party logging records
  • RFC 5424 severity codes included in every log record
  • Native Rust runtime — rendering and output run through the bundled abi3 extension
  • Fully typed — PEP 561 compliant with strict mypy

Native processing:

  • Redaction — mask sensitive fields (passwords, tokens) by key name or regex
  • Sampling — probabilistic and rate-limited log suppression
  • Metrics — extract counters/histograms from log events via callbacks
  • Exception formatting — render exc_info as text or a structured frame dictionary
  • Off-thread logging — native Rust writer with a bounded queue and backpressure
  • OpenTelemetry — automatic trace_id/span_id injection from current span

Framework integrations (optional dependencies):

  • ASGI (FastAPI, Starlette) — request ID, timing, context binding middleware
  • Celery — task context binding and cross-worker context propagation via headers
  • Flask — before/after request hooks with request ID tracking
  • Django — logging dict config builder and request middleware
  • SQLAlchemy — slow query detection and logging
  • gRPC — server interceptor with per-RPC context binding
  • Sentry — forward log events as breadcrumbs/events with configurable severity

Installation

pip install structguru

With optional integrations:

pip install structguru[celery,flask,sentry]  # pick what you need
pip install structguru[all]                   # everything

Available extras: otel, celery, flask, django, sqlalchemy, grpc, sentry, httpx, requests, all.

Quick start

from structguru import Logger, configure, logger

# Configure once at startup
configure(service="myapp", level="DEBUG", format="json")

# Use anywhere
logger.info("Hello {name}", name="world")
# → {"logger":"...","level":"INFO","severity":6,"timestamp":"...","service":"myapp","message":"Hello world"}

# Or choose an explicit module name
log = Logger(name=__name__)

Configuration

Call configure() once at startup. Each call replaces the previous configuration: explicit keywords override environment values, which override built-in defaults. Use update() to retain existing options while changing selected ones:

from structguru import Settings, configure, get_config, update

configure(service="checkout", sensitive_patterns=[r"token=\w+"])
update(otel=True, structured_exceptions=True)  # retains service and redaction
current = get_config()  # Settings, or None after shutdown()

# Applications can load a mapping themselves; no files are read automatically.
settings = Settings.from_mapping({"service": "checkout", "level": "DEBUG"})
configure(settings)  # uses this object instead of environment values

Settings.from_env() resolves environment values without applying them; pass a mapping instead of using the process environment when testing. Settings validates Python values and freezes collections. Native regex compilation and file access are checked when configuring; failure leaves the previous runtime active. Explicit keywords, including None and built-in default values, win over the selected base.

update() never rereads the environment and requires an active runtime. An empty update does nothing. Level-only updates and set_level() preserve queues and rate-limit state; other updates rebuild writers and reset filter state. Snapshots describe configured options, not buffered records, counters, stdlib bridge state, or logger.add() sinks. Those registered sinks survive reconfiguration. Streams and callbacks retain their identity.

Levels accept case-insensitive names (including NOTSET) or non-negative integer thresholds up to 2**63 - 1. Unknown names, booleans and out-of-range integers raise ValueError.

Environment configuration

Variable Default Compatibility fallback
STRUCTGURU_SERVICE app —
STRUCTGURU_LEVEL INFO LOG_LEVEL
STRUCTGURU_TARGET stdout STRUCTGURU_NATIVE_TARGET
STRUCTGURU_FORMAT json —
STRUCTGURU_SAMPLE_RATE 1.0 STRUCTGURU_NATIVE_SAMPLE_RATE
STRUCTGURU_RATE_LIMIT disabled; period defaults to 60 seconds STRUCTGURU_NATIVE_RATE_LIMIT
STRUCTGURU_AUTOCONFIGURE enabled inverse of STRUCTGURU_LEGACY

New names win over their fallbacks; old names remain supported without warnings. Level variables accept a name or a non-negative integer threshold (LOG_LEVEL=10). Rate limits use MAX or MAX/PERIOD, with integer counts and seconds for the period. Autoconfiguration accepts 1/0, true/false, yes/no, or on/off and controls import only. Set it to 0 before import to configure explicitly later. Invalid selected values fail validation; an invalid import-time value must be corrected or autoconfiguration disabled before the application can call configure().

File output, redaction, exceptions and other settings currently use Python configuration. The stdlib bridge retains its separate STRUCTGURU_STDLIB_* options and explicit installer.

Usage

Log levels

from structguru import logger

logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical message")

# Aliases
logger.trace("Maps to DEBUG")
logger.success("Maps to INFO")
logger.warn("Alias for warning")
logger.fatal("Alias for critical")

Brace formatting

Arguments used in str.format placeholders are consumed by formatting (matching loguru behaviour). Extra kwargs that are not in any placeholder are forwarded as structured fields:

from structguru import logger

logger.info("User {user_id} logged in", user_id=42, ip="10.0.0.1")
# message: "User 42 logged in"
# ip: "10.0.0.1"  (extra kwarg kept as structured field)
# user_id is consumed by formatting and not duplicated

The message is formatted whenever positional or keyword arguments are passed, as str.format would ("a }} b" becomes "a } b"); exc_info and stack_info alone do not count, so logger.exception("{{x}}") logs {{x}} like logger.error. Fields named in a nested format spec ("{x:{width}}") are consumed too. A placeholder that names a sensitive key — as the root ({token}) or an attribute or index ({creds[password]}) — is interpolated as [REDACTED]. A mapping, sequence, set, dataclass, or namespace interpolated whole ({creds}) renders with the values under sensitive keys redacted; other objects' own str() text is covered by sensitive_patterns only. The message is positional-only, so message= and self= are ordinary fields. A template that fails to format, or a message whose str() raises, is logged raw or as a placeholder with a one-shot UserWarning; logging calls do not raise for their arguments.

Bound context

from structguru import logger

log = logger.bind(request_id="abc-123", user="alice")
log.info("Processing request")  # includes request_id and user
log.info("Request complete")  # same context carried through

Request-scoped context

from structguru import logger

with logger.contextualize(request_id="abc-123"):
    logger.info("Handling request")  # includes request_id
    do_work()  # any logging inside also gets request_id
# request_id removed automatically

Exception logging

from structguru import logger

try:
    risky_operation()
except Exception:
    logger.exception("Operation failed")  # logs with exc_info at ERROR level

# Or with opt():
logger.opt(exception=True).error("Something went wrong")

Sink management

from structguru import logger

# Add a file sink
handler_id = logger.add("app.log", level="ERROR")

# Add a callable sink
logger.add(lambda msg: send_to_monitoring(msg), level="CRITICAL")

# Remove a specific sink
logger.remove(handler_id)

# Remove all added sinks
logger.remove()

Handler ids are process-wide: any Logger can remove a sink that another one added. Removing an id that names no active sink raises ValueError (a non-integer raises TypeError), as in loguru; remove() without an id removes the sinks added through that logger and its bind()/opt() children. level accepts a name or a non-negative integer up to 2**63 - 1 and raises ValueError for anything else, like configure(level=...). A logging.Handler passed to add() keeps its own level and formatter: its formatter wraps the rendered line, only level gates what it receives, and remove() closes it.

On Unix, new files created by either logger.add(path) or the native rotating file sink are owner-only (0600). Existing files retain their permissions.

All sink forms receive structguru records. They are also registered with the stdlib root logger for third-party records, which arrive raw (unrendered) on that path. Install the stdlib bridge to receive them rendered and redacted instead — while it is installed the raw delivery is suspended, so a sink never sees the same record twice.

Logs emitted inside a sink callback, whether it received a native record or a raw stdlib one, reach the native writer but skip callable and logger.add() sinks, preventing recursive delivery and worker deadlocks. Outside callbacks, logger.remove() waits for producers that already selected the removed sink and for raw stdlib deliveries in progress. Lifecycle calls inside a callback, including a stdlib handler's emit() on the raw path, cannot wait for the worker; previously selected deliveries finish as that worker drains. For native file/stdout mirroring, writer_metrics()["sink_errors"] includes failed destinations even when another destination successfully writes the record.

Native delivery uses the bounded callable queue and is drained on reconfiguration, shutdown(), fork, and interpreter exit. Call structguru.flush() when you need to block until buffered records have actually been written:

import structguru

structguru.logger.info("checkpoint")
structguru.flush()  # returns once the line has reached its sink

Console vs JSON output

format= selects the renderer: "json" (default, production) or "console" (colored, human-readable development output).

from structguru import update

# JSON (production)
update(service="myapp", format="json")
# → {"logger":"...","level":"INFO","severity":6,"timestamp":"...","service":"myapp","message":"..."}

# Console (development) — colored, human-readable
update(service="myapp", format="console")
# → 2026-01-15T12:00:00.123456Z [INFO    ] Hello world

Native processing

Redaction

Mask sensitive fields automatically:

from structguru import update

update(
    sensitive_keys=["password", "token", "ssn"],
    sensitive_patterns=[r"\b\d{3}-\d{2}-\d{4}\b"],
    pattern_replacement="***",
)

Patterns apply to the message, field names, and string values at any depth, and to integers by their decimal digits (a matching integer is emitted as the redacted string). If redaction makes two keys of one map equal, the record keeps one key with the last value.

Patterns run on Rust's linear-time regex engine (no ReDoS), which rejects look-around and backreferences at update() time. Most look-behinds rewrite as capture groups — (?<=password=)\S+ becomes (password=)\S+ with pattern_replacement="$1[REDACTED]", so the prefix is re-emitted and the secret is replaced (password=hunter2 → password=[REDACTED]). Put the capture group around the part you want to keep, never around the secret. For patterns that can't be rewritten, allow_backtracking_patterns=True opts them into a bounded backtracking engine: look-around and backreferences then work as written, at the cost of the linear-time guarantee for those patterns. If a value ever exceeds the backtrack limit, it is redacted entirely (fail-closed) rather than emitted unchecked.

from structguru import update

update(
    sensitive_patterns=[r"(?<=password=)\S+"],
    allow_backtracking_patterns=True,
)

Sampling & rate limiting

Suppress noisy logs:

from structguru import update

update(sample_rate=0.1, rate_limit_max=5, rate_limit_period=60)

Metric extraction

Derive metrics from log events:

from structguru import MetricProcessor, update

metrics = MetricProcessor()
metrics.counter("user.login", lambda ed: login_counter.inc())
metrics.histogram("db.query", "duration_ms", lambda v, ed: query_hist.observe(v))

update(metric_processor=metrics)

Exception formatting

Render exceptions as JSON-serializable dictionaries:

from structguru import update

update(structured_exceptions=True, exception_max_frames=20)

exception_max_frames=0 omits traceback frames entirely. Negative frame and local-representation limits are rejected during configuration.

Formatted tracebacks (the default) carry CPython's per-frame position markers, the ~~~^^^ lines, and on Python 3.11+ computing them is most of the cost of logger.exception(). exception_carets=False omits them, which formats a traceback about five times faster and matches what CPython prints under PYTHONNODEBUGRANGES=1:

from structguru import update

update(exception_carets=False)

OpenTelemetry correlation

Inject trace context into every log event:

from structguru import update

update(otel=True)  # no-op injection when opentelemetry-api is absent

Non-blocking logging

Since v1.0, log I/O is offloaded to a background thread by default. The native Rust writer uses a bounded 8192-record queue and waits for space while it is open. Set overflow="drop" to favor caller latency, or explicitly pass maxsize=0 only when an unbounded queue is acceptable.

Native runtime

structguru ships a required Rust extension that renders and enqueues logging natively, off-thread. It is auto-enabled at import time, and importing the package without the extension raises RuntimeError. The runtime does not depend on orjson; exotic values (datetime, UUID, Enum, dataclasses) are converted natively in Rust.

A field value the renderer cannot represent never fails the record. It is replaced by a marker so the message, level, remaining fields, and exception traceback still ship:

  • <unsupported: WSGIRequest> for any other object (Decimal, bytes, set, Path, request objects, ...). The marker names the type only: structguru never calls str()/repr() on an arbitrary object or reads its attributes, so nothing it holds can leak into a log line.
  • <cycle: dict> for a container that refers back to itself.
  • <max depth exceeded> beyond 64 levels of nesting.

Integers outside the 64-bit range are written as JSON numbers, int and float subclasses (such as numpy.float64) are written by value, non-string mapping keys are rendered as strings ({200: 3} becomes {"200": 3}), and each unpaired surrogate in text becomes one U+FFFD while a split surrogate pair decodes to its character. Keys that render to the same text never produce duplicate JSON keys: the later value wins at the earlier key's position. Markers are redacted like any other string. The policy applies to native logger fields and to extra= fields bridged from the standard library alike.

import structguru

# Native mode is already on. Logger calls route through the Rust renderer.
structguru.logger.info("order {id} accepted", id=987)
# → JSON line written to stdout by a background writer thread

No configuration is required for the default JSON-to-stdout behavior. Call configure(...) to customize the renderer, filtering, or sinks.

import structguru

structguru.configure(service="myapp", level="INFO", file_path="/var/log/app.log")
structguru.logger.bind(request_id="abc").info("order {id} accepted", id=987)
# → JSON line written to /var/log/app.log by a background writer thread

Import-time configuration and configure() without a Settings object honor environment variables:

STRUCTGURU_LEVEL=INFO STRUCTGURU_SERVICE=myapp python -m myapp

Invalid native environment values fail import with an actionable exception. This prevents a deployment from starting while the native-only logging path is disabled.

Public API:

Symbol Purpose
configure(...) Replace rendering, filtering, redaction, and output settings.
Settings Validate reusable options; construct from Python values, a mapping, or the environment.
get_config() Return configured options, or None when shut down.
update(...) Change selected active options without rereading the environment.
shutdown() Stop the writer; logging is disabled until configure() is called.
set_level(level) Adjust the level threshold at runtime.
writer_metrics() Current writer counters (enqueued/written/dropped/depth/...) plus filter counters when active; None after shutdown.
lifecycle_metrics() Cumulative native deliveries rejected by closed writers; available after shutdown and across reconfiguration.
is_available() Compatibility helper; always True once the package has imported, because a missing extension fails import.

Behavior notes:

  • Overflow: the default maxsize=8192 uses overflow="block" to wait for queue space. Use overflow="drop" for drop-newest behavior with metrics and rate-limited warnings. maxsize=0 explicitly opts into an unbounded queue.
  • Redaction, level filtering, exceptions, and OpenTelemetry injection are supported natively; redaction covers the message, field names, string values, and integers at any depth before rendering or Sentry export, and message placeholders that name a sensitive key are interpolated as [REDACTED] (see the redaction API reference for the exact coverage). sensitive_keys overrides the default redaction keys. Rust's linear-time regex engine rejects backreferences and look-around with ValueError at configuration time.
  • Sampling & rate limiting (sample_rate, rate_limit_max, rate_limit_period) are applied as native pre-render filters — dropped records cost zero rendering. sampled and rate_limited counters are distinct from the transport dropped counter. sample_max_level restricts sampling to records at or below that level; more severe records always pass.
  • Metric hooks (metric_processor=...) invoke a structlog-style processor (e.g. MetricProcessor) for every kept record on the caller's thread, with (None, method, {"event": message, **fields}); the message stays in "event" even when a field has that name. Dropped records (level/sampling/rate-limit) never reach it; hook errors are swallowed.
  • Fork/shutdown safe — the writer is flushed on exit and respawned in forked children (gunicorn/celery prefork). The exit drain is registered when structguru is imported, so atexit handlers registered afterwards can still log. Rotating-file writers sharing a path coordinate through an owner-only .lock sidecar; distributed hosts should still prefer stdout and an external collector.
  • Structured exceptions (structured_exceptions=True) render type, message, module, and frames as a dictionary, with optional redacted/truncated locals controlled by the exception_* options. A local named like a sensitive key is redacted, and so is any value under a sensitive key inside a mapping, list, tuple, named tuple, set, dataclass with its generated __repr__, or SimpleNamespace (walked with bounded depth and size, cycle-safe); other objects' own repr() text is covered by sensitive_patterns, which scan a bounded rendering prefix of at most exception_max_local_repr + 4096 characters before final truncation (depth and item limits also apply; patterns needing later context can miss visible text). Exception groups include nested members under exceptions, with the same frame limits and redaction. Traversal stops at ten nesting levels or 100 exception nodes; exceptions_truncated counts omitted direct children. Failed message conversions produce a marker instead of interrupting logging.
  • stack_info is supported natively: the stack is captured in Python and rendered in the same position as StackInfoRenderer (stack between service and message). Unlike the standard path, the stack ends at the user's calling frame (frames of the structguru package are skipped, the way structlog skips its own).
  • Console mode (format="console"): renders colored, human-readable lines instead of JSON — structguru's own stable dev format (<timestamp> [<LEVEL>] <message> k=v), with ANSI colors by default on a TTY. Override with colors=True/False. String values are double-quoted with " and \ escaped, keys containing spaces, =, quotes, or backslashes are quoted, and control characters, U+2028/U+2029, and bidirectional controls are escaped everywhere, so a field key or value cannot forge another field or line. Floats use the JSON renderer's text (1.0, 1e+300); the stack and a formatted exception follow as indented blocks.
  • File sinks (file_path=...): write to a rotating file natively. Defaults mirror RotatingFileHandler (50 MB, 5 backups); configure via file_max_bytes/file_backup_count. Set also_stdout=True to mirror output to both file and stdout (e.g. container + persistent log).
  • Callable sinks (callable_sinks=[fn, ...]): use a bounded queue (callable_queue_maxsize=1024). overflow="block" provides lossless backpressure; overflow="drop" reports callable_dropped metrics. One background thread at a time calls the sinks, in log order, also across reconfiguration; logger.add() never waits for the queue. Sink exceptions are counted in callable_errors with a rate-limited warning. Flush and lifecycle operations drain queued calls; a sink that makes no progress for 10 seconds is abandoned with a warning instead of blocking them.
  • Sentry integration (sentry_processor=SentryProcessor(...)): receives the already-redacted event; raw exception capture requires capture_raw_exceptions=True.
  • Scope: the native renderer covers JSON and console rendering, file/stdout/callable sinks, redaction, sampling/rate limiting, metrics, exceptions, and stack information. logger.add() sinks receive native and stdlib records.

Shutdown and reconfiguration drain records already accepted by the native queue. A native or callable sink that makes no progress for 10 seconds is abandoned with a warning instead of blocking the caller. Queued native records are discarded, and the warning does not wait on a full stderr. Calls still formatting or waiting for space may be rejected when their writer closes, even in block mode. lifecycle_metrics()["rejected"] counts these native deliveries without queue-full warnings and survives shutdown and configuration changes; forked children start at zero. A rejected record reaches no other destination either: the synchronous stream, callable sinks, and Sentry follow the native writer's outcome. Calls begun while logging is disabled are no-ops and are not counted. See the lifecycle contract and how delivery works for details.

Framework integrations

ASGI (FastAPI / Starlette)

from fastapi import FastAPI

from structguru.integrations.asgi import StructguruMiddleware

app = FastAPI()
app.add_middleware(StructguruMiddleware, request_id_header="X-Request-ID")

Granian

Route Granian's server logs through StructguruHandler using --log-config, and use StructguruMiddleware for ASGI request IDs and structured summaries. The Granian guide includes a complete logging dictionary, application and launcher examples, and access-log options.

Celery

from structguru.integrations.celery import setup_celery_logging

setup_celery_logging(propagate_context=True, context_keys=["request_id"])
# Binds task_id/task_name; propagates selected keys (redacted, JSON-safe) via headers

Flask

from flask import Flask

from structguru.integrations.flask import setup_flask_logging

app = Flask(__name__)
setup_flask_logging(app, request_id_header="X-Request-ID")

Django

# settings.py
from structguru.integrations.django import build_logging_config, StructguruMiddleware

LOGGING = build_logging_config(service="myapp", level="INFO", json_logs=True)
MIDDLEWARE = ["structguru.integrations.django.StructguruMiddleware", ...]

SQLAlchemy

from structguru.integrations.sqlalchemy import setup_query_logging

setup_query_logging(engine, slow_threshold_ms=100, log_all=False)
# query is "<omitted>" by default; pass include_query=True to log statement[:500]

gRPC

from concurrent import futures

import grpc

from structguru.integrations.grpc import StructguruInterceptor

server = grpc.server(
    futures.ThreadPoolExecutor(),
    interceptors=[StructguruInterceptor()],
)

Sentry

import logging

from structguru import update
from structguru.integrations.sentry import SentryProcessor

sentry = SentryProcessor(event_level=logging.ERROR, tag_keys=frozenset({"service"}))
update(sentry_processor=sentry)

Stdlib bridge

Third-party libraries log through the standard logging module. Installing the bridge re-emits those records through structguru, so they share the same JSON / console formatting, redaction, and output stream as your own logs:

from structguru.integrations.stdlib import install_stdlib_bridge

bridge = install_stdlib_bridge(
    level="INFO",
    suppress_loggers=("urllib3", "botocore"),
    disable_existing_loggers=False,
)

import logging

logging.getLogger("sqlalchemy.engine").info("SELECT 1")
# → {"logger":"sqlalchemy.engine","level":"INFO",...,"message":"SELECT 1"}

While the bridge is installed, logger.add() sinks receive third-party records only through it — rendered once, never also raw. Pass the returned handler to uninstall_stdlib_bridge() to restore the previous behavior.

Installing a second bridge while one is active raises RuntimeError. When logging setup legitimately runs more than once per process (a Django manage.py that imports a Celery app module, repeated setup in test suites), pass replace=True to release the previous bridge first — last call wins:

bridge = install_stdlib_bridge(level="INFO", replace=True)

The swap is atomic for callers: a record logged by another thread during it is delivered at most once (rendered, raw, or dropped — never twice). Suppression levels applied by the earlier install are not reverted, and calling uninstall_stdlib_bridge() on the replaced handler is a no-op.

disable_existing_loggers=True disables named stdlib loggers that already exist at installation time; False re-enables them, following dictConfig semantics. When the option is omitted, install_stdlib_bridge() reads STRUCTGURU_STDLIB_DISABLE_EXISTING_LOGGERS; if the variable is also unset, existing states are preserved. Explicit Python values override the environment. An empty environment value is treated as unset.

STRUCTGURU_STDLIB_DISABLE_EXISTING_LOGGERS=false python -m myapp

To configure all bridge options from environment variables at a controlled point in application startup:

STRUCTGURU_STDLIB_LEVEL=INFO \
STRUCTGURU_STDLIB_DISABLE_EXISTING_LOGGERS=false \
python -m myapp
from structguru.integrations.stdlib import install_stdlib_bridge_from_env

bridge = install_stdlib_bridge_from_env()

Requirements

  • Python 3.11+
  • The compiled Rust extension (shipped as abi3 wheels for Linux/macOS/Windows, plus free-threaded CPython 3.14t/3.15t wheels for Linux x86_64, macOS arm64, and Windows x64)

Documentation & Examples

The documentation follows Diátaxis:

  • Tutorials — Learn structguru step by step, from the first log line to a logged web service.
  • How-to guides — Configure, route, redact, and integrate with frameworks (FastAPI, Granian, Flask, Django, Celery, gRPC, SQLAlchemy, HTTPX, Requests).
  • Reference — API, settings and environment variables, record format, metrics, and integration details.
  • Explanation — Architecture, delivery guarantees, context propagation, and redaction design.
  • Full-stack Example — FastAPI + Celery + SQLAlchemy in action.
  • Granian + FastAPI Example — Launch through Granian's Python API with structured server and request logs.
  • Existing-loggers Example — Configure the stdlib policy and bridge replacement from code or environment.
  • Context-propagation Example — Carry request fields through async tasks and a thread pool.
  • Sinks and Testing Example — Capture, redact, and assert on rendered records with deterministic cleanup.

Development

uv sync --all-extras
uv run pytest
make bench
uv run ruff check .
uv run mypy src/

License

MIT — Copyright (c) 2025 Aleksandr Pavlov

Metadata

Release files for structguru 1.7.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for structguru 1.7.1
File Size Uploaded Provenance Actions
structguru-1.7.1.tar.gz 181.2 kB With provenance Details for structguru-1.7.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for structguru 1.7.1
File Actions
structguru-1.7.1-cp315-cp315t-win_amd64.whl CPython 3.15 CPython 3.15 free-threading Windows x86-64 Details for structguru-1.7.1-cp315-cp315t-win_amd64.whl
structguru-1.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.15 CPython 3.15 free-threading Linux glibc 2.17+ x86-64 Details for structguru-1.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
structguru-1.7.1-cp315-cp315t-macosx_11_0_arm64.whl CPython 3.15 CPython 3.15 free-threading macOS 11.0+ ARM64 Details for structguru-1.7.1-cp315-cp315t-macosx_11_0_arm64.whl
structguru-1.7.1-cp314-cp314t-win_amd64.whl CPython 3.14 CPython 3.14 free-threading Windows x86-64 Details for structguru-1.7.1-cp314-cp314t-win_amd64.whl
structguru-1.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64 Details for structguru-1.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
structguru-1.7.1-cp314-cp314t-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 Details for structguru-1.7.1-cp314-cp314t-macosx_11_0_arm64.whl
structguru-1.7.1-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details for structguru-1.7.1-cp311-abi3-win_amd64.whl
structguru-1.7.1-cp311-abi3-musllinux_1_2_x86_64.whl CPython 3.11 abi3 Linux musl 1.2+ x86-64 Details for structguru-1.7.1-cp311-abi3-musllinux_1_2_x86_64.whl
structguru-1.7.1-cp311-abi3-musllinux_1_2_aarch64.whl CPython 3.11 abi3 Linux musl 1.2+ ARM64 Details for structguru-1.7.1-cp311-abi3-musllinux_1_2_aarch64.whl
structguru-1.7.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details for structguru-1.7.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
structguru-1.7.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details for structguru-1.7.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
structguru-1.7.1-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details for structguru-1.7.1-cp311-abi3-macosx_11_0_arm64.whl
structguru-1.7.1-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details for structguru-1.7.1-cp311-abi3-macosx_10_12_x86_64.whl

Total release size: 14.8 MB

Release files / structguru-1.7.1.tar.gz

Download URL structguru-1.7.1.tar.gz
Size 181.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5f3ed6587281910f5ec1bfa2abf77953e60c37f1c6d133d3c93827504863857d
BLAKE2b-256 checksum
How to use checksums
3fb1c6267465c5d83a46c80ee7da3d1f3f3e4b8a30ccbb107cc90b6370d3a386
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp315-cp315t-win_amd64.whl

Download URL structguru-1.7.1-cp315-cp315t-win_amd64.whl
Size 1.1 MB
Tags CPython 3.15 CPython 3.15 free-threading Windows x86-64
SHA-256 checksum
How to use checksums
4da532486f0e55922446804b9152ad06f78e3e3da47e526c657fe88377ff2df7
BLAKE2b-256 checksum
How to use checksums
ca664a499ca0ba53627f6a8f9b6ec6526638e0380553f184b3662d9c826b1eab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL structguru-1.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.1 MB
Tags CPython 3.15 CPython 3.15 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
d502369d47ebf69d6cae19f9da2d62fa1830e317cb3c71ac03dffe9a5ce7726f
BLAKE2b-256 checksum
How to use checksums
f4679ba9f8f3124f5e9e51204ca93368511ab07299e901e52048b2e1cadd20ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp315-cp315t-macosx_11_0_arm64.whl

Download URL structguru-1.7.1-cp315-cp315t-macosx_11_0_arm64.whl
Size 1.0 MB
Tags CPython 3.15 CPython 3.15 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
88ff65967fbb32f51e7718b571f76a8d5eef6e5e35fdf15372c3813b8884ce29
BLAKE2b-256 checksum
How to use checksums
07d1ebbed17a86f824be8556d8be05b571dc15fb3b59fb4b1afd877327200ee5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp314-cp314t-win_amd64.whl

Download URL structguru-1.7.1-cp314-cp314t-win_amd64.whl
Size 1.1 MB
Tags CPython 3.14 CPython 3.14 free-threading Windows x86-64
SHA-256 checksum
How to use checksums
2ca5b0313df49a540bb540cf9846811fbc360d6cfedc38006575de6c615c5b19
BLAKE2b-256 checksum
How to use checksums
e0396562c2dfa27a9bc310218d3ad73e66edcbf15ba2d6115c04b78854f86873
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL structguru-1.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.1 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
34e344e853f92cf0113b754d22c8873e3121281cdc1f22cdca14bcd0c4b42770
BLAKE2b-256 checksum
How to use checksums
34e9eedfcc6ea860fdd8eba5b953191f3fc3da399d1bd8aa46b493164272da60
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp314-cp314t-macosx_11_0_arm64.whl

Download URL structguru-1.7.1-cp314-cp314t-macosx_11_0_arm64.whl
Size 1.0 MB
Tags CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f85253fcdfa8fc528fc0e64916101d414f936ea94ae563ad61ca3ad65a912915
BLAKE2b-256 checksum
How to use checksums
b56eb6216eb3c019d591261e50bc0b9129eccd96392019a47e57933f21b812a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-win_amd64.whl

Download URL structguru-1.7.1-cp311-abi3-win_amd64.whl
Size 1.1 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
0fa671069efd5aefce2afdbf9532dd6d15b57ffaa218ab2de3d5e064a869da56
BLAKE2b-256 checksum
How to use checksums
aec1b250bb996c833d761b96afb74b5c46a353c522f8e9a17190c747f260889e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-musllinux_1_2_x86_64.whl

Download URL structguru-1.7.1-cp311-abi3-musllinux_1_2_x86_64.whl
Size 1.4 MB
Tags CPython 3.11 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
7726c8cf6fbdaff8a31ef789f9eba6d07f9a718a29be267a0fb7c59803234684
BLAKE2b-256 checksum
How to use checksums
cc2c06befca6659645a0ade4dd5948a93d96661be32826fb791917862f3fce4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-musllinux_1_2_aarch64.whl

Download URL structguru-1.7.1-cp311-abi3-musllinux_1_2_aarch64.whl
Size 1.3 MB
Tags CPython 3.11 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
d4be55f2bb49bb113996d819d9dde477c3b83aeaa7433d2eecd102fdf46abcc9
BLAKE2b-256 checksum
How to use checksums
668554c6adedceafdbeb1bada0afe543b918be51cc75c1a1f26782528610a0d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL structguru-1.7.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.1 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
13df8777f7ed8307ea4f0fff4f80f55eb15bd7c78cc3d93b940c92514a2f25bc
BLAKE2b-256 checksum
How to use checksums
a5a19c19c73954a6d260f5a13534156ed7df8c88251cbac38472e4b0b5f31296
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL structguru-1.7.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.1 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
3624dd7da2c7ccf734b377a76a1b6aa4f548cc2f5f1112891518689b524b4302
BLAKE2b-256 checksum
How to use checksums
d48544a4738f9348b59261294606e0f0ed35e8107232c379e7013e105f07b06c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-macosx_11_0_arm64.whl

Download URL structguru-1.7.1-cp311-abi3-macosx_11_0_arm64.whl
Size 1.0 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
83bfd3ac7c3e6bd1fbd5a1c1bfa5018276fc2614e8394b0d5cfc89eb88ea6dd9
BLAKE2b-256 checksum
How to use checksums
d48adea86d785f2de4acce002983fe0499dd9be81ac649aff72046dcf037681c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Release files / structguru-1.7.1-cp311-abi3-macosx_10_12_x86_64.whl

Download URL structguru-1.7.1-cp311-abi3-macosx_10_12_x86_64.whl
Size 1.1 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
9ae785f18eff6626c5fbc2216c79f3a1121656df4065554843d53669de19a5b1
BLAKE2b-256 checksum
How to use checksums
1c8497f96daeef765600acbbccf1e1aefef0df3b9583d7d5e71b582956a3ae19
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 27, 2026.

Transparency log

Security for structguru 1.7.1

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.

Full provenance

All 14 files in this release have been uploaded with provenance metadata.

Select from 14 files

Attestation for structguru-1.7.1.tar.gz

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 Oct 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page