-
Notifications
You must be signed in to change notification settings - Fork 595
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
Vision: imageContext isn't documented #2553
Comments
You might want to update these docs also when you're at it -- Thanks for following up jmdobry@ |
Thanks for reporting and sorry for the trouble @arpwal. I believe we have two action items here:
|
Why does 2) have to be a breaking change? var _createSingleFeatureMethod = featureValue => {
return function(image, options) {
return this.annotateImage({
image: image,
features: [{type: featureValue}],
}, options);
};
}; => var _createSingleFeatureMethod = featureValue => {
return function(request, options) {
// Assume that "request" is a full AnnotateImageRequest
const features = [{ type: featureValue }];
if (!request.image) {
// All of users' current code would hit this path
request = {
image: request,
features: features
};
}
if (!request.features) {
request.features = features;
}
return this.annotateImage(request, options);
};
}; |
I'm not too bothered by the breaking change, and I would avoid the duality and just stick with "one way" of using the method. This API was designed by @lukesneeringer / automated, so let's get his take on it. |
Okay. I'm personally okay with a breaking change, and making the shorthand methods take the normal AnnotateImageRequest, instead of taking just |
I will look at it when I am at the office tomorrow, but this looks like a slip up on my part and easily corrected. It might be a breaking change only insofar as we take an extremely rarely used argument and shift it back one slot. |
So, a couple thoughts: In Python, I took arbitrary keyword arguments which I mapped onto the This is a little less good in Node because it essentially means that these methods take three objects, but it still seems like the right thing to do to make the simple case easy and the advanced case possible. |
Oh, wow, I just noticed the repeated instantiations needed in order to get docs working. :-/ I really hope we can make that automatic and use a JSDoc plugin in the future. |
What do you mean?
This concept is going to affect a lot of our methods; short hand arguments vs raw API format vs GAX options. We should figure out the best solution now and start applying it wherever it fits. We've struggled with this in various APIs since our inception, and have ended up with a couple different solutions. Most recently, we had to fit "gaxOptions" to the Logging API:
It's not great using the term "gaxOptions", because this has no meaning to the user. However, they can click from our docs to the gax docs and see all of the knobs without us having to duplicate docs and worry about going stale.
Mixing a method's config/options object with |
I think these shorthand methods currently introduce greater cognitive dissonance than they alleviate. It's tiring deciphering the differences between a Service's REST/GRPC API and the request/response formats of the client library. I think the implementation of var _createSingleFeatureMethod = (featureValue) => {
return function(annotateImageRequest, callOptions) {
if (!annotateImageRequest.features) {
annotateImageRequest.features = [{ type: featureValue }];
}
return this.annotateImage(annotateImageRequest, callOptions);
};
}; |
I previously had a one-shot loop that iterated over an enum and created all the methods. Now the method is declared 8-10 times with the differing values, in order to allow the documentation parser to pick up the documentation comments.
Oh, it is nice to realize that this has some prior art. I did not realize that. (For a bikeshed, I would have preferred |
cc @callmehiphop for the API-wide discussion of a frictionless way to integrate |
Hmm. At the point that we are doing that, I almost wonder if it would make more sense to scrap these entirely and just ask the user to call I could potentially get behind this, and it does have the advantage of solving every other problem. |
Ah, yeah. Where that started: #2298 (comment) I also like the @jmdobry proposal. These are just shortcut methods, that do "one shortcut" (setting the feature option for you). Otherwise, the interface being the same is a good thing. |
One change I would make if we go with @jmdobry's solution is that the caution on updating Therefore, the logic would need to become... var _createSingleFeatureMethod = featureValue => {
return function(annotateImageRequest, callOptions) {
annotateImageRequest.features = annotateImageRequest.features || [];
// Ensure the feature value indicated by the user's method choice exists on the
// features array; if it does not, add it.
var found = false;
for (let feature of annotateImageRequest.features) {
if (feature.type === featureValue) {
found = true;
break;
}
}
if (found === false) {
annotateImageRequest.features.push({type: featureValue});
}
// Call the underlying #annotateImage method.
return this.annotateImage(annotateImageRequest, callOptions);
};
}; |
Yeah, I definitely understand why you did it, but in the medium-term I would like to find a better way. The entire point of creating those methods on a loop is that the underlying enum (defined by autogen) may change. We should punt on that issue until we covert Vision to JSDoc. I bet once we do, I can write a plugin to handle this case. |
I am slowly becoming increasingly convinced that @jmdobry's solution is the best one. |
I think if at all possible, google-cloud-node should rely on (meaning should accept and return) the request/response formats defined in the protos (though fully-handwritten libs might be an exception). In cases where google-cloud-node needs to add stuff, they should be "non-breaking" additions, e.g. proto has field
Couple of benefits:
Obviously we still want the library to be idiomatic, but I think it can be idiomatic and also be well representative of the service's API surface. |
I agree with all of these principles. :-) In fact, these were the reasons for going from the one-off methods in the manual layer to the one we have now. I also agree that the proposed solution follows these principles better than what I did originally. Let's go with that. |
#2555 updated accordingly. |
Fixed in #2555. |
Customer wondered how to pass a crop hint option to
Vision#cropHints()
. Turns out, you can't. The helper methods only accept anImage
and a grpc options object, and do not acceptimageContext
.In order to pass say, the
aspectRatios
option as part of thecropHints
request, you have to use theannotateImage
method directly, like so:I'm not sure how folks are supposed to know this.
imageContext
itself isn't even documented on the annotateImage methodAlso, accessing the enum (e.g.
Vision.types.Feature.Type.CROP_HINTS
) is only documented in the client library's README, and even then, only for FACE_DETECTION.The text was updated successfully, but these errors were encountered: