Skip to main content

completr: serverless autocompletion for Rust and Python

An embedded autocompletion engine whose database is a bucket. No servers to run.
Exact, prefix, infix, abbreviation, spelling-tolerant, word-decomposing and semantic completions,
ranked by popularity and served in well under a millisecond.

Quick start · Docs · Rust docs · Python API · Architecture · Benchmarks · Changelog

CI crates.io docs.rs PyPI Python 3.11+ License: MIT

completr completing music queries: prefix, abbreviation, spelling correction, word decomposition and infix

completr is a serverless autocompletion engine. In the spirit of LanceDB, it is a library, not a service: your application embeds it (Rust, or Python through first-class bindings), and an object-store bucket or a local directory is the database. There is no cluster to deploy, scale, upgrade or keep alive. Every process that serves completions reads the index straight from storage, and writers coordinate through the storage itself.

You give it documents (an id, a text, a popularity weight, and optionally aliases and an embedding), and it completes what your users type: every kind of match an autocomplete box needs, ranked together, and kept fresh while your data changes.

Contents

Serverless by design

flowchart LR
    W["Any process<br/>txn.commit()"] -- "create-only commit" --> M
    W -- "new segments" --> S
    subgraph B["Bucket or directory: the database"]
        M["_versions/ manifests"]
        S["segments/ immutable files"]
    end
    M -- "new versions" --> F1["Your app + completr<br/>engine.complete(...)"]
    S -- "changed segments" --> F1
    M --> F2["Your app + completr"]
    S --> F2
    M --> F3["Your app + completr"]
    S --> F3
  • Storage is the only shared component. Manifests and segments are plain objects on S3, GCS, Azure or a file system. Nothing else runs between your processes.
  • Commits are create-only writes. Version N + 1 is written with If-None-Match (exclusive create on a file system), so concurrent writers never corrupt each other; a loser retries on the newer version.
  • Readers scale with your application. Each engine syncs itself in the background, loads only changed, immutable segments (memory-mapped from local disk or the optional disk cache) and switches versions atomically. Add capacity by adding replicas of your own app.
  • Queries never leave the process, so there is no network hop on the hot path.

Features

Matching

  • Exact and prefix completion as users type, over whole titles and their words.
  • Infix matching: queen finds Dancing Queen – ABBA.
  • Abbreviations: RHCP completes Under the Bridge – Red Hot Chili Peppers. Abbreviations match exactly, so short codes do not flood the results.
  • Synonyms: alternative names that are prefix-searchable and point back to their document, searched on their own so they never displace a direct match.
  • Spelling correction of up to two edits per word, SymSpell-style, verified with rapidfuzz: bohemain rapsody finds Bohemian Rhapsody – Queen.
  • Word decomposition: run-together input such as dancingqueen is split into words and completed.
  • Semantic completion from embeddings of any model, quantised to 2-4 bits.
  • Hybrid completion with reciprocal rank fusion, weighted blending or lexical-first ordering, chosen per request.
  • Context filters: restrict any request to documents tagged with a category, tenant or language.
  • Your own ids: integers or strings such as UUIDs, returned with every suggestion as given. Documents with the same title stay separate results.

Ranking

  • Popularity through a per-document weight, combined with match kind, text length and whole-word bonuses.
  • Every suggestion carries its text, match kind and highlight ranges, so your UI renders it directly.
  • Deterministic: identical inputs give bit-identical scores and order, with ties broken by id.

