Previously, when reading a LazyReferenceField from the DB, it was stored
internally in the parent document's _data field as an ObjectId. However, this
meant that equality tests using an enclosing EmbeddedDocument would not return
True when the EmbeddedDocument being compared to contained a DBRef or Document
in _data. Enclosing Documents were largely unaffected because they look at the
primary key for equality (which EmbeddedDocuments lack).
This makes the internal Python representation of a LazyReferenceField (before
the LazyReference itself has been constructed) a DBRef, using code identical to
ReferenceField.
Previous implementation of `Document._object_key` was *pretending* to work on
MongoEngine-level fields (e.g. using "pk" instead of "_id" and separating
nested field parts by "__" instead of "."), but then it was also attempting to
transform field names from the `shard_key` into DB-level fields.
This, expectedly, didn't really work well. Most of the test cases added in this
commit were failing prior to the code fixes.
This commit:
1. Formats all of our existing code using `black`.
2. Adds a note about using `black` to `CONTRIBUTING.rst`.
3. Runs `black --check` as part of CI (failing builds that aren't properly formatted).
For example, if you had the following class:
```
class Person(Document):
name = StringField()
age = IntField()
```
You could instantiate an object of such class by doing one of the following:
1. `new_person = Person('Tom', 30)`
2. `new_person = Person('Tom', age=30)`
3. `new_person = Person(name='Tom', age=30)`
From now on, only option (3) is allowed.
Supporting positional arguments may sound like a reasonable idea in this
heavily simplified example, but in real life it's almost never what you want
(especially if you use inheritance in your document definitions) and it may
lead to ugly bugs. We should not rely on the *order* of fields to match a given
value to a given name.
This also helps us simplify the code e.g. by dropping the confusing (and
undocumented) `BaseDocument._auto_id_field` attribute.
This more closely aligns with the rule that a single tests should test one
thing and one thing only. Previous code tested like 4 different things in a
single test and was hard to follow.