5

In Google App Engine, using NDB, how can an entire namespace be entirely removed?

The following code removes all entities:

def delete(namespace):

    namespace_manager.set_namespace(namespace)

    for kind in ndb.metadata.get_kinds():
        keys = [ k for k in ndb.Query(kind=kind).iter(keys_only=True) ]
        ndb.delete_multi( keys )

However, on the dev server, the namespace is still there when calling:

ndb.metadata.get_namespaces()

and, in production, exceptions are raised when trying to delete system kind, for example:

illegal key.path.element.type: __Stat_Ns_Kind__

How can a namespace be wiped out entirely?

As pointed out by @jeremydw, namespace information is stored in a __namespace__ kind. However, this does not behave as a normal kind and in particular, deleting entities does not seem to have any effect:

id_namepace = 'some_test'

print list( ndb.Query(kind='__namespace__') ) 
# id_namespace is not present
# SomeModel is some existing model
key_entity = ndb.Key('SomeModel', 'some_string_id', namespace=id_namepace)
entity = datastore.CustomerAction(key=key_entity)
entity.put()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is present (expected, namespace was implicitly created by adding one entity in it)
key_entity.delete()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is present (expected, namespace still exists but contains no entities)
key_namespace = ndb.metadata.Namespace.key_for_namespace(id_namepace)
key_namespace.delete()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is still present (not expected, kind='__namespace__' does not behave as a normal kind)

1 Answers1

1

Looking at the actual implementation of ndb.metadata.get_namespaces in the SDK (https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/ndb/metadata.py#224), it looks like the list of namespaces is stored in Datastore itself, in a model named Namespace with kind __namespace__.

While I haven't attempted this ever myself, perhaps you can find the corresponding entity in the Datastore for the namespace that you want to obliterate, and then delete it. Then, next time you call ndb.metadata.get_namespaces, the query results should not include the entity for the namespace that you just deleted.

jeremydw
  • 74
  • 1
  • 2
  • Yes, this is something that could work. However I am not very comfortable messing with undocumented reserved system names. These might not behave as "normal" entities. For example, I cannot delete __Stat_Ns_Kind__ (see my question). I'll give it a shot anyway and report back. Thanks! – Eric PICHON Sep 15 '13 at 07:07
  • It looks like `__namespace__` does not behave as a normal kind. In particular deleting entities has no effect. – Eric PICHON Sep 16 '13 at 08:59
  • (added code snippet in question, direct modification of `__namespace__` does not work) – Eric PICHON Sep 16 '13 at 09:05