Closed Codonaut closed 6 years ago
@Codonaut Thanks for the PR! Are there other methods, either from modules
or some other package that could also throw an exception? I seem to recall others which rely on a stubbed API being available, which often isn't outside of the GAE environment (or a stubbed local environment).
If there are more, is there a way to cover them all at a higher level?
Good question-- I just took a look and get_current_module_name
also looks susceptible to a KeyError
in the case of a missing environment variable. From what I can tell the other modules functions that are used as-is in gaek all make API calls to get their results, and I think that should work even in a remote API context.
I'll fix get_current_module_name
in the same way I did get_current_version_name
There are a few functions from google.appengine.api.modules
that rely on RPC calls. Notably, those which are used to get information from modules other than the "current" one.
Examples:
Going from memory, these will raise an exception due to the modules_service_pb
not being available. I forget the exact details or exception, but it should be easy to reproduce.
I think this PR is useful regardless of whether or not it fixes all of these functions. The two KeyError
s that get raised are addressed by this diff, and fixing the other class of errors could go in another PR imo.
I guess my point is that this PR alters the intent (convenience of fewer imports) by wrapping some methods and changing their behavior. That might break things for people and it adds the responsibility of consistency -- make sure they all work offline/unstubbed. The docs would also need to be updated to make those changes clear to users. It's a lot more work, which is why I was wondering if you had ideas on how to handle all cases instead of just these few. Does that make sense?
Alternatively, we could add a convenience method to stub them all out (e.g. gaek.environment.stub_all()
)
I thought of another approach that may be a bit easier to implement, without the backwards compatible drawback.
Each pass-through method could be wrapped and renamed with _safe
or _offline
. These wrapped functions should behave the same, unless the API isn't stubbed, in which case they can return None
or another reasonable alternative.
Example:
gaek.get_modules()
>>> KeyError
gaek.get_modules_safe()
>>> None
Thoughts?
Hey Eric sorry for the slow reply, been busy with some other work.
The _safe
approach seems good to me. I'll try to pursue that and update this PR.
@erichiggins what do you think of adding an optional safe
boolean kwarg? That way the environ module namespace won't have a bunch of nearly identical functions.
E.g.
gaek.get_modules()
>>> KeyError
gaek.get_modules(safe=True)
>>> None
Actually, I just went through the module calling all the functions in a remote API context and in a plain ol' python shell context and I don't think that we should stub all the functions-- imo the only two functions we should look at are get_current_version_name
and get_current_module_name
. The reason is that every other function works in a remote API context, it's only these two that raise errors. I think it's reasonable for gaek
to assume that it's either being used in (1) a running GAE app or (2) in a GAE remote API context. In a regular old shell blowing up with API proxy errors seems like the right behavior to me.
Ok. So do you propose just adding an optional safe
parameter to those two functions, or would it be more explicit to make gaek-specific wrappers (e.g. get_current_module_safe()
)? For the reasons I mentioned before, I think I'd prefer the wrapped function, but adding a custom parameter would be fine too. If you prefer the parameter, I think something longer & more specific might be better (offline_safe=True
perhaps).
Either way, can you please take a moment to update the docs to reflect the changes in this PR as well?
Using wrapper functions is fine with me. And yup, I'll update the docs accordingly in my next update here.
@Codonaut Yo, just wanted to check in on this. No rush, but don't want to block you if it's ready to go.
Hey @erichiggins, sorry I didn't see the notification for your last message. Sorry to leave you hanging for a while, I've been getting pulled in a few different directions so it took me a little bit to come back to this.
Anyway, I think this PR is in a pretty good state now. I added a get_current_module_name_safe
and a get_current_version_name_safe
, and then also added _safe
versions of the other functions that consume those two. Let me know what you think!
Ok, I fixed the typo and got myself out of the git hell that suddenly popped up. Thanks for the fast review Eric!
Awesome! Thanks for the PR, @Codonaut !
Right now
get_current_version_name()
will raise aKeyError
if called outside of an appengine app. Here's a portion of a stacktrace showing this:This usually isn't a huge deal because generally
gaek
is used in a running app. This is however a problem when running remote API scripts that interact with application code. In those cases the 'CURRENT_VERSION_ID' environment variable is not populated, and aKeyError
is raised.I think suppressing that error is the natural thing to do here, especially since it's not at all clear that an error would be raised when calling
gaek.environ.is_default_version