Source code for google.cloud.vision_helpers.decorators
# Copyright 2017, Google LLC All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
def add_single_feature_methods(cls):
"""Custom decorator intended for :class:`~vision.helpers.VisionHelpers`.
This metaclass adds a `{feature}` method for every feature
defined on the Feature enum.
"""
# Sanity check: This only makes sense if we are building the GAPIC
# subclass and have enums already attached.
if not hasattr(cls, "enums"):
return cls
# Add each single-feature method to the class.
for feature in cls.enums.Feature.Type:
# Sanity check: Do not make a method for the falsy feature.
if feature.name == "TYPE_UNSPECIFIED":
continue
# Assign the appropriate metadata to the function.
detect = _create_single_feature_method(feature)
# Assign a qualified name to the function, and perform module
# replacement on the docstring.
detect.__qualname__ = "{cls}.{name}".format(
cls=cls.__name__, name=detect.__name__
)
detect.__doc__ = detect.__doc__.format(module=cls.__module__)
# Place the function on the class being created.
setattr(cls, detect.__name__, detect)
# Done; return the class.
return cls
def _create_single_feature_method(feature):
"""Return a function that will detect a single feature.
Args:
feature (enum): A specific feature defined as a member of
:class:`~enums.Feature.Type`.
Returns:
function: A helper function to detect just that feature.
"""
# Define the function properties.
fx_name = feature.name.lower()
if "detection" in fx_name:
fx_doc = "Perform {0}.".format(fx_name.replace("_", " "))
else:
fx_doc = "Return {desc} information.".format(desc=fx_name.replace("_", " "))
# Provide a complete docstring with argument and return value
# information.
fx_doc += """
Args:
image (:class:`~.{module}.types.Image`): The image to analyze.
max_results (int):
Number of results to return, does not apply for
TEXT_DETECTION, DOCUMENT_TEXT_DETECTION, or CROP_HINTS.
retry (int): Number of retries to do before giving up.
timeout (int): Number of seconds before timing out.
kwargs (dict): Additional properties to be set on the
:class:`~.{module}.types.AnnotateImageRequest`.
Returns:
:class:`~.{module}.types.AnnotateImageResponse`: The API response.
"""
# Get the actual feature value to send.
feature_value = {"type": feature}
# Define the function to be returned.
def inner(self, image, max_results=None, retry=None, timeout=None, **kwargs):
"""Return a single feature annotation for the given image.
Intended for use with functools.partial, to create the particular
single-feature methods.
"""
copied_features = feature_value.copy()
if max_results is not None:
copied_features["max_results"] = max_results
request = dict(image=image, features=[copied_features], **kwargs)
response = self.annotate_image(request, retry=retry, timeout=timeout)
return response
# Set the appropriate function metadata.
inner.__name__ = fx_name
inner.__doc__ = fx_doc
# Return the final function.
return inner