Skip to main content

Endless Database with pyyaml and pymongo

Project description

EndlessDB

EndlessDB is a lightweight Python wrapper around MongoDB that lets you work with databases, collections, and documents as dynamic Python objects.

It is a developer tool for scripts, prototypes, fixtures, notebooks, and debugger-friendly workflows. It is not a full ODM and does not try to hide PyMongo.

It keeps MongoDB as the source of truth while making common document access feel natural:

from endlessdb import EndlessConfiguration, EndlessDatabase


class LocalConfiguration(EndlessConfiguration):
    def override(self):
        self.MONGO_URI = "mongodb://root:root@localhost:27017/"
        self.MONGO_DATABASE = "example"


LocalConfiguration.apply()

db = EndlessDatabase()
employees = db.Employee

employees["john"] = {"Name": "John", "Age": 25}
employees["john"].Age = 26

print(employees["john"].Name)
print(employees["john"]().to_dict())

Features

  • Dynamic wrappers for MongoDB databases, collections, and documents.
  • Attribute and item access for collections and document fields.
  • Dot-path writes for nested document values.
  • Lazy document wrappers for paths that do not exist until written.
  • Strict mode for typo-safe attribute access when you do not want virtual paths.
  • Mongo-backed updates for collection items and document properties.
  • Explicit patch, replace, unset, and delete operations.
  • Query helpers for filters, sorting, limits, offsets, counts, existence checks, and raw PyMongo access.
  • Document references stored as DBRef-compatible values.
  • Dictionary, JSON, and YAML serialization helpers.
  • YAML-based default documents.
  • Access to the underlying PyMongo database and collection objects when needed.
  • Debugger-friendly string representations for VS Code and other Python debuggers.

Installation

EndlessDB requires Python 3.11 or newer and a reachable MongoDB server.

Install the package from PyPI:

python -m pip install endlessdb

For local examples, you can start MongoDB with Docker Compose from this repository:

docker compose -f samples/docker-compose.yml up -d

Quick Start

Configure the MongoDB connection before creating EndlessDatabase:

from endlessdb import EndlessConfiguration, EndlessDatabase


class AppConfiguration(EndlessConfiguration):
    def override(self):
        self.MONGO_URI = "mongodb://root:root@localhost:27017/"
        self.MONGO_DATABASE = "app"


AppConfiguration.apply()

db = EndlessDatabase()

Collections are available through attributes or item access:

employees = db.Employee
same_collection = db["Employee"]

Documents are addressed by MongoDB _id:

employees["john"] = {"Name": "John", "Age": 25}
john = employees["john"]

Fields can be read and written through attributes or item paths:

john.Age = 26
john["Profile.City"] = "New York"

assert john.Age == 26
assert john.Profile.City == "New York"

Object Model

EndlessDB exposes public wrappers for everyday use:

  • EndlessDatabase represents a MongoDB database.
  • EndlessCollection represents a MongoDB collection.
  • EndlessDocument represents a MongoDB document or nested document path.

Calling a wrapper returns its logic container. Logic containers expose metadata, lower-level Mongo objects, serialization, reload, and delete operations:

db = EndlessDatabase()
collection = db.Employee
document = collection["john"]

print(collection().key())
print(document().path(True))
print(document().mongo())

This split keeps application code compact while still making lower-level operations available when you need them.

Configuration

EndlessConfiguration controls the default MongoDB connection, database name, config collection, and YAML defaults file.

class AppConfiguration(EndlessConfiguration):
    def override(self):
        self.CONFIG_YML = "config.yml"
        self.CONFIG_COLLECTION = "config"
        self.MONGO_URI = "mongodb://root:root@localhost:27017/"
        self.MONGO_DATABASE = "app"

You can also pass connection values directly when creating a database:

db = EndlessDatabase(
    url="mongodb://root:root@localhost:27017/",
    database="app",
)

Use strict mode when missing collections, documents, or fields should raise PropertyNotFoundError instead of creating virtual wrappers:

db = EndlessDatabase(
    url="mongodb://root:root@localhost:27017/app",
    strict=True,
)

References

Assigning one EndlessDocument to another document field stores a reference-like value in MongoDB. When the document is loaded again, EndlessDB resolves it back to an EndlessDocument wrapper.

departments = db.Department
departments["it"] = {"Name": "IT"}

employees["john"].Department = departments["it"]

assert employees["john"].Department == departments["it"]

Querying

Use find_one() and find() from the collection logic container for Mongo-style filters:

employees["john"] = {"Name": "John", "Age": 26}
employees["jane"] = {"Name": "Jane", "Age": 31}

match = employees().find_one({"Name": "Jane"})
matches = list(
    employees().find(
        {"Age": {"$gte": 25}},
        sort=[("Age", -1)],
        limit=10,
    )
)

