views:

132

answers:

3

I want to be able to take a dynamically created string, say "Pigeon" and determine at runtime whether Google App Engine has a Model class defined in this project named "Pigeon". If "Pigeon" is the name of a existant model class, I would like to then get a reference to the Pigeon class so defined.

Also, I don't want to use eval at all, since the dynamic string "Pigeon" in this case, comes from outside.

+1  A: 

You could try, although probably very, very bad practice:

def get_class_instance(nm) :
    try :
        return eval(nm+'()')
    except :
        return None

Also, to make that safer, you could give eval a locals hash: eval(nm+'()', {'Pigeon':pigeon})

I'm not sure if that would work, and it definitely has an issue: if there is a function called the value of nm, it would return that:

def Pigeon() :
    return "Pigeon"
print(get_class_instance('Pigeon')) # >> 'Pigeon'

EDIT: Another way of doing it is possibly (untested), if you know the module:
(Sorry, I keep forgetting it's not obj.hasattr, its hasattr(obj)!)

import models as m
def get_class_instance(nm) :
    if hasattr(m, nm) :
        return getattr(m, nm)()
    else : return None

EDIT 2: Yes, it does work! Woo!

Lucas Jones
Yeah, I should have also specified, I don't want to be using eval at all, since "Pigeon" could come from outside.
Stephen Cagle
Affitmative. (Stupid comment min. length - I would have just said "OK.") :D
Lucas Jones
eval is completely unecessary here.
Nick Johnson
*was*. I forgot the second way when I first wrote the post, and left it there for posterity.
Lucas Jones
+1  A: 

Actually, looking through the source code and interweb, I found a undocumented method that seems to fit the bill.

from google.appengine.ext import db

key = "ModelObject" #This is a dynamically generated string

klass = db.class_for_kind(key)

This method will throw a descriptive exception if the class does not exist, so you should probably catch it if the key string comes from the outside.

Stephen Cagle
A: 

There's two fairly easy ways to do this without relying on internal details:

Use the google.appengine.api.datastore API, like so:

from google.appengine.api import datastore

q = datastore.Query('EntityType')
if q.get(1):
  print "EntityType exists!"

The other option is to use the db.Expando class:

def GetEntityClass(entity_type):
  class Entity(db.Expando):
    @classmethod
    def kind(cls):
      return entity_type
  return Entity

cls = GetEntityClass('EntityType')
if cls.all().get():
  print "EntityType exists!"

The latter has the advantage that you can use GetEntityClass to generate an Expando class for any entity type, and interact with it the same way you would a normal class.

Nick Johnson