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.

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

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

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

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.1.tar.gz (26.7 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.1-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: endlessdb-0.5.1.tar.gz
  • Upload date:
  • Size: 26.7 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.1.tar.gz
Algorithm Hash digest
SHA256 c91b55453caea5aa51ef2ac6f657793d2eeb44977205befa311cac00109341c7
MD5 87ebdf1b9ce84a69cb81ef4e5c0feaca
BLAKE2b-256 ee364c37b89fb215c9a404b088ecdd0d41692ddb5bed7edbeb1dbe63af78eaec

See more details on using hashes here.

File details

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

File metadata

  • Download URL: endlessdb-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 22.2 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 05f61f22566efa0c06126e5e1f1ca4cb800bbce659960196dc0959e43a604c1f
MD5 218376d916f55ed67d9b5882be3a3d6b
BLAKE2b-256 0469876bf0f04229a3b17ddc8b7c75855bc5b721c7d99cd871f1ba4fb3e39b50

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