cmpnd
The cmpnd package traces, deploys and optimizes DSPy programs on the cmpnd
platform. You give a program a name, and a client records its traces,
deployments and optimization runs under that name.
Installation
uv add cmpnd # or: pip install cmpnd
Authentication
The cmpnd library works with the cmpnd service at
platform.cmpnd.ai. Create an API key on the
platform under Settings → API keys, and pass it as api_key= to
cmpnd.Client() or cmpnd.configure(). For a self-hosted cmpnd install, also
pass the install's URL as endpoint=.
Quick start
A program name is the name your organization gives a program, such as
question-answerer. Traces, deployments and optimization runs under one
program name go to one program. The platform makes the program the first time
your organization uses the program name.
@cmpnd.program(name) above a dspy.Module class gives the class a program
name. Building the class takes its own arguments and a required lm=. The
lm= argument is the dspy.LM that the program runs on:
import cmpnd
import dspy
class Answer(dspy.Signature):
"""Answer the question in one short sentence."""
question: str = dspy.InputField()
answer: str = dspy.OutputField()
@cmpnd.program("question-answerer")
class QA(dspy.Predict):
def __init__(self):
super().__init__(Answer)
qa1 = QA(lm=dspy.LM("openai/gpt-6-luna"))
A cmpnd.Client runs the program and records its trace under the program
name:
gepa = dspy.GEPA(metric=metric, reflection_lm=dspy.LM("openai/gpt-6-luna"), auto="light")
with cmpnd.Client(api_key="ck_xxx", project_tags="my-project") as sdk:
# the trace goes to the program "question-answerer"
result = sdk.run_program(qa1, question="What is DSPy?")
qa2 = sdk.optimize_program(qa1, gepa, trainset=train, valset=val)
cmpnd.trace_id(result) # "a1b2c3d4-...", the trace of this run
cmpnd.trace_id() links a result to its platform trace, for example to attach
feedback later. A client records only the programs you run through it.
A client is active from construction. The with form flushes the client's
traces and closes it on exit. Without with, the client stays active until
you call close() or the process exits, and its traces go out at exit:
sdk = cmpnd.Client(api_key="ck_xxx", project_tags="my-project")
sdk.run_program(qa2, question="What is DSPy?")
# optional: flushes the traces now, so a later read sees them
sdk.close()
The cmpnd.Program constructor gives a program name to a module you already
have, such as a dspy.Predict. It makes the same kind of
program as the decorator:
qa3 = cmpnd.Program(
"question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
)
- A program name starts with an ASCII letter or digit, then has letters,
digits,
.,_or-, at most 64 characters. It does not start withp_. A bad name raisesValueError. Declaring a program makes no network call. optimize_programruns the optimizer in your process and returns a copy of the program that holds the optimized module. The copy keeps the program name and the LM.
Sketching with auto_instrument()
cmpnd.auto_instrument() records a trace of every DSPy call in the process,
with no other change to your code. Use it to sketch a
DSPy program and see what it does:
cmpnd.configure(api_key="ck_xxx", project_tags="my-project")
cmpnd.auto_instrument()
dspy.configure(lm=dspy.LM("openai/gpt-6-luna"))
dspy.ChainOfThought("question -> answer")(question="What is DSPy?")
These traces carry no program, so the platform files them under Unattributed.
The first one in a process logs a warning that points to @cmpnd.program and
cmpnd.Client. Calling a cmpnd.Program directly while auto_instrument() is
on raises a TypeError that points to the client. The API reference below
lists the options of cmpnd.configure().
Deployed programs
Every deployment belongs to a program, and each program has a program name.
Give a DSPy module a program name with cmpnd.Program, then deploy it through a
client for server-side execution:
import cmpnd
import dspy
sdk = cmpnd.Client(api_key="ck_xxx")
qa4 = cmpnd.Program(
"question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
)
deployed = sdk.deploy_program(qa4)
result = sdk.run_deployment(deployed, question="What is DSPy?") # runs server-side
print(result.answer)
deploy_program() packages the module's source, sends it to the platform and
waits until the platform has read it. It then returns a DeployedProgram.
run_deployment() runs it server-side on the client's account, and also takes
a deployment ID. A DeployedProgram is not callable, because a run needs a
client. str(deployed) and deployed.deployment_id return the deployment ID.
deployed.artifact_metadata holds the typed artifact record when the platform
has inspected it. An unknown interface leaves input_fields and
output_fields as None. A known interface with no fields returns empty
lists.
The platform makes the program the first time your organization uses the program name. Later deploys under the same program name go to the same program, and so do the traces of a client that runs it.
Credentials
A hosted program spends a credential your organization sealed, and the deploy names it. The program's code stays the code you run on your laptop:
lm = dspy.LM("openai/deepseek-4.1-flash", api_base="https://gw.lunaroute.com/v1") # unchanged
luna = cmpnd.credentials.get("luna-exec")
deployed = sdk.deploy_program(program, credential=luna)
# deploy: default-lm: chat_completions openai/deepseek-4.1-flash → luna-exec (https://gw.lunaroute.com)
cmpnd.credentials.get(name)returns acmpnd.Credentialholding the name, the protocols its endpoint serves and itsapi_base. It holds no key. A name the organization does not hold raisescmpnd.CredentialNotFound, which lists the names it does hold and the nearest one.cmpnd.credentials.list()returns them all.credential=takes acmpnd.Credential, never a string. A string raises and shows thecmpnd.credentials.get(...)line to write.- Without
credential=, the deployment spends the organization's default, which an owner sets withcmpnd credentials default NAME. - The deployment records the credential's name. Each call spends the newest credential sealed under that name, so an owner who rotates a key needs no redeploy.
- The deploy prints the protocol, model and credential of each binding, as above. A server that prints none chose the credential from the model's provider prefix, and the SDK warns.
- A hosted call goes to the credential's
api_base. The LM's ownapi_baseserves your laptop run and is not sent.
Keys never leave your laptop. The SDK sends no key on the LM, and a key reaches
the platform only through cmpnd credentials create. cmpnd deploy FILE
refuses source whose import builds an LM carrying a key, and names the module,
the model and the field.
The same source on your laptop and hosted
A program's logic runs unchanged on your laptop and hosted. On your laptop it spends the key in your environment. Hosted, it spends a credential your organization sealed. Keep the logic in one file and let a small entry point choose where it runs.
The program file holds the logic and names its model. It holds no key:
# qa.py
import dspy
lm = dspy.LM("openai/gpt-5-mini") # no api_key: litellm reads OPENAI_API_KEY on your laptop
program = dspy.Predict("question -> answer")
def metric(gold, pred, trace=None, pred_name=None, pred_trace=None, lms=None):
verdict = dspy.Predict("answer, gold -> correct: bool")(answer=pred.answer, gold=gold.answer, lm=lms["critic"])
return dspy.Prediction(score=float(verdict.correct), feedback="correct" if verdict.correct else "wrong")
Seal the key once for the organization and make it the default:
printf '%s' "$OPENAI_API_KEY" | cmpnd credentials create --name openai --preset openai
cmpnd credentials default openai
The entry point is the only code that knows where the run happens:
# main.py
import functools
import sys
import cmpnd
import dspy
from qa import lm, metric, program
HOSTED = "--hosted" in sys.argv
sdk = cmpnd.Client()
qa = cmpnd.Program("qa", module=program, lm=lm)
reflection = dspy.LM("openai/gpt-5", max_tokens=32000)
lms = {"critic": dspy.LM("openai/gpt-5-mini")}
train, val = load_examples() # your dspy.Example lists
if HOSTED:
deployed = sdk.deploy_program(qa) # spends the default credential, openai
print(sdk.run_deployment(deployed, question="What is DSPy?"))
best = sdk.optimize_deployment(
deployed,
trainset=train,
valset=val,
metric=metric, # the platform hands it lms
reflection_lm=cmpnd.HostedLM(reflection),
lms={name: cmpnd.HostedLM(model) for name, model in lms.items()},
auto="light",
)
else:
print(sdk.run_program(qa, question="What is DSPy?")) # spends $OPENAI_API_KEY
gepa = dspy.GEPA(metric=functools.partial(metric, lms=lms), reflection_lm=reflection, auto="light")
best = sdk.optimize_program(qa, gepa, trainset=train, valset=val)
python main.py runs everything on your laptop, and python main.py --hosted
runs it on the platform. cmpnd deploy qa.py qa deploys the same file from the
terminal.
| On your laptop | Hosted | |
|---|---|---|
| Key | the provider's variable in your environment, such as OPENAI_API_KEY |
the credential the call names, else the organization's default |
| Address | the LM's api_base, else the provider's endpoint |
the credential's api_base |
| Model | gpt-5-mini, the model after its first / |
gpt-5-mini |
The metric's lms |
the dict the entry point binds | the run's lms=, which the platform hands it |
These rules keep the program file portable:
- Leave the key off the program's LM and let litellm read the provider's
own variable. For a key in a variable litellm does not read, write
api_key=os.environ.get("NAME"). cmpnd imports a deploy file with an empty environment, so the key isNonethere and present on your laptop. - Never write a key into the file, and never read it as
os.environ["NAME"]at module scope. The deploy refuses the first. The second raisesKeyErrorhosted, where the environment holds no key. - Seal the credential at the address your laptop LM reaches. A program
that sets
api_base="https://gw.lunaroute.com/v1"needs a credential sealed there, with--preset lunarouteor--api-base. Hosted calls go to the credential's address and ignore the LM'sapi_base. The deploy prints the address it chose, so you can compare the two. - Wrap a model you hand the hosted optimization in
cmpnd.HostedLM. The entry point buildsreflection_lm=and eachlms=entry, so those LMs may hold a key for the laptop run. The wrapper leaves that key on your machine.optimize_deploymentrefuses a key on an unwrapped LM, because there it would look spent.cmpnd.HostedLM(model, credential=c)makes a model spend a credential other than the run's.
A judge built on dspy.experimental.TypeSafe also runs unchanged in both
places. docs/sdk-instrumentation.md, under
"System One judges", describes the hosted side.
Options
sdk.deploy_program(
program, # required: a cmpnd.Program
metric=None, # optional: a metric callable, packaged for optimization
timeout=300, # optional: seconds to wait for the deployment to be ready
metadata=None, # optional: a JSON-serializable dict, at most 64 KiB, stored with the deployment
credential=None, # optional: a cmpnd.Credential the program's model spends
)
How it works
- The SDK packages the module's source, including its LM configuration, signature and types.
- The platform reads the program, the model string and the sampling settings from that source.
deploy_program()returns theDeployedProgramwhen the deployment is ready.
Optimization on the platform
optimize_deployment() optimizes a deployment through the platform. It returns
the best deployment as a DeployedProgram, whose score is the best score
found. Deploy the program first:
import cmpnd
import dspy
sdk = cmpnd.Client(api_key="ck_xxx")
program = cmpnd.Program(
"haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna")
)
deployed = sdk.deploy_program(program)
# GEPA needs a five-argument feedback metric that returns dspy.Prediction(score=, feedback=)
def metric(example, pred, trace=None, pred_name=None, pred_trace=None):
ok = example.season.lower() not in pred.haiku.lower()
return dspy.Prediction(
score=float(ok), feedback=None if ok else "Don't name the season."
)
best = sdk.optimize_deployment(
deployed,
optimizer="gepa",
trainset=train,
valset=val,
metric=metric,
reflection_lm=dspy.LM("openai/gpt-6-luna"),
auto="light",
)
print(best.score)
print(sdk.run_deployment(best, topic="late autumn").haiku)
optimize_deployment() also takes the ID of a ready deployment. The
optimization belongs to the deployment's program, and the program's model comes
from the deployment.
reflection_lm is the model that proposes each new instruction. The search is
only as good as this model, so it is usually a strong model and not the one
being optimized. A dspy.LM passes its sampling settings to the provider. A
bare model name gives the same model with no sampling settings. A run spends
sealed credentials only, so the SDK refuses a key on the LM before any network
call. cmpnd.HostedLM(lm) keeps a key your laptop runs spend on this machine
and passes the LM's model and sampling.
credential= names the run's credential, which every binding that names none
spends: the program's model, the reflection model and each entry of lms. A
binding names its own credential through a wrapper for its protocol:
luna = cmpnd.credentials.get("luna-exec") # serves chat_completions and system_one
openai = cmpnd.credentials.get("openai")
best = sdk.optimize_deployment(
deployed, trainset=train, valset=val, metric=metric,
credential=luna,
reflection_lm=cmpnd.HostedLM(dspy.LM("openai/gpt-5"), credential=openai),
lms={"judge": cmpnd.SystemOne("lunaroute/djev", credential=luna)},
auto="light",
)
cmpnd.HostedLM(lm, credential=c) wraps a chat LM, and
cmpnd.SystemOne(model, credential=c) declares a System One model. A binding
without a credential spends the run's, or the organization's default. The
platform refuses a credential whose endpoint does not serve a binding's
protocol, and names the credential= to add.
The SDK checks the metric before any network call. GEPA writes each new
instruction from the textual feedback the metric returns, so it needs a
five-argument feedback metric. The SDK refuses a metric with fewer than five
positional arguments, because such a run would report success and learn
nothing. A *args metric cannot be checked, and the SDK accepts it with a
warning.
gepa is the default and the only optimizer the platform runs.
optimize_deployment() raises ValueError for the retired bootstrap_fewshot
and random_search before any network call, and the platform answers them with
a 404 that names gepa.
A metric with its own model
A metric reaches a model the same way the program's predictors do. A metric
that builds a dspy.Predict runs on the program's own model. A metric that
needs a different model, such as a stronger judge, declares it in the
optimize call's lms argument and selects it by name through a sixth
parameter, lms:
def faithfulness(gold, pred, trace, pred_name, pred_trace, lms=None):
"""Does the summary say only what the document says?"""
verdict = dspy.Predict("document, summary -> score: float, feedback: str")(
document=gold.document,
summary=pred.summary,
lm=lms["critic"],
)
return dspy.Prediction(score=verdict.score, feedback=verdict.feedback)
best = sdk.optimize_deployment(
deployed, optimizer="gepa", trainset=train, valset=val, metric=faithfulness,
reflection_lm=dspy.LM("openai/gpt-6-luna"),
lms={"critic": dspy.LM("openai/gpt-6-luna")},
max_metric_calls=300,
)
lms declares any model that is not one of the program's predictors. The
rules:
- A name the run did not declare raises at the metric and lists the declared names.
"default-lm"is reserved for the program's own model, which comes from the deployment. Declaring it raises an error that names it.- The platform refuses a binding it finds no credential for when it dispatches
the run, before the run starts. These LMs, like
reflection_lm, must not carry a key.
The lms parameter does not change the arity check. Five or more positional
arguments make a feedback metric, and a metric without lms never receives
it.
Options
sdk.optimize_deployment(
deployed, # required: a DeployedProgram or a deployment ID
optimizer="gepa", # optional: the only optimizer the platform runs
trainset=train, # required: training examples
valset=val, # required: validation examples
metric=metric, # required: the metric, arity-checked
config=None, # optional: optimizer config, allow-listed by the platform
reflection_lm=None, # required: a dspy.LM, a bare model name or a cmpnd.HostedLM
lms=None, # optional: name -> dspy.LM, cmpnd.HostedLM or cmpnd.SystemOne
credential=None, # optional: the cmpnd.Credential every other binding spends
max_metric_calls=None, # budget: the metric-call ceiling for the run
auto=None, # budget: "light", "medium" or "heavy"
may_author_code=None, # optional: False keeps each dspy.Flex at its deployed source
seed=0, # optional: the search's random seed
poll_interval=3.0, # optional: seconds between status checks
timeout=600.0, # optional: seconds to wait for the run
)
Pass exactly one budget: max_metric_calls, auto or
config["max_full_evals"]. The SDK raises before any network call when the
budget is missing.
optimize_deployment() raises cmpnd.OptimizeError when the platform answers a step's
initiation with a 4xx, such as a 409 for missing data or a metric mismatch. It
raises cmpnd.OptimizeFailed when a step reaches failed.
The result's optimization_run_id names the run that produced it.
continue_optimization() starts a new run from one of that run's candidates,
reusing its data, with a budget of its own:
better = sdk.continue_optimization(best, max_metric_calls=120) # from the best candidate
for candidate in sdk.list_candidates(best.optimization_run_id): # read each one first
print(candidate["candidate_id"], candidate["aggregate_score"], candidate["instructions"])
other = sdk.continue_optimization(best, candidate="ca_...", auto="light")
model= runs the candidate on another student model, and credential= names
the credential that model spends. A loop over models is a model sweep:
for model in ["openai/gpt-4o-mini", "openai/gpt-4.1-nano"]:
swept = sdk.continue_optimization(best, model=model, auto="light")
print(model, swept.score)
A refusal raises cmpnd.OptimizeError, whose error_code says why, such as
not_completed, unknown_candidate or no_credential.
Command line
The package installs the cmpnd command. cmpnd login saves your API key for
the command line. cmpnd -h lists the commands, and cmpnd COMMAND -h
describes one:
usage: cmpnd [-h] [--version] [--api-key API_KEY] [--endpoint ENDPOINT]
{auth,login,logout,org,credentials,tool-servers,optimizations,programs,traces,evals,datasets,deployments,ps,status,logs,inspect,schema,sample,run,deploy,optimize}
...
CMPND platform CLI — deploy, run, and inspect DSPy programs.
options:
-h, --help show this help message and exit
--version show program's version number and exit
--api-key API_KEY API key (or set CMPND_API_KEY)
--endpoint ENDPOINT API endpoint (or set CMPND_ENDPOINT)
Deploy a source file under a program name, or optimize the program a file declares:
cmpnd deploy program.py question-answerer
cmpnd optimize gepa task.py haiku --reflection-model openai/gpt-6-luna --auto light
cmpnd deploy uploads the file as written. cmpnd optimize reads program,
trainset, valset and metric from the file, deploys the program under the
program name and prints the best deployment ID.
Custom spans
Trace non-DSPy code with the decorator:
from cmpnd import trace, SpanType
@trace(name="fetch_documents", span_type=SpanType.RETRIEVE)
def fetch_documents(query: str) -> list[str]:
return documents
Or with the context manager:
from cmpnd import start_span, SpanType
def run_pipeline(query: str):
with start_span("vector_search", span_type=SpanType.RETRIEVE) as span:
span.set_attribute("index", "my-faiss-index")
docs = search(query)
span.set_outputs({"doc_count": len(docs)})
return generate(query, docs)
What gets traced
- Modules: the module type, signature name and instructions, input and output field names, and demo count.
- LM calls: the model name and provider, token usage and the request and response content.
- Adapters: format and parse operations.
- Tools: the tool name and description and each invocation's inputs and outputs.
- Evaluations: scores and the program under evaluation.
Span types
SpanType has these members: UNKNOWN, MODULE, PREDICT,
CHAIN_OF_THOUGHT, REACT, RLM, RETRIEVE, LM_CALL, ADAPTER_FORMAT,
ADAPTER_PARSE, TOOL, INTERPRETER_EXECUTE, SIGNATURE_VALIDATE,
DEMO_SELECT, OPTIMIZATION and EVALUATION.
API reference
cmpnd.configure()
Sets the global API key, endpoint and options that auto_instrument() uses:
cmpnd.configure(
api_key="ck_xxx", # required, or CMPND_API_KEY
endpoint="https://platform.cmpnd.ai", # optional, or CMPND_ENDPOINT
project_tags="my-project", # optional: one tag or a list of tags
batch_size=100, # optional: spans per export batch
flush_interval_seconds=5.0, # optional: seconds between flushes
capture_inputs=True, # optional: record span inputs
capture_outputs=True, # optional: record span outputs
default_tags={"env": "prod"}, # optional: tags on every trace
)
api_key and endpoint fall back to the CMPND_API_KEY and
CMPND_ENDPOINT environment variables. project is a deprecated alias for
project_tags. Passing both raises ValueError. CMPND_MAX_INPUT_SIZE and CMPND_MAX_OUTPUT_SIZE set the
captured input and output size limits, 65,536 bytes each by default.
cmpnd.auto_instrument()
Registers the callback with DSPy, so every DSPy call records a trace. The traces carry no program and land in Unattributed.
cmpnd.Client()
Takes most of the same arguments as cmpnd.configure() and keeps them apart from the
global config. Use it as a context manager or as a plain object.
run_program(program, **inputs)runs acmpnd.Programand records its trace under the program name.optimize_program(program, optimizer, trainset=..., valset=...)compiles acmpnd.Programwith a DSPy optimizer in your process, records every rollout, and returns a copy of the program that holds the optimized module. Fordspy.GEPA, it also records the optimization run.deploy_program(program)deploys acmpnd.Programunder its program name and returns aDeployedProgram.run_deployment(deployment, **inputs)runs a deployment and returns adspy.Prediction. The section below describes it.optimize_deployment(deployment, ...)optimizes a deployment on the platform and returns the bestDeployedProgram, whose.scoreis the best score found. It raisescmpnd.OptimizeErrororcmpnd.OptimizeFailedon failure.list_candidates(run_id)returns a run's candidates as dicts, each with itsca_id, score, parent and instructions.continue_optimization(run, candidate=None, model=None, credential=None, ...)runs a new optimization from one candidate of a completed run, with that run's data and a new budget, optionally on another student model, and returns its bestDeployedProgram.list_traces(**filters)andget_trace(trace_id)read traces with the client's credentials. They flush the client's traces first.list_deployments(status=None, since=None, limit=50, offset=0)andget_deployment(deployment_id)read deployment records, ascmpnd deployments listandshowdo.get_deployment_source(deployment_id, path=None)returns the program file a deployment stores, ascmpnd inspect --sourcedoes. A continuation's deployment holds the program the continuation runs.close()flushes the client's traces and closes the client. A closed client raisesRuntimeErroron every method.
cmpnd.program()
@cmpnd.program(name) above a dspy.Module class returns a cmpnd.Program
class with the same class name. Building it takes the class's own arguments
and a required lm= keyword. The decorator refuses a class whose
constructor already takes lm. Give an instance of it to cmpnd.Program instead.
cmpnd.Program()
cmpnd.Program(name, *, module, lm) gives a DSPy module a program name and
the dspy.LM it runs on. @cmpnd.program(name) builds the same thing from a
dspy.Module class.
cmpnd.CmpndCallback
The callback class, for manual registration:
import dspy
import cmpnd
cmpnd.configure(api_key="ck_xxx")
dspy.configure(callbacks=[cmpnd.CmpndCallback()])
cmpnd.Client.run_deployment()
Submits one durable run of a DeployedProgram or a deployment ID, waits for
the result within the local timeout and returns a dspy.Prediction. A fast
result returns at once, and the SDK never submits one run twice. A deployment
of another account answers 404.
timeout is the whole submit-and-wait budget in seconds, 30 by default, or
None for no local limit. entrypoint and lm select a module and model and
travel beside the inputs. metadata and tags take dict[str, str] values
that the platform applies to the run's root trace. Names the platform sets,
such as deployment_run_id, raise TypeError before anything is sent. The
errors:
- A refused request raises
httpx.HTTPStatusError. - A lost or failed submission reply raises
RunSubmissionUncertain. - A spent budget raises
RunWaitTimeout, which holds the run ID. - An answer that expired before it was read raises
RunResultExpired.
sdk.deployment_run_id(result) returns the run ID of a result, or of an
exception when the platform had assigned a run.
sdk.submit_deployment_run(deployment, inputs) returns the accepted handle
without waiting. sdk.list_deployment_runs(), get_deployment_run(id),
get_deployment_run_result(id) and wait_deployment_run(id) find, inspect and
resume runs. list_deployment_runs(deployment) limits the list to one
deployment. RunSubmissionUncertain names the list command to check before you
send new work.
cmpnd.DeployedProgram
The deployment that deploy_program() and optimize_deployment() return. Run
it with run_deployment(). str() and .deployment_id return its ID.
.score is its score when it came from optimize_deployment(), and None
otherwise.
.deployment_signature holds the typed deployment response, and
.artifact_metadata holds its metadata when available.
cmpnd.trace()
A decorator that traces a function.
cmpnd.start_span()
A context manager that opens a span.
cmpnd.get_current_trace()
Returns the current trace, or None.
cmpnd.get_current_span()
Returns the current span, or None.
cmpnd.trace_id()
Returns the platform trace ID stamped on a prediction from an instrumented
program, or None when the prediction came from outside instrumentation. Use
it to attach feedback through
POST /api/v1/traces/{cmpnd.trace_id(pred)}/metadata.
cmpnd.flush_exporter()
Publishes everything the background exporter has queued and leaves the
exporter running. Call it before a reader fetches a trace the program just
produced. It returns True when the drain finished within the timeout, 5
seconds by default, and False when it timed out or no exporter is running.
cmpnd.shutdown_exporter()
Flushes and stops the background exporter.
Metadata
Release files for cmpnd 0.70.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cmpnd-0.70.0.tar.gz | 1.8 MB | With provenance | Details for cmpnd-0.70.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cmpnd-0.70.0-py3-none-any.whl | Python 3 | none | any | Details for cmpnd-0.70.0-py3-none-any.whl |
Total release size: 2.3 MB
Release files / cmpnd-0.70.0.tar.gz
| Download URL | cmpnd-0.70.0.tar.gz |
|---|---|
| Size | 1.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
35481fee3628a936ab13d120dbbc2554d0c0e51896bb5c2001b3c123f9c1be63
|
|
BLAKE2b-256 checksum How to use checksums |
e3a32c7a7695d4e122d5d89883809735d1239c22bbdf159e28fa7c4181b83a2c
|
| 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 Nov 2, 2026.
Transparency logRelease files / cmpnd-0.70.0-py3-none-any.whl
| Download URL | cmpnd-0.70.0-py3-none-any.whl |
|---|---|
| Size | 438.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7ab77b3746cc809332d21a20d84ef2b191895fc8ad053e593b1ab15f57670e25
|
|
BLAKE2b-256 checksum How to use checksums |
104c8d062e9249784a8365263f0255ef3ea44030613c8bd1ba15196014ab1527
|
| 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 Nov 2, 2026.
Transparency logSecurity for cmpnd 0.70.0
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 2 files in this release have been uploaded with provenance metadata.
Attestation for cmpnd-0.70.0.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 Nov 2, 2026.
Transparency logA 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.