Serving

  • Fast: p50 around 0.1 ms and p99 under 3 ms for typed queries on 200k documents, on one core.
  • Zero-copy segments: an aligned, checksummed binary format read in place through mmap. Opening a segment takes under a millisecond and reads only its headers. Texts are FSST-compressed and decoded one at a time.
  • Compact index: titles are found through documents sorted by title, words by binary search over their sorted texts, spelling variants through Elias-Fano coded buckets, and postings are delta coded in blocks, so the 7.2 million English Wikipedia titles index into 338 MB, less than tantivy's 357 MB.
  • Streaming builds: documents stream into a SegmentBuilder (completr.Segment.build(rows, path=...) in Python), which keeps them compactly and writes each section to the file as it is produced. Indexing the 124,440 HN titles takes 0.29 s and peaks at 59 MB.
  • Bounded indexing memory: a SegmentWriter starts a new segment file whenever building the current one would pass its memory budget (256 MB by default), so any corpus indexes in bounded memory. The segments rank exactly like one, and compaction merges them through their sorted dictionaries, byte for byte as a rebuild would: all of English Wikipedia, 7.2 million titles, is written and compacted into one segment in 25.6 s, and 40 million MusicBrainz recordings in 317 s with a peak of 547 MB.
  • Override layers: one catalogue, many views. Tenants, languages, listeners, promotions, takedowns and experiments are small indexes stacked on the shared data, overriding it per document id, without a copy.
  • A short-query cache for one- to three-character prefixes, carried across index versions.

Serverless updates

  • Immutable segments, as in Lucene and LanceDB: updates land as small delta segments, and tiered compaction merges them.
  • Versioned databases on local disk, S3, GCS, Azure or memory, with optimistic, create-only commits and automatic retries.
  • Engines that follow the database: an engine from db.engine() loads new versions in a background thread, with no sync loop to write.
  • One ingestor, many writers, when you need it: any process submits change sets, and a lease-elected Ingestor commits them in order.
  • Credentials like boto3: environment, profiles, SSO, web identity, ECS and IMDS.

Developer experience

  • Documents as dicts, completr.Document objects, or pandas, polars and Arrow tables, with int or string ids.
  • Indexes, engines, databases and transactions at the top level of completr, an asyncio API, typed stubs and a clear exception hierarchy.
  • Collections on top, for named collections that compact themselves.
  • A completr command-line tool, and tracing events that also reach Python's logging.

What it completes

Real results from the index behind the demo above (23 short titles with popularity weights):

Query Top completion Kind Capability
danc Dancing Queen – ABBA, Dancing in the Dark – Bruce Springsteen, Dancing On My Own – Robyn prefix completion by popularity
rhcp Under the Bridge – Red Hot Chili Peppers abbreviation abbreviations, case-insensitive
bohemain rapsody Bohemian Rhapsody – Queen fuzzy spelling correction, two words
dancingqueen Dancing Queen – ABBA prefix word decomposition
queen Bohemian Rhapsody – Queen, Dancing Queen – ABBA, Killer Queen – Queen infix matches inside titles
is this the real Bohemian Rhapsody – Queen synonym synonyms, through complete_aliases

Installation

pip install completr
cargo add completr --features store                       # databases on local disk and in memory
cargo add completr --features aws-credentials,gcp,azure   # plus S3, GCS and Azure
cargo add tokio --features macros,rt-multi-thread         # the database API is async
Cargo feature Adds
none The engine: Segment, SegmentWriter, Index, Engine
store Database, Transaction, Replica, Lease, ChangeSet, Ingestor, local and in-memory stores, and collections: connect, Client, Collection
aws / gcp / azure S3, Google Cloud Storage, Azure Blob Storage
aws-credentials S3 credentials through the AWS SDK chain

The Python wheel includes all features. It is abi3 for CPython 3.11+, and releases the GIL while it searches and builds.

Quick start

Python

import completr
from completr import Index

docs = [   # also completr.Document objects, pandas, polars or Arrow tables
    {"id": "bohemian", "text": "Bohemian Rhapsody – Queen", "popularity": 0.95, "synonyms": ["is this the real life"]},
    {"id": "dancing", "text": "Dancing Queen – ABBA", "popularity": 0.85},
    {"id": "dark", "text": "Dancing in the Dark – Bruce Springsteen", "popularity": 0.7},
    {"id": "bridge", "text": "Under the Bridge – Red Hot Chili Peppers", "popularity": 0.75, "abbreviations": ["RHCP"]},
]
index = Index.from_documents(docs)   # in memory

for query in ["danc", "RHCP", "bohemain rapsody", "queen"]:
    print(query, [(s.text, s.kind, round(s.score, 3)) for s in index.complete(query, limit=3)])
