Lookup
Purpose
vcti-lookup provides Lookup, an attribute-based filtering engine
for Python sequences. It works at two levels:
Level 1 — Filtering. You have a sequence of items, each with an ID and attributes. Lookup lets you filter by rules and get matching items back. The items can be dicts, dataclasses, Pydantic models, numpy structured-array rows, or any object — pluggable getters control how attributes are extracted.
Level 2 — Data mapping. You have external data (a list of file
paths, a numpy array, a tree of nodes) and a separate set of
attributes describing each item. You build an attribute set where
id = index, filter with Lookup, and use the matching IDs to index
back into your data. Lookup doesn't wrap or copy your data — you
keep full control.
Level 1 — Filter directly Level 2 — Map to external data
┌──────────────┐ ┌───────────────┐
│ items │ │ your data │
│ (id + attrs) │ │ (list, array) │
└──────┬───────┘ └───────▲───────┘
│ │ indices
▼ │
┌──────────────┐ Rules ┌──────────────┐ Rules
│ Lookup │◄────── │ Lookup │◄──────
└──────┬───────┘ └──────┬───────┘
│ │
▼ ▼
matched items matching_ids()
Installation
From GitHub (recommended for development)
# Latest main branch
pip install vcti-lookup
### In `requirements.txt`
vcti-lookup>=1.0.2
### In `pyproject.toml` dependencies
```toml
dependencies = [
"vcti-lookup>=1.0.2",
]
Quick Start
Level 1 — Filter items directly
from vcti.lookup import Lookup, Rule
items = [
{"id": 1, "type": "pdf", "size": 1000},
{"id": 2, "type": "txt", "size": 200},
{"id": 3, "type": "pdf", "size": 1500},
]
lk = Lookup(items)
# Single rule
pdfs = lk.filter([Rule("type", "==", "pdf")])
# [{"id": 1, ...}, {"id": 3, ...}]
# Multiple rules (AND)
large_pdfs = lk.filter([Rule("type", "==", "pdf"), Rule("size", ">", 1200)])
# [{"id": 3, ...}]
# OR logic
result = lk.filter_any([Rule("type", "==", "pdf"), Rule("type", "==", "jpg")])
# Exclusion (complement of filter)
non_pdfs = lk.exclude([Rule("type", "==", "pdf")])
# Lookup by ID
item = lk.get(2)
# Unary operators
lk.filter([Rule("name", "is_empty")])
Level 2 — Map attributes to external data
from vcti.lookup import Lookup, Rule
# Your data — any shape, Lookup doesn't touch it
data = ["report.pdf", "notes.txt", "analysis.pdf"]
# Build attribute set — id = index into your data
attrs = [
{"id": 0, "type": "pdf", "size": 1000},
{"id": 1, "type": "txt", "size": 200},
{"id": 2, "type": "pdf", "size": 1500},
]
lk = Lookup(attrs)
indices = lk.matching_ids([Rule("type", "==", "pdf")])
# [0, 2]
# Map back to your data
results = [data[i] for i in indices]
# ["report.pdf", "analysis.pdf"]
Numpy structured arrays (direct, no copy)
import numpy as np
from vcti.lookup import Lookup, Rule
from vcti.lookup.getter import numpy_getter
dt = np.dtype([("id", "i4"), ("type", "U10"), ("value", "f8")])
arr = np.array([(0, "sensor", 3.14), (1, "actuator", 2.71)], dtype=dt)
# Pass the array directly — no conversion
lk = Lookup(arr, getter=numpy_getter, id_key="id")
indices = lk.matching_ids([Rule("type", "==", "sensor")])
# [0]
# Index back into the array
results = arr[indices]
Dataclasses
from dataclasses import dataclass
@dataclass
class File:
id: int
type: str
size: int
files = [File(1, "pdf", 1000), File(2, "txt", 200), File(3, "pdf", 1500)]
lk = Lookup(files)
result = lk.filter([Rule("type", "==", "pdf")])
# [File(1, "pdf", 1000), File(3, "pdf", 1500)]
Modifiers
Modifiers are keyword arguments forwarded to vcti-predicate. They
control comparison behaviour. Pass them as the fourth argument to
Rule.
items = [{"id": 1, "name": "Report_Q1"}, {"id": 2, "name": "report_Q2"}]
lk = Lookup(items)
# Default: case-insensitive (both match)
lk.filter([Rule("name", "^=", "report")])
# Case-sensitive via modifier (only item 1)
lk.filter([Rule("name", "^=", "Report", {"case_sensitive": True})])
# Float tolerance
lk.filter([Rule("value", "==", 3.14, {"tolerance": 0.01})])
# Regex with multiline
lk.filter([Rule("content", "~=", r"^error:", {"multiline": True})])
See patterns.md for more modifier examples.
Public API
| Name | Type | Description |
|---|---|---|
Lookup[T] |
Class | Attribute-based filtering for any sequence |
Rule |
Frozen dataclass | Filter condition (attribute, operator, value, modifiers) |
ValueGetter |
Type alias | Callable[[Any, str], Any] |
MISSING |
Sentinel | Returned by getters when attribute is absent |
auto_getter |
Function | Handles dicts and objects transparently |
dict_getter |
Function | Extracts values from dicts |
object_getter |
Function | Extracts values via getattr |
attributes_getter |
Function | Extracts values from .attributes dict |
numpy_getter |
Function | Extracts fields from numpy structured-array rows |
Lookup methods
| Method | Returns | Description |
|---|---|---|
filter(rules) |
list[T] |
Items matching ALL rules (AND) |
filter_any(rules) |
list[T] |
Items matching ANY rule (OR) |
exclude(rules) |
list[T] |
Items NOT matching all rules |
first(rules) |
T | None |
First matching item (short-circuits) |
first_any(rules) |
T | None |
First item matching any rule (short-circuits) |
first_id(rules) |
Any | None |
ID of first matching item |
matching_ids(rules) |
list[Any] |
IDs of all matching items |
count(rules) |
int |
Number of matching items (no list allocation) |
get(item_id) |
T | None |
Item by ID (O(1)) |
items |
Sequence[T] |
The underlying sequence (same reference) |
lk[i] / lk[i:j] |
T / Sequence[T] |
Index or slice access |
Dependencies
- vcti-predicate — condition evaluation engine
- numpy — optional, for
numpy_getter
Documentation
- Design — Concepts, architecture, and design decisions
- Patterns — Real-world recipes and usage patterns
- Source Guide — Implementation walkthrough
- Extending — Creating custom value getters
- API Reference — Autodoc for all modules
Metadata
Release files for vcti-lookup 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vcti_lookup-1.0.2.tar.gz | 17.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vcti_lookup-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.7 kB
Release files / vcti_lookup-1.0.2.tar.gz
| Download URL | vcti_lookup-1.0.2.tar.gz |
|---|---|
| Size | 17.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
850adbfb7360f02332ee8364367ca113bb6c82883ff3fb94dce33df3dc473c0e
|
|
BLAKE2b-256 checksum How to use checksums |
61e5bb0ada04f9f30623abff0415da873652562ca7d368fa55d411b1bedb2346
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / vcti_lookup-1.0.2-py3-none-any.whl
| Download URL | vcti_lookup-1.0.2-py3-none-any.whl |
|---|---|
| Size | 10.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
94f7524ee5fce53a454e8a3f033628d19afc7c9cf2a79313b7d9391c8e55f0cb
|
|
BLAKE2b-256 checksum How to use checksums |
f3a8205004c570638df5b22f8907761e189f3c221f09f4ec0e17093d1916a743
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency log