Skip to content
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

Adding script to enable clearing datastore. #369

Merged
merged 2 commits into from
Nov 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ Running Regression Tests

$ python regression/populate_datastore.py

- If you make a mistake during development (i.e. a failing test that
prevents clean-up) you can clear all regression data from your
datastore instance via::

$ python regression/clear_datastore.py

This comment was marked as spam.

This comment was marked as spam.

Test Coverage
-------------

Expand Down
92 changes: 92 additions & 0 deletions regression/clear_datastore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""Script to populate datastore with regression test data."""


# This assumes the command is being run via tox hence the
# repository root is the current directory.
from regression import regression_utils


FETCH_MAX = 20
ALL_KINDS = [
'Character',
'Company',
'Kind',
'Person',
'Post',
]
TRANSACTION_MAX_GROUPS = 5


def fetch_keys(dataset, kind, fetch_max=FETCH_MAX, query=None):
if query is None:
query = dataset.query(kind=kind).limit(
fetch_max).projection(['__key__'])
# Make new query with start cursor if a previously set cursor
# exists.
if query._cursor is not None:
query = query.with_cursor(query.cursor())

return query, query.fetch()

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.



def get_ancestors(entities):
# NOTE: A key will always have at least one path element.
key_roots = [entity.key().path()[0] for entity in entities]
# Turn into hashable type so we can use set to get unique roots.
# Also sorted the items() to ensure uniqueness.
key_roots = [tuple(sorted(root.items())) for root in key_roots]
# Cast back to dictionary.
return [dict(root) for root in set(key_roots)]


def delete_entities(dataset, entities):
dataset_id = dataset.id()
connection = dataset.connection()

key_pbs = [entity.key().to_protobuf() for entity in entities]
connection.delete_entities(dataset_id, key_pbs)


def remove_kind(dataset, kind):
delete_outside_transaction = False
with dataset.transaction():
results = []

query, curr_results = fetch_keys(dataset, kind)
results.extend(curr_results)
while curr_results:
query, curr_results = fetch_keys(dataset, kind, query=query)
results.extend(curr_results)

if not results:
return

# Now that we have all results, we seek to delete.
print 'Deleting keys:'
print results

ancestors = get_ancestors(results)
if len(ancestors) > TRANSACTION_MAX_GROUPS:
delete_outside_transaction = True
else:
delete_entities(dataset, results)

if delete_outside_transaction:
delete_entities(dataset, results)


def remove_all_entities():
print 'This command will remove all entities for the following kinds:'
print '\n'.join(['- ' + val for val in ALL_KINDS])
response = raw_input('Is this OK [y/n]? ')
if response.lower() != 'y':
print 'Doing nothing.'
return

dataset = regression_utils.get_dataset()
for kind in ALL_KINDS:
remove_kind(dataset, kind)


if __name__ == '__main__':
remove_all_entities()