Skip to content

Commit 4667e10

Browse files
committed
Version bumps.
1 parent b8b05f9 commit 4667e10

File tree

3 files changed

+8
-169
lines changed

3 files changed

+8
-169
lines changed

LICENSE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright © 2016 Alice Bevan-McGregor and contributors.
1+
Copyright © 2016-2017 Alice Bevan-McGregor and contributors.
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
44

README.rst

+6-167
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,14 @@ marrow.mongo
1313
..
1414
1515

16-
17-
18-
Introduction
19-
============
20-
2116
Marrow Mongo is a collection of small, focused utilities written to enhance use of the `PyMongo native MongoDB driver
2217
<http://api.mongodb.com/python/current/>`__ without the overhead, glacial update cycle, complexity, and head-space
2318
requirements of a full active record object document mapper. Additionally, it provides a very light-weight database
2419
connection plugin for the `WebCore web framework <https://github.com/marrow/WebCore>`__ and Python standard logging
2520
adapter to emit logs to MongoDB.
2621

22+
Additional documentation is provided in the form of an `online reference manual <https://mongo.webcore.io/>`__.
23+
2724

2825
Installation
2926
============
@@ -49,166 +46,8 @@ This package has a few dependencies:
4946
* A modern (>3.2) version of the ``pymongo`` package.
5047
* The Marrow Package and Schema utility packages for plugin handling and declarative syntax support.
5148

52-
There are a few conditional, tag-based dependencies:
53-
54-
* ``development`` installs additional utilites relating to testing and contribution.
55-
* ``scripting`` pulls in the `Javascripthon <https://github.com/azazel75/metapensiero.pj>`__ Python to JavaScript
56-
transpiler to enable use of native Python function transport to MongoDB. (E.g. for use in map/reduce, stored
57-
functions, etc.)
58-
* ``logger`` requires knowledge of the local host's timezone, so pulls in ``tzlocal`` to retrieve this information.
59-
60-
Installing ``marrow.mongo`` will also install package dependencies automatically. To utilize optional tags, add them,
61-
comma separated, beween square braces. E.g. ``marrow.mongo[scripting,logger]``. On a command line this will require
62-
quoting.
63-
64-
65-
Development Version
66-
-------------------
67-
68-
|developstatus| |developcover| |develophealth| |ghsince| |issuecount| |ghfork|
69-
70-
Development takes place on `GitHub <https://github.com/>`__ in the
71-
`marrow.mongo <https://github.com/marrow/mongo/>`__ project. Issue tracking, documentation, and downloads
72-
are provided there.
73-
74-
Installing the current development version requires `Git <http://git-scm.com/>`__, a distributed source code management
75-
system. If you have Git you can run the following to download and *link* the development version into your Python
76-
runtime::
77-
78-
git clone https://github.com/marrow/mongo.git
79-
(cd mongo; python setup.py develop)
80-
81-
You can then upgrade to the latest version at any time::
82-
83-
(cd mongo; git pull; python setup.py develop)
84-
85-
If you would like to make changes and contribute them back to the project, fork the GitHub project, make your changes,
86-
and submit a pull request. This process is beyond the scope of this documentation; for more information see
87-
`GitHub's documentation <http://help.github.com/>`__.
88-
89-
90-
Documents
91-
=========
92-
93-
This package utilizes the `Marrow Schema <https://github.com/marrow/schema>`__ declarative schema toolkit and extends
94-
it to encompass MongoDB data storage concerns. You define data models by importing classes describing the various
95-
components of a collection, such as ``Document``, ``ObjectId``, or ``String``, then compose them into a declarative
96-
class model. For example, if you wanted to define a simple user account model, you would begin by importing::
97-
98-
from marrow.mongo import Index, Document
99-
from marrow.mongo.field import ObjectId, String, Number, Array
100-
101-
Defining Documents
102-
------------------
103-
104-
Now we can define our own ``Document`` subclass::
105-
106-
class Account(Document):
107-
username = String(required=True)
108-
name = String()
109-
locale = String(default='en-CA-u-tz-cator-cu-CAD', assign=True)
110-
age = Number()
111-
112-
id = ObjectId('_id', assign=True)
113-
tag = Array(String(), default=lambda: [], assign=True)
114-
115-
_username = Index('username', unique=True)
116-
117-
Broken down::
118-
119-
class Account(Document):
120-
121-
No surprises here, we subclass the Document class. This is required to utilize the metaclass that makes the
122-
declarative naming and order-presrving sequence generation work. We begin to define fields::
123-
124-
username = String(required=True)
125-
name = String()
126-
locale = String(default='en-CA-u-tz-cator-cu-CAD', assign=True)
127-
128-
Introduced here is ``required``, indicating that when generating the *validation document* for this document to
129-
ensure this field always has a value. This validation is not currently performed application-side. Also notable is the
130-
use of ``assign`` on a string field; this will assign the default value during instantiation. Then we have a different
131-
type of field::
132-
133-
age = Number()
134-
135-
This allows storage of any numeric value, either integer or floating point. Now there is the record identifier::
136-
137-
id = ObjectId('_id', assign=True)
138-
139-
Marrow Mongo does not assume your documents contain IDs; there is no separation internally between top-level documents
140-
and "embedded documents", leaving the declaration of an ID up to you. You might not always wish to use an ObjectID,
141-
either; please see MongoDB's documentation for discussion of general modelling practices. The first positional
142-
parameter for most non-complex fields is the name of the MongoDB-side field. Underscores imply an attribute is
143-
"protected" in Python, so we remap it by assigning it to just ``id``. The ``assign`` argument here ensures whenever a
144-
new ``Account`` is instantiated an ObjectID will be immediately generated and assigned.
145-
146-
Finally there is an array of tags::
147-
148-
tag = Array(String(), default=lambda: [], assign=True)
149-
150-
This combines what we've been using so far into one field. An ``Array`` is a *complex field* (a container) and as such
151-
the types of values allowed to be contained therein may be defined positionally. (If you want to override the field's
152-
database-side name, pass in a ``name`` as a keyword argument.) A default is defined as an anonymous callback function
153-
which constructs a new list on each request. The default will be executed and the result assigned automatically during
154-
initialization as per ``id`` or ``locale``.
155-
156-
Lastly we define a unique index on the username to speed up any queries involving that field::
157-
158-
_username = Index('username', unique=True)
159-
160-
161-
Instantiating Documents
162-
-----------------------
163-
164-
With a document schema defined we can now begin populating data::
165-
166-
alice = Account('amcgregor', "Alice Bevan-McGregor", age=27)
167-
print(alice.id) # Already has an ID.
168-
print(alice.id.generation_time) # This even includes the creation time.
169-
170-
As can be seen above construction accepts positional and keyword parameters. Fields will be filled, positionally, in
171-
the order they were defined, unless otherwise adjusted using the ``adjust_attribute_sequence`` decorator.
172-
173-
Assuming a ``pymongo`` collection is accessible by the variable name ``collection`` we can construct our index::
174-
175-
Account._username.create_index(collection)
176-
177-
There is no need to run this command more than once unless the collection is dropped.
178-
179-
Let's insert our record::
180-
181-
result = collection.insert_one(alice)
182-
assert result.acknowledged and result.inserted_id == alice.id
183-
184-
Yup, that's it. Instances of ``Document`` are directly usable in place of a dictionary argument to ``pymongo``
185-
methods. We then validate that the document we wanted inserted was, in fact, inserted. Using an assert in this way,
186-
this validation will not be run in production code run with the ``-O`` option passed (or ``PYTHONOPTIMIZE``
187-
environment variable set) in the invocation to Python.
188-
189-
190-
Querying Documents
191-
------------------
192-
193-
Now that we have a document stored in the database, let's retrieve it back out and get the result as an ``Account``
194-
instance::
195-
196-
record = collection.find_one(Account.username == 'amcgregor')
197-
record = Account.from_mongo(record)
198-
print(record.name) # Alice Bevan-McGregor
199-
200-
Several things are going on here. First it's important to note that Marrow Mongo isn't making the query happen for
201-
you, and does not automatically cast dictionaries to ``Document`` subclasses when querying. The first line
202-
demonstrates the native approach to building *filter documents*, the first argument to ``find`` or ``find_one``.
203-
204-
You can use standard Python comparison operators, bitwise operators, and several additional querying methods through
205-
class-level access to the defined fields. The result of one of these operations or method calls is a dictionary-like
206-
object that is the query. They may be combined through bitwise and (``&``) and bitwise or (``|``) operations, however
207-
due to Python's order of operations, individual field comparisons must be wrapped in parenthesis if combining.
208-
209-
Combining produces a new ``Ops`` instance, so it is possible to use these to pre-construct parts of queries prior to
210-
use. As a tip, it can save time (and visual clutter) to assign the document class to a short, single-character
211-
variable name to make repeated reference easier.
49+
Additional instructions on `conditional dependencies, package flags, and development version utilization
50+
<https://mongo.webcore.io/installation.html>`__ are available in the manual.
21251

21352

21453
Version History
@@ -281,12 +120,12 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
281120
:target: https://github.com/marrow/mongo/issues
282121
:alt: Github Issues
283122

284-
.. |ghsince| image:: https://img.shields.io/github/commits-since/marrow/mongo/1.1.0.svg
123+
.. |ghsince| image:: https://img.shields.io/github/commits-since/marrow/mongo/1.1.1.svg
285124
:target: https://github.com/marrow/mongo/commits/develop
286125
:alt: Changes since last release.
287126

288127
.. |ghtag| image:: https://img.shields.io/github/tag/marrow/mongo.svg
289-
:target: https://github.com/marrow/mongo/tree/1.1.0
128+
:target: https://github.com/marrow/mongo/tree/1.1.1
290129
:alt: Latest Github tagged release.
291130

292131
.. |latestversion| image:: http://img.shields.io/pypi/v/marrow.mongo.svg?style=flat

marrow/mongo/core/release.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from collections import namedtuple
88

9-
version_info = namedtuple('version_info', ('major', 'minor', 'micro', 'releaselevel', 'serial'))(1, 1, 1, 'beta', 1)
9+
version_info = namedtuple('version_info', ('major', 'minor', 'micro', 'releaselevel', 'serial'))(1, 1, 1, 'final', 0)
1010
version = ".".join([str(i) for i in version_info[:3]]) + \
1111
((version_info.releaselevel[0] + str(version_info.serial)) if version_info.releaselevel != 'final' else '')
1212

0 commit comments

Comments
 (0)