danc [('Dancing Queen – ABBA', 'prefix', 0.547), ('Dancing in the Dark – Bruce Springsteen', 'prefix', 0.462)]
RHCP [('Under the Bridge – Red Hot Chili Peppers', 'abbreviation', 0.486)]
bohemain rapsody [('Bohemian Rhapsody – Queen', 'fuzzy', 0.186)]
queen [('Bohemian Rhapsody – Queen', 'infix', 0.356), ('Dancing Queen – ABBA', 'infix', 0.329)]

Each suggestion carries its id (an int or the string you gave), text, score, kind, layer (the index it came from, in a layered search), and highlights: character ranges of the text that matched, ready to render in bold.

top = index.complete("danc")[0]
[top.text[a:b] for a, b in top.highlights]   # ['Danc']

A database keeps named indexes in a directory or bucket. A transaction commits a new version, and an engine from the database serves it, loading newer versions by itself every sync_every seconds (5 by default):

db = completr.connect("./data")   # or "s3://bucket/prefix", "gs://...", "az://...", "memory://"
txn = db.begin()
txn.append("songs", docs)   # upserts; deletes=[...] removes ids
txn.commit()

engine = db.engine()
engine.complete("danc", ["songs"])   # [Suggestion(id='dancing', ...), Suggestion(id='dark', ...)]

Other processes that open the same database and take an engine see the commit within sync_every seconds; engine.sync() loads it at once.

Rust

use std::{sync::Arc, time::Duration};
use completr::{Database, Document, Engine, Index, IndexOptions, Replica};

let docs = || [
    Document::keyed("bohemian", "Bohemian Rhapsody – Queen", 0.95).with_synonym("is this the real life"),
    Document::keyed("dancing", "Dancing Queen – ABBA", 0.85),
    Document::keyed("dark", "Dancing in the Dark – Bruce Springsteen", 0.7),
    Document::keyed("bridge", "Under the Bridge – Red Hot Chili Peppers", 0.75).with_abbreviation("RHCP"),
];
let index = Index::from_documents(docs())?;
for s in index.complete("danc", 10) {
    println!("{} {} {:.3} {:?}", s.text, s.kind.as_str(), s.score, s.highlights);
}

let database = Database::open("./data", Vec::<(String, String)>::new()).await?;
let mut txn = database.begin().await?;
txn.append_documents("songs", docs(), [])?;
txn.commit().await?;

let engine = Arc::new(Engine::new());
let replica = Arc::new(Replica::new(database, IndexOptions::default()));
replica.sync(&engine).await?;
let _follower = replica.follow(&engine, Duration::from_secs(5));   // syncs until dropped
let hits = engine.complete(&["songs"], "danc", 10);

Runnable versions: quickstart.rs and quickstart.py.

Guides

Documents

Field Type Meaning
id int or str Your identifier. String ids are hashed to a stable 64-bit id and returned as given.
text str What is completed and displayed.
popularity float Usually in [0, 1]; more popular documents rank higher.
synonyms list[str] Alternative names, matched by complete_aliases.
abbreviations list[str] Codes such as RHCP, matched exactly by complete.
contexts list[str] Tags that requests can filter on, e.g. a genre or tenant.
vector float array Optional embedding; or pass vectors= for all documents at once.

Unknown fields raise InvalidInputError, so a typo never silently drops data.

Filtering by context

Tag documents with contexts and restrict any request to them. Filtering happens while candidates are collected, so a filtered request still returns up to limit results.

index = completr.Index.from_documents([
    {"id": "dancing", "text": "Dancing Queen – ABBA", "popularity": 0.85, "contexts": ["pop", "disco"]},
    {"id": "dark", "text": "Dancing in the Dark – Bruce Springsteen", "popularity": 0.7, "contexts": ["rock"]},
    {"id": "ownown", "text": "Dancing On My Own – Robyn", "popularity": 0.5, "contexts": ["pop"]},
])
[s.text for s in index.complete("danc", contexts=["pop"])]
# ['Dancing Queen – ABBA', 'Dancing On My Own – Robyn']
[s.text for s in index.complete("danc", contexts=["disco", "rock"])]   # any of the contexts
# ['Dancing Queen – ABBA', 'Dancing in the Dark – Bruce Springsteen']

engine.complete(...) and hybrid_search(...) take the same contexts.

Synonyms

