Marrow Mongo is a collection of small, focused utilities written to enhance use of the PyMongo native MongoDB driver without the overhead, glacial update cycle, complexity, and head-space requirements of stateful active mapper patterns. This project grew out of the need (both personal and commercial) to find a viable, simple, well-tested alternative to existing ODMs. We believe that Marrow Mongo hits the Goldilocks zone for a supportive MongoDB experience in Python without getting in the way, offering elegant and Pythonic approaches to document storage modelling, access, and interaction.
Explicit is better than implicit, with fields, traits, and document classes registered as
entry_pointplugins and made accessible through the standard import mechanism.
from marrow.mongo import Document, Index
from marrow.mongo.field import String
from marrow.mongo.trait import Queryable
Instantiate field objects and associate them with custom
Documentsub-classes to model your data declaratively.
model = String()
Documentinstances as attribute access mutable mappings with value typecasting, directly usable with PyMongo APIs. Attention is paid to matching Python language expectations, such as allowing instantiation using positional arguments. Values are always stored in the PyMongo-preferred MongoDB native format, and cast on attribute access as needed.
tv = Television('D50u-D1')
assert tv.model == \
tv[~Television.model] == \
tv['model'] == \
Keep information about your data model with your data model and standardize access.
__collection__ = 'tv'
model = String()
brand = String()
_model = Index('model')
collection = Television.create_collection(database)
Construct filter documents through comparison of (or method calls on) field instances accessed as class attributes.
exact = Television.model == 'D50u-D1'
prefix = Television.model.re(r'^D50\w')
tv_a = Television.find_one(exact)
tv_b = Television.find_one(prefix)
assert tv_a.model == tv_b.model == 'D50u-D1'
assert tv_a['_id'] == tv_b['_id']
Many Python active record object relational mappers (ORMs) and object document mappers (ODMs) provide a short-hand involving the transformation of named parameters into database concepts.
filter_doc = F(Television, model__ne='XY-zzy')
update_doc = U(Television, set__brand='Vizio')
tv = Television.find_one(model='D50u-D1')
assert tv.brand == 'Vizio'
position = Point(longitude, latitude)
We utilize Travis continuous integration, with test coverage reporting provided by Codecov.io. We also monitor requirements for security concerns and deprecation using Requires.io. Extensive static analysis through Landscape.io, proactive use of tools such as pre-commit with plugins such as the infosec analyzer OpenStack Bandit, and various linting tools help to keep code maintainable and secure.
Every developer has run into those objects that fail to produce sensible or useful programmers' representation, generate meaningless exception messages, or fail to provide introspective help. With more documentation in the code than code, you won't find that problem here. Code should be self-descriptive and obvious; we feel comments and docstrings are integral to this.
Changes to the library demand meditation to ensure feature creep and organic growth are kept in check. Where possible, solutions involving objects passed to standard PyMongo functions and methods are preferred to solutions involving wrapping, proxying, or middleware. All but minor changes are isolated in pull requests to aid in code review.
The MIT License is highly permissive, allowing commercial and non-commercial use, reproduction, modification, republication, redistribtution, sublicensing, and sale of the software (and associated documentation) or its components. The license notice must be included in the reproduced work, and any warranty or liability on behalf of the Marrow Open Source Collective or project contributors waived.
You are effectively free to deal in this software however you choose, without commercial hinderance.