2

Using Python, I'm trying to connect to my AppEngine app's remote_api handler, but I keep getting an error. What I want to do is set up the remote_api stubs to route database calls through that and access my app's datastore directly. So, first, I import the remote_api libraries, then call the ConfigureRemoteApi on the stub module, and try to use the calls to the remote datastore. Here's some sample code:

from google.appengine.ext.remote_api import remote_api_stub

def test_remote_api():
    # This function is called when I want to use the remote api instead of the local datastore access
    remote_api_stub.ConfigureRemoteApi('myapp.appspot.com', '/_ah/remote_api', auth_func, '')

def auth_func:
    # This actually returns a tuple with my credentials to skip the console input
    return ('username', 'password')

Ok, now, I've tested my login information and the app name with remote_api_shell.py, but I get an error like this:

File "C:\Program Files(x86)\Google\google_appengine\google\appengine\tools\dev_appserver_blobstore.py", line 79, in GetBlobStorage
return apiproxy_stub_map.apiproxy.GetStub('blobstore').storage
AttributeError: 'RemoteStub' object has no attribute 'storage'

And then I get a 404: Not Found from the application, which I know to be wrong since accessing the app from the Web does give me the result. What do I need to do to set up the remote_api_stub so I won't get this error?

Thanks!

Juan Carlos Coto
  • 11,900
  • 22
  • 62
  • 102
  • What are you trying to achieve? – Hans Then Sep 13 '12 at 20:06
  • I stated this on my question: "What I want to do is set up the remote_api stubs to route database calls through that and access my app's datastore directly." Also, "What do I need to do to set up the remote_api_stub so I won't get this error?". In case that doesn't make it clear, I want to be able to use the remote_api calls from _inside_ my code, not call my app code from the remote_api shell. – Juan Carlos Coto Sep 13 '12 at 21:20
  • My apologies if my question was unclear. What is the purpose of using the remote_api calls from inside your code? I think the purpose of the remote api is to be able to call your application code from outside your application. – Hans Then Sep 13 '12 at 21:25
  • this is certainly do-able. I had a project where zope/plone could write directly to the datastore by via the remote_api. And first param for ConfigureRemoteApi is the appid as per the answer below. – Tim Hoffman Sep 14 '12 at 04:31

2 Answers2

6

assuming you are using high replication datastore now...

Your app_id is probably wrong, and you also need to pass the address parameter. I whipped this up a while back while reading the oreilly book for appengine(book is severely out of date and not recommended)

def attach_to_app(app_id, user=None, password=None, path=None, address=None):
    """
    attaches to app_id instance at address (default: <app_id>.appspot.com)

    if you don't specify a user/password you will be prompted for one

    if you don't specify an address it is assumed to be
    <app_id>.appspot.com

    path: path to remote_api handler, if not
    specified, will use /_ah/remote_api 
    """
    path = path or "/_ah/remote_api"

    if not address:
        address = "%s.appspot.com" % app_id

    init_remote_api(app_id, path, address, user=user, password=password)




def auth_func():
    """
    function to prompt user for credentials
    """
    email_address = raw_input("Email Address: ")
    password = getpass.getpass("Password: ")
    return email_address, password


def init_remote_api(app_id, path, address, user=None, password=None):
    """
    generic wrapper to initialize the remoteapi for a given path

    required
    =========
    app_id : the app_id of the application to connect to
    path: the path to the remote_api handler ex: /_ah/remote_api
    address: server to connect to ex: myapp.appspot.com

    if user and password are not specified you will be prompted on
    connection if needed
    """
    if user and password:
        def my_auth():
            return (user, password)
    else:
        my_auth = auth_func

    remote_api_stub.ConfigureRemoteApi(app_id, path, my_auth, address)
    remote_api_stub.MaybeInvokeAuthentication()
    os.environ["SERVER_SOFTWARE"] = "Development (remote_api)/1.0"

# example
APP_ID = "s~myapp" # when hrds was introduced it became necessary to specify app_id and address note the "s~..."
ADDRESS = "myapp.appspot.com"
attach_to_app(APP_ID, address=ADDRESS)
Tom Willis
  • 5,250
  • 23
  • 34
  • Ok, thanks, Tom. Now, I'm getting an error and a warning that I've seen before: `BadRequestError: app s~myapp cannot access app dev~myapp's data` and `Can't open zipfile C:\Python27\lib\site-packages\setuptools-0.6c11-py2.7.egg-info: IOError: [Errno 13] file not accessible: 'C:\\Python27\\lib\\site-packages\\setuptools-0.6c11-py2.7.egg-info'`. Any ideas about this? – Juan Carlos Coto Sep 14 '12 at 19:10
  • dev~.... is an indicator that you are somehow pointing at your local dev server. what are you passing in for app_id and address? – Tom Willis Sep 14 '12 at 19:37
  • That's what I thought, but I couldn't for the life of me figure out why that's happening. This is my code: `app_id = "s~myapp"` `address = "myapp.appspot.com"` `path = "/_ah/remote_api"`. Sorry for the formatting. I am running this from my local machine, but I believe that is not the wrong way of doing it. After all, the idea is to connect from local to server. – Juan Carlos Coto Sep 14 '12 at 20:37
  • I was told `remote_api_stub` in its current form within the dev_appserver won't work because it throws away the original API stubs. In line ~601 of `/ext/remote_api/remote_api_stub.py` of the SDK, you remove `apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()` and replace both `RegisterStub` calls with `ReplaceStub` and then pass `services=['datastore_v3']` into `ConfigureRemoteApi`, it worked for me. – ebidel Oct 24 '12 at 09:34
  • As commented at [link](http://stackoverflow.com/questions/9280613/badrequesterror-app-smyapphr-cannot-access-app-devmyapphrs-data-why/9281772#9281772), you should change the default partition to avoid the "cannot access app" error. – fmatheis Jul 22 '13 at 12:55
  • @TomWillis where should I run the code to get this to work ? Is it my main.py or somewhere else ? thanks – ThomasD Jan 07 '15 at 09:33
  • @ThomasD I dont do anything with appengine anymore but IIRC, you run a python console as you normally would from the interpreter that has the sdk on the path. other than that it's normal python you put those funtions in a module and import it like anything else in python. – Tom Willis Jan 08 '15 at 18:39
  • I had to add s~ to the beginning of my application name in the --application parameter. – YoungDinosaur Apr 20 '15 at 17:51
1

If you are only interested in accesing the datastore you can avoid the stub error with the testBed:

# First, create an instance of the Testbed class.
myTestBed = testbed.Testbed()

# Then activate the testbed, which prepares the service stubs for use.
myTestBed.activate()

# Next, declare which service stubs you want to use.
myTestBed.init_blobstore_stub()
myTestBed.init_logservice_stub()
fmatheis
  • 241
  • 3
  • 8
  • Thanks. This seems to solve the problem, although sadly the AppEngine application I was working on is no longer in use. Therefore, I haven't been able to test this. +1, though. – Juan Carlos Coto Aug 27 '13 at 15:39