Synonyms are searched with complete_aliases, apart from direct matches, so an alternative name never displaces what the user typed. Suggestions carry the document's text:

index.complete_aliases("is this the real")   # [AliasSuggestion(id='bohemian', text="Bohemian Rhapsody – Queen", ...)]

Layers

One catalogue, many views. An engine searches a stack of indexes, and later layers override earlier ones per document id. A tenant, a language, a listener or an experiment gets a small index holding only what differs (edits, deletions, additions, different popularity) on top of the shared catalogue, which is built and held once:

txn = db.begin()
txn.append("radio", [{"id": "bohemian", "text": "Bohemian Rhapsody (Remastered 2011) – Queen", "popularity": 0.95},
                     {"id": "session", "text": "Dancing Queen (Live Session) – ABBA", "popularity": 0.8}],
           deletes=["killer"])   # a station's edits, exclusives and removals
txn.commit()

stack = ["catalog", "catalog/de", "radio", f"user/{user_id}", "takedowns"]
[(s.text, s.layer) for s in engine.complete("queen", stack)]
# [('Bohemian Rhapsody (Remastered 2011) – Queen', 'radio'), ('Dancing Queen – ABBA', 'catalog'),
#  ('Dancing Queen (Live Session) – ABBA', 'radio')]
  • Tenants rename, hide and add songs without a copy of the catalogue.
  • Locales raise local charts and add local songs, titles and abbreviations.
  • Listeners get their own plays ranked first, from a layer that builds in under a millisecond.
  • Promotions, takedowns and experiments are layers published atomically, with no rebuild.

Scores from every layer are on the first layer's scale, so an unchanged copy ranks exactly where it did. Five layers over 200,000 titles answer in 0.2 ms at the median. See Layers for each pattern with its output.

Semantic and hybrid completion

Documents can carry embeddings from any model. completr quantises them with TurboQuant (4 bits by default, 2 or 3 optional) and searches them with deleted and filtered-out documents masked out.

vectors = embed([d["text"] for d in docs]).astype("float32")   # shape (n, dim)
index = Index.from_documents(docs, vectors=vectors)              # or txn.append(..., vectors=vectors)

index.hybrid_search("dancing q", embed(["dancing q"])[0])                       # fused by reciprocal rank
index.hybrid_search("dancing q", embed(["dancing q"])[0], fusion="weighted")    # or "lexical_first"
index.vector_search(embed(["disco classics"])[0])                               # kind == "semantic"
Fusion Score
rrf (default) 1 / (k + lexical_rank) + 1 / (k + semantic_rank), k = 60, no calibration needed
weighted (1 - w) * lexical + w * max(semantic, 0), set semantic_weight
lexical_first lexical hits in their order, then semantic-only hits

A hybrid suggestion keeps its lexical match kind when it matched lexically, and is semantic otherwise. It also reports both source scores.

Databases on disk and in buckets

completr.connect(url) opens a versioned database in a directory or bucket, and creates a local one if it does not exist. Commits go straight to storage, durable on return; concurrent writers retry on the newer version. Engines sync themselves in a background thread.

import completr

# Any process that writes:
db = completr.connect("s3://my-bucket/completions")   # or a local path, gs://..., az://...
txn = db.begin()
txn.append("songs", [{"id": f"s{i}", "text": f"song {i}"} for i in range(10_000)], deletes=["s42"])
txn.commit()

# Every serving process: the engine picks up new versions every sync_every seconds.
engine = completr.connect("s3://my-bucket/completions", cache_dir="/var/cache/completr").engine(sync_every=5.0)
engine.complete("danc", ["songs"])

Runnable: live_updates.py.

  • Status: engine.version is the version served, and engine.sync_status the last background sync's synced_at and error.
  • Compaction: db.compact("songs") merges small segments tier by tier; an ingestor does it for you.
  • Cleanup: db.cleanup(keep_versions=10, older_than_seconds=3600) deletes old manifests, and segment files that no retained version references.
  • Many writers: db.submit(changes) queues a ChangeSet, and a lease-elected Ingestor commits queued change sets in order.
  • Forking servers: open databases and engines in each worker after a pre-forking server forks.
  • Credentials: S3 uses the standard AWS chain. Override it with options={"aws_access_key_id": ..., "aws_region": ...}, and pass cache_dir=... to keep downloaded segments on local disk.