find() returns an iterator of EndlessDocument objects. The collection logic also exposes count(), exists(), first(), and raw() for direct PyMongo collection access.

Updating And Deleting

Item assignment keeps patch-compatible $set behavior:

employees["john"] = {"Name": "John", "Age": 25}
employees["john"] = {"Age": 26}

Use explicit methods when the difference matters:

employees().patch("john", {"Role": "developer"})
employees().replace("john", {"Name": "John", "Status": "active"})
employees["john"]().unset("Profile.City")
employees["john"].Profile().delete()

Root document deletion remains explicit:

employees["john"]().delete()

Serialization

Logic containers can export data to dictionaries, JSON, or YAML. Use iter_items() when you need lazy key/value traversal.

data = employees["john"]().to_dict()
items = list(employees["john"]().iter_items())
json_text = employees["john"]().to_json()
yaml_text = employees().to_yml()

Bytes are base64 encoded for JSON. date and datetime values are encoded in ISO format.

YAML Defaults

EndlessDB can load default collections and documents from YAML. This is useful for sample data, local application defaults, and repeatable test fixtures.

Employee:
  john:
    Name: John
    Age: 25

Set CONFIG_YML in your configuration class, then create EndlessDatabase() as usual.

Samples

The samples directory contains runnable examples for the main workflows:

  • quickstart collection and document writes;
  • nested dot-path updates;
  • document references;
  • JSON, base64 JSON, and YAML serialization;
  • YAML defaults loading;
  • debugger-friendly representations;
  • strict mode;
  • query helpers;
  • patch, replace, unset, and delete behavior;
  • small storage CLI and notebook app examples.

Run a sample from the repository root:

docker compose -f samples/docker-compose.yml up -d
python -m pip install -e .
python samples\01_quickstart.py

For a fuller walkthrough of the public API, see docs/usage.md.

Project Status

EndlessDB 0.5.x is focused on making the dynamic MongoDB facade safer and clearer while keeping it small. The current API includes strict mode, dictionary-returning serialization, query helpers, explicit patch/replace semantics, field unset/delete helpers, runnable samples, CI, Ruff checks, and coverage reporting.

Future improvements are intentionally narrow: formatter/type-checking workflow, more negative-path coverage, and better public type hints where they help without hiding the dynamic API.

Development

Create a local virtual environment and install development dependencies:

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt

Start the integration MongoDB instance:

docker compose -f tests/docker-compose.yml up -d

Run the test suite:

.\.venv\Scripts\python.exe -m pytest tests

Run lint checks:

.\.venv\Scripts\python.exe -m ruff check src tests samples
.\.venv\Scripts\python.exe -m ruff format --check src tests samples

Pytest writes a terminal coverage summary and coverage.xml through pytest-cov; the current baseline gate is 70%.

Format Python files with Ruff when needed:

.\.venv\Scripts\python.exe -m ruff format src tests samples

Build the package locally:

.\.venv\Scripts\python.exe -m build

GitHub Actions runs tests against Python 3.11, 3.12, and 3.13 with a MongoDB service container, then builds and checks the package distributions.

To create a GitHub Release, commit the version change first, then create and push a v<version> tag. The release workflow verifies that the tag matches pyproject.toml, runs tests, builds the wheel and source distribution, checks them with Twine, and attaches the artifacts to the GitHub Release:

.\scripts\create-github-release-tag.ps1

License

EndlessDB is licensed under the Apache License 2.0. See LICENSE.txt for details.

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

endlessdb-0.5.2.tar.gz (26.3 kB view details)

Uploaded Source

Built Distribution

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

endlessdb-0.5.2-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file endlessdb-0.5.2.tar.gz.

File metadata

  • Download URL: endlessdb-0.5.2.tar.gz
  • Upload date:
  • Size: 26.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for endlessdb-0.5.2.tar.gz
Algorithm Hash digest
SHA256 7d1c3f88e3f152e4ce73c626099f9a1512f7b46c1ff2ad0acbc66ab6bc822fcc
MD5 b18de1302e744420909d8925a6abfb51
BLAKE2b-256 55cc22eb5cd0f2400d13997b405dc996eba578292bf110c0f0028e389e236fe5

See more details on using hashes here.

File details

Details for the file endlessdb-0.5.2-py3-none-any.whl.

File metadata

  • Download URL: endlessdb-0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 21.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for endlessdb-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 03af3941b8e23b99b3bb3be950c0794aaab522fc53437c50c0f471a5904dabb0
MD5 71210ece3777f24eeeee579e5b31fb1c
BLAKE2b-256 0c659fb76131c18093435b2b7e80056cfb6593cde3b052204dd76eee8615fcb7

See more details on using hashes here.

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