-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal for supporting ancestor keys in fixtures #3
base: develop
Are you sure you want to change the base?
Conversation
Thanks a lot, John! I was imagining in turning the JSON loader inside out so that ancestors would be .put() before their children, allowing ancestor/children to be defined using the same syntax as non-ancestor children.
Would you mind splitting the postprocessor fix and the README update as separate pull requests so we can discuss ancestors a little more before we go this way or the other? My children key seems to me (obviously) more natural (the JSON itself is a hierarchy) but is a lot more work than your approach and I'd like to mature both ideas before we commit to The One True Way of doing ancestors. |
Hi! I've created the two separate pull requests for the README and post_processor changes. Hmm one potential issue with the nested way of defining ancestors/children is that two entities can't share the same parent/child, as each will have its own 'copy' of its parent/child. Also, I just realized while testing this that the ancestor entities don't actually need to be saved first before any of its descendants. Setting an entity's parent to a key with no value is perfectly valid, although querying its parent later on would fail. EDIT: My proposal would be to something like:
|
Not sure. The original idea I had was to use the Once you save an entity to the datastore, you cannot change its ancestor. If we want to be able not to specify a key, we need it |
Ah right, that handles the multiple descendants scenario. Hmm but how would entities that share the same
Ah yes, that would be one of the requirements with my proposal, that keys need to be explicitly specified if you want to use it as a parent/child somewhere (which for me isn't so bad, since keys are easy enough to define). Also, it helps keep your fixtures clean by allowing to keep entities of different kinds in separate fixture files. e.g.:
Downsides though is that it would only work with NDB and would introduce backward incompatible changes. Thanks! |
I have no big problem with being backward-incompatible. This tool is very new and not many people are using it. I'm not sure of what you meant by "how would entities that share the same KeyProperty references be defined?". Using the same syntax we use for non-ancestor references, we simply have a list of objects (that could be of multiple kinds) under the There are reasons to keep different kinds on different files, but having explicit identifiers referring data on different files will introduce inter-file dependencies - it would make no sense to import the children if you do not import their parents before. |
I mean something like this:
|
You are right. In this case you'd have to model Spot as the parent Pet and John and Jane as the In any case, let's, for now, include a This way we'd have::
equivalent to:
Maybe it'd be better to rename |
Yes, having
I agree. So for scenarios where a nested definition of KeyProperty references is a better fit, the (Would the |
Since We should probably throw an error. |
If ancestor keys are desired, then the whole ancestor path will need to be defined explicitly in the fixture data. Custom keys are specified by the `'_key'` special attribute with its value being an array of kind and id pairs. The array will need to have an even number of elements (the same specs as defined here https://cloud.google.com/appengine/docs/python/ndb/entities) e.g. [{ ... "_key": ["ParentKind", "parent_id", "SomeKind", "some_id"] }]
Hello! I pushed some updates (rebased from recent So with these changes, Also added support for Somewhat off-topic, but one thing I'm confused about the e.g. for this definition
At a glance, one would think that "John" has an "owner" KeyProperty with value of "Fido"'s key. But in fact it is the reverse, it is "Fido" that has an "owner" KeyProperty with "John" as the value. |
We can avoid the delete-and-recreate-with-key issue by parsing the whole JSON into an in-memory list and creating all objects from the top-down (rather than bottom-up as json.load seems to do) so that keys are always available by the time you create the children. I've been reluctant to do this because simply invoking json.load is very concise and I have a somewhat misguided preference for loading things as they are needed rather than doing so upfront. This is a rather foolish take on the problem because these JSON files are not meant to become too large (even though I am using them to store initial application state). I'll give that top-down approach a spin. From there, it should be easy to hook up a simpler version of your code without the create-delete-recreate part. |
|
Just made some additions. |
If ancestor keys are desired, then the whole ancestor
path will need to be defined explicitly in the fixture data.
Custom keys are specified by the
'__key__'
special attribute withits value being an array of kind and id pairs. The array will
need to have an even number of elements (the same specs
as defined here https://cloud.google.com/appengine/docs/python/ndb/entities)
e.g.
P.S.
on line # 59 in
loader.py
, I moved thepost_processor(obj)
call to outside of thefor
loop (I believe this was a bug? As calling thepost_processor
in the loop would trigger it for each attribute. Let me know if that was intended instead.)EDIT: After reviewing, it seems
__key__
(instead of_key
) would be a better attribute name?