asyncio

completr.AsyncDatabase has the same methods as a database, awaited, for FastAPI and other asyncio services. Constructing it does not block; storage opens on the first awaited call. Completions stay synchronous: they take well under a millisecond.

db = completr.AsyncDatabase("s3://my-bucket/completions")
txn = await db.begin()
txn.append("songs", [{"id": "billie", "text": "Billie Jean – Michael Jackson", "popularity": 0.9}])
await db.commit(txn)
engine = await db.engine()
engine.complete("bill", ["songs"])

See the FastAPI example.

Collections

completr.Client is a convenience layer on top: named collections with stored settings, that compact themselves after writes, report stats(), and complete synonyms below direct matches in one call. Each collection is an index of the same name.

client = completr.Client("./data")
songs = client.get_or_create_collection("songs")
songs.add([{"id": "bohemian", "text": "Bohemian Rhapsody – Queen", "popularity": 0.95, "synonyms": ["is this the real life"]}])
songs.complete("is this the real", aliases=True)   # [Suggestion(id='bohemian', ..., kind="synonym")]

It does not expose index options, the choice of fusion, or getting documents by id; client.database returns the database underneath. In Rust, completr::connect returns this client. See Collections.

Command line

The completr tool operates a database from a terminal or a cron job. Every command takes the database URL first (or COMPLETR_URL).

cargo install completr-cli

completr s3://my-bucket/completions import songs songs.jsonl   # JSON Lines documents
completr s3://my-bucket/completions complete songs "danc" --contexts pop
completr s3://my-bucket/completions inspect                    # versions, indexes, sizes
completr s3://my-bucket/completions compact songs
completr s3://my-bucket/completions cleanup --keep-versions 10
completr s3://my-bucket/completions ingest --interval 1         # run an ingestor

Engine events are logged to stderr; set COMPLETR_LOG=completr=debug for more.

Errors

Every error derives from completr.CompletrError: ConflictError, CorruptionError, NotFoundError, InvalidInputError (also a ValueError) and StorageError (also an OSError).

Configuration

Where Settings
connect(...) options, cache_dir, and the build options min_word_chars, max_edit_distance, fuzzy_prefix_chars, vector_bits, compact_keys, build_threads
db.engine(...) sync_every, group_separator, overfetch, and the index options popularity_weight, short_query_chars, short_query_limit, short_query_cache_entries, vector_threads
complete(...), hybrid_search(...) limit, contexts; fusion, rrf_k, semantic_weight, candidates
db.compact(...), db.cleanup(...), Ingestor(...) fanout, max_segments, max_hidden_fraction; keep_versions, older_than_seconds; lease_ttl_seconds, max_change_sets

In Rust, BuildOptions, IndexOptions, SearchOptions, HybridOptions, CompactionPolicy and CleanupPolicy expose the same settings through chainable setters, e.g. SearchOptions::new(5).contexts(["pop"]). The configuration guide lists every setting, including the collections layer's.

Benchmarks

Against other engines. On five corpora, from 124,440 Hacker News titles to all 40 million MusicBrainz recordings, 39.6 million Amazon search terms and 41.7 million Open Library works, typed character by character, completr ranks the wanted title best of tantivy, Typesense and Meilisearch in 19 of 20 comparisons (popular and uniformly drawn targets, typed cleanly and with a typo). On 20,000 prefixes Amazon's users really typed, it has the searched term in its top 10 for 28.5% of them, against 25.2% for Meilisearch and 23.8% for tantivy. In process it answers 40 million MusicBrainz recordings in 1.5 to 3.0 ms at the median, with every p99 below every other engine's, and serves 1,355 queries per second on 8 threads, 14 times tantivy. Its index is the smallest on every corpus above HN (MusicBrainz: 3.1 GB, against 5.9 GB for tantivy and 39.5 GB for Meilisearch). tantivy still indexes the two largest corpora faster. Full tables, a capability comparison, where the bytes go, settings and caveats are in docs/benchmarks.md; the harness is in bench/.

On a synthetic corpus.

A synthetic corpus of 200,000 documents (1 to 4 words from a 30,000-word vocabulary, Zipf-distributed), on one core of an Apple M1 Pro. Reproduce with cargo run --release -p completr --example bench -- 200000 --vectors.

Step Result
Build a segment 188 ms, 5.6 MB
Open a segment (memory-mapped) 0.2 ms
Build a delta segment of 1,000 upserts 3.7 ms
Query, limit 10 p50 p99
Every prefix of 2,000 titles, as typed (33,744 queries) 0.08 ms 2.6 ms
The same, with the short-query cache (default) 0.05 ms 0.51 ms
The same, over a base plus a delta segment 0.12 ms 3.4 ms
One-edit typos 0.21 ms 1.1 ms
Vector search, 256-d, 4-bit 1.1 ms 1.2 ms
Hybrid search (RRF) 1.3 ms 3.7 ms

The vector rows come from the same run with --vectors, whose segment is 32.8 MB.

One- and two-character prefixes, which match large parts of the corpus, dominate the tail. The short-query cache serves them, and replicas carry its hottest entries across index versions.

Guarantees and testing

  • Determinism: results depend only on the documents and settings, not on how the index was segmented, compacted or queried concurrently. The tests re-run queries sampled under concurrent updates, on the same snapshot and on a freshly built index, and require bit-identical output.
  • Concurrency: readers never block. New index versions are published atomically, and a reader keeps the version it started with.
  • Integrity: every segment ends with an xxh3 checksum. Segment::open checks a local file's structure only; Segment::verify, Segment::from_bytes and downloads into a store's cache check the checksum and every section. Stable-Rust fuzz tests feed in truncated, bit-flipped and garbage segments, random Unicode queries and corrupted manifests.
  • Memory: replicas replace indexes group by group, and release old segments before loading the next group. In a soak test over thousands of versions, serving memory stayed flat.
cargo test --release -p completr --features store          # unit, database, concurrency and fuzz tests
COMPLETR_FUZZ_ITERS=1000000 cargo test --release -p completr --features store --test fuzz

Non-features

completr does one job. It deliberately does not include:

  • a server or HTTP API; it is serverless by design, so expose it through your own API if you need one;
  • full-text search over long documents, filtering or faceting;
  • multi-field schemas; each document has one text, plus aliases and an optional embedding;
  • built-in embedding models; bring vectors from any model;
  • sharding across machines; one index is expected to fit on one machine, memory-mapped.

FAQ

What does "serverless" mean here? The same as for LanceDB: there is no completr server. The engine is a library in your process, and the database is a set of files in a bucket or directory. Your application is still deployed however you like, on containers, VMs or functions; completr adds no extra service to it.

How does completr differ from Elasticsearch, OpenSearch, Typesense or Meilisearch? Those are search servers for documents with many fields, filters and facets: you run and scale a cluster, and every query crosses the network. completr is serverless and does autocompletion only: it runs inside your process, and ranks the match kinds a completion box needs (abbreviations, spelling correction, word decomposition) together with popularity. Many applications use both: a search server for the results page, completr for the box.

How do several writers avoid conflicts without a server? Through the store. Commits create the next manifest create-only, so exactly one writer wins each version and the others rebase and retry. For high write rates, processes can instead submit change sets to an inbox, and a single Ingestor elected by an expiring lease commits them in order. Every commit carries the lease generation as a fencing token, so an ingestor that lost its lease cannot commit.

How does it differ from an FST or trie library? fst and marisa-trie are excellent key dictionaries, and completr uses the same ideas internally. On top of them it adds scoring, typo tolerance, abbreviations, semantic search, updates without rebuilding, and storage.

Which languages does it support? Text is normalised with Unicode lowercasing and split on Unicode whitespace, so any language written with spaces works as it is. For scripts written without spaces, such as Chinese and Japanese, pass text segmented into words to get infix matching.

How large can an index be? A segment is memory-mapped and costs roughly 100 bytes per short title, plus about 136 bytes per 256-d vector at 4 bits. Hundreds of thousands to a few million documents per index fit comfortably on one machine.

Why the name? completr is said "completer": it completes what people type, and the missing vowel is a nod to search-engine names such as Solr. Its wordmark shows the name being completed as you type it.

How it works

A segment stores its documents in zstd-compressed blocks, and its keys in three dictionaries: titles, title words and aliases. SymSpell delete variants for spelling correction are hashed into buckets of word ordinals. Popularity and title length are kept in aligned columns, and postings are bit-packed. Queries run on primitives merged across segments (cursor merges over the sorted dictionaries), so an index of many segments ranks exactly like a single one. See docs/architecture.md for the format, the ranking and the database protocol.

Status

completr is young. The on-disk format is versioned and checked on load, but it and the API may still change before 1.0. Feedback and issues are very welcome.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md and the Code of Conduct. To report a vulnerability, see SECURITY.md.

Acknowledgements

completr builds on excellent work: fst by Andrew Gallant, rapidfuzz, turbovec, object_store, zstd and PyO3. Its trie design is inspired by marisa-trie, its spelling correction and word decomposition by SymSpell, and its database protocol by Lance. The wordmark and demo use outlines of Space Grotesk and Source Sans 3.

License

MIT. Developed and maintained by Saiful Islam.

Metadata

Release files for completr 0.1.0

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

Source distribution (sdist)

Source distribution for completr 0.1.0
File Size Uploaded
completr-0.1.0.tar.gz 202.1 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for completr 0.1.0
File
completr-0.1.0-cp311-abi3-musllinux_1_2_x86_64.whl CPython 3.11 abi3 Linux musl 1.2+ x86-64 Details
completr-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details
completr-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
completr-0.1.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
completr-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 103.5 MB

Release files / completr-0.1.0.tar.gz

Download URL completr-0.1.0.tar.gz
Size 202.1 kB
Tags Source
SHA-256 checksum
How to use checksums
138c3ce5fd90feb9af253cb2d5577397a9656ce4f413cc9454227dc332fd1701
BLAKE2b-256 checksum
How to use checksums
64a8e29ad28afc1b11a87fc12720d8bd37c57d9d62457fbb396dd1beb922c484
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 Oct 4, 2026.

Transparency log

Release files / completr-0.1.0-cp311-abi3-musllinux_1_2_x86_64.whl

Download URL completr-0.1.0-cp311-abi3-musllinux_1_2_x86_64.whl
Size 28.9 MB
Tags CPython 3.11 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
c1e1203624aac95e59f1b47934a360a87d2144ff19f0f8af5e1d05c76c5a7e3f
BLAKE2b-256 checksum
How to use checksums
a48c9d488a331000fc90d0521ae62874245b0482203f43ef291f20260e316616
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 Oct 4, 2026.

Transparency log

Release files / completr-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL completr-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl
Size 26.8 MB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
8052eecf2026d54fe358c2d5aafc55b4c3cdaf2de35c1d909411a4896fbf2300
BLAKE2b-256 checksum
How to use checksums
00c6639314793b3bbe92265c821726be158fdf0d0fb3ad113bf67f551193d8ff
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 Oct 4, 2026.

Transparency log

Release files / completr-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL completr-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 31.7 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
85da2df4f5a7a33616601d742b197317cfd6d5b4fd9c1462f30f69b3a32430d2
BLAKE2b-256 checksum
How to use checksums
1c93f60b9214e092bb0365641cd42c06af57031680868b7dedbf6d72f3d6482d
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 Oct 4, 2026.

Transparency log

Release files / completr-0.1.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL completr-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
Size 7.4 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
b094c0cd73c417e454863dd67e9d409aecaa0881765087862d93ccfd2b4856d8
BLAKE2b-256 checksum
How to use checksums
555dc55e68144e7390f77b345c27793640a56ad090346d3adbbdba267b24b5c9
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 Oct 4, 2026.

Transparency log

Release files / completr-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl

Download URL completr-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl
Size 8.5 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
3360e99db26f706a3413845376bb19f54e29b1de7808cc54ec028c96f29e012e
BLAKE2b-256 checksum
How to use checksums
00fc6d1138d1803258f573ecfd751dc9e2df3bf09be9bb0244f79ba8f4ab49b1
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 Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

6 release files

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