Skip to main content

Attribute-based item lookup and filtering for Python collections

Project description

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


Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vcti_lookup-1.0.2.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vcti_lookup-1.0.2-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file vcti_lookup-1.0.2.tar.gz.

File metadata

  • Download URL: vcti_lookup-1.0.2.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vcti_lookup-1.0.2.tar.gz
Algorithm Hash digest
SHA256 850adbfb7360f02332ee8364367ca113bb6c82883ff3fb94dce33df3dc473c0e
MD5 1b385dc02e8fd7faaa40f093005d53cd
BLAKE2b-256 61e5bb0ada04f9f30623abff0415da873652562ca7d368fa55d411b1bedb2346

See more details on using hashes here.

Provenance

The following attestation bundles were made for vcti_lookup-1.0.2.tar.gz:

Publisher: publish.yml on vcollab/vcti-python-lookup

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vcti_lookup-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: vcti_lookup-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vcti_lookup-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 94f7524ee5fce53a454e8a3f033628d19afc7c9cf2a79313b7d9391c8e55f0cb
MD5 e33e6b862b3f8e09a106d117ad19fdea
BLAKE2b-256 f3a8205004c570638df5b22f8907761e189f3c221f09f4ec0e17093d1916a743

See more details on using hashes here.

Provenance

The following attestation bundles were made for vcti_lookup-1.0.2-py3-none-any.whl:

Publisher: publish.yml on vcollab/vcti-python-lookup

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page