# coding: utf-8
# Copyright 2018 IBM 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.
"""
The IBM Watson™ Visual Recognition service uses deep learning algorithms to identify
scenes, objects, and faces in images you upload to the service. You can create and train
a custom classifier to identify subjects that suit your needs.
"""
from __future__ import absolute_import
import json
from .watson_service import datetime_to_string, string_to_datetime
from os.path import basename
import re
from .watson_service import WatsonService
##############################################################################
# Service
##############################################################################
[docs]class VisualRecognitionV3(WatsonService):
"""The Visual Recognition V3 service."""
default_url = 'https://gateway.watsonplatform.net/visual-recognition/api'
def __init__(
self,
version,
url=default_url,
iam_apikey=None,
iam_access_token=None,
iam_url=None,
):
"""
Construct a new client for the Visual Recognition service.
:param str version: The API version date to use with the service, in
"YYYY-MM-DD" format. Whenever the API is changed in a backwards
incompatible way, a new minor version of the API is released.
The service uses the API version for the date you specify, or
the most recent version before that date. Note that you should
not programmatically specify the current date at runtime, in
case the API has been updated since your application's release.
Instead, specify a version date that is compatible with your
application, and don't change it until your application is
ready for a later version.
:param str url: The base url to use when contacting the service (e.g.
"https://gateway.watsonplatform.net/visual-recognition/api").
The base url may differ between Bluemix regions.
:param str iam_apikey: An API key that can be used to request IAM tokens. If
this API key is provided, the SDK will manage the token and handle the
refreshing.
:param str iam_access_token: An IAM access token is fully managed by the application.
Responsibility falls on the application to refresh the token, either before
it expires or reactively upon receiving a 401 from the service as any requests
made with an expired token will fail.
:param str iam_url: An optional URL for the IAM service API. Defaults to
'https://iam.bluemix.net/identity/token'.
"""
WatsonService.__init__(
self,
vcap_services_name='watson_vision_combined',
url=url,
iam_apikey=iam_apikey,
iam_access_token=iam_access_token,
iam_url=iam_url,
use_vcap_services=True)
self.version = version
#########################
# General
#########################
[docs] def classify(self,
images_file=None,
accept_language=None,
url=None,
threshold=None,
owners=None,
classifier_ids=None,
images_file_content_type=None,
images_filename=None,
**kwargs):
"""
Classify images.
Classify images with built-in or custom classifiers.
:param file images_file: An image file (.jpg, .png) or .zip file with images.
Maximum image size is 10 MB. Include no more than 20 images and limit the .zip
file to 100 MB. Encode the image and .zip file names in UTF-8 if they contain
non-ASCII characters. The service assumes UTF-8 encoding if it encounters
non-ASCII characters.
You can also include an image with the **url** parameter.
:param str accept_language: The language of the output class names. The full set
of languages is supported for the built-in classifier IDs: `default`, `food`, and
`explicit`. The class names of custom classifiers are not translated.
The response might not be in the specified language when the requested language is
not supported or when there is no translation for the class name.
:param str url: The URL of an image to analyze. Must be in .jpg, or .png format.
The minimum recommended pixel density is 32X32 pixels per inch, and the maximum
image size is 10 MB.
You can also include images with the **images_file** parameter.
:param float threshold: The minimum score a class must have to be displayed in the
response. Set the threshold to `0.0` to ignore the classification score and return
all values.
:param list[str] owners: The categories of classifiers to apply. Use `IBM` to
classify against the `default` general classifier, and use `me` to classify
against your custom classifiers. To analyze the image against both classifier
categories, set the value to both `IBM` and `me`.
The built-in `default` classifier is used if both **classifier_ids** and
**owners** parameters are empty.
The **classifier_ids** parameter overrides **owners**, so make sure that
**classifier_ids** is empty.
:param list[str] classifier_ids: Which classifiers to apply. Overrides the
**owners** parameter. You can specify both custom and built-in classifier IDs. The
built-in `default` classifier is used if both **classifier_ids** and **owners**
parameters are empty.
The following built-in classifier IDs require no training:
- `default`: Returns classes from thousands of general tags.
- `food`: Enhances specificity and accuracy for images of food items.
- `explicit`: Evaluates whether the image might be pornographic.
:param str images_file_content_type: The content type of images_file.
:param str images_filename: The filename for images_file.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
headers = {'Accept-Language': accept_language}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
form_data = {}
if images_file:
if not images_filename and hasattr(images_file, 'name'):
images_filename = basename(images_file.name)
form_data['images_file'] = (images_filename, images_file,
images_file_content_type or
'application/octet-stream')
if url:
form_data['url'] = (None, url, 'text/plain')
if threshold:
form_data['threshold'] = (None, threshold, 'application/json')
if owners:
owners = self._convert_list(owners)
form_data['owners'] = (None, owners, 'application/json')
if classifier_ids:
classifier_ids = self._convert_list(classifier_ids)
form_data['classifier_ids'] = (None, classifier_ids,
'application/json')
url = '/v3/classify'
response = self.request(
method='POST',
url=url,
headers=headers,
params=params,
files=form_data,
accept_json=True)
return response
#########################
# Face
#########################
[docs] def detect_faces(self,
images_file=None,
url=None,
images_file_content_type=None,
images_filename=None,
**kwargs):
"""
Detect faces in images.
**Important:** On April 2, 2018, the identity information in the response to calls
to the Face model was removed. The identity information refers to the `name` of
the person, `score`, and `type_hierarchy` knowledge graph. For details about the
enhanced Face model, see the [Release
notes](https://console.bluemix.net/docs/services/visual-recognition/release-notes.html#2april2018).
Analyze and get data about faces in images. Responses can include estimated age
and gender. This feature uses a built-in model, so no training is necessary. The
Detect faces method does not support general biometric facial recognition.
Supported image formats include .gif, .jpg, .png, and .tif. The maximum image size
is 10 MB. The minimum recommended pixel density is 32X32 pixels per inch.
:param file images_file: An image file (gif, .jpg, .png, .tif.) or .zip file with
images. Limit the .zip file to 100 MB. You can include a maximum of 15 images in a
request.
Encode the image and .zip file names in UTF-8 if they contain non-ASCII
characters. The service assumes UTF-8 encoding if it encounters non-ASCII
characters.
You can also include an image with the **url** parameter.
:param str url: The URL of an image to analyze. Must be in .gif, .jpg, .png, or
.tif format. The minimum recommended pixel density is 32X32 pixels per inch, and
the maximum image size is 10 MB. Redirects are followed, so you can use a
shortened URL.
You can also include images with the **images_file** parameter.
:param str images_file_content_type: The content type of images_file.
:param str images_filename: The filename for images_file.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
form_data = {}
if images_file:
if not images_filename and hasattr(images_file, 'name'):
images_filename = basename(images_file.name)
form_data['images_file'] = (images_filename, images_file,
images_file_content_type or
'application/octet-stream')
if url:
form_data['url'] = (None, url)
url = '/v3/detect_faces'
response = self.request(
method='POST',
url=url,
headers=headers,
params=params,
files=form_data,
accept_json=True)
return response
#########################
# Custom
#########################
[docs] def create_classifier(self,
name,
negative_examples=None,
negative_examples_filename=None,
**kwargs):
"""
Create a classifier.
Train a new multi-faceted classifier on the uploaded image data. Create your
custom classifier with positive or negative examples. Include at least two sets of
examples, either two positive example files or one positive and one negative file.
You can upload a maximum of 256 MB per call.
Encode all names in UTF-8 if they contain non-ASCII characters (.zip and image
file names, and classifier and class names). The service assumes UTF-8 encoding if
it encounters non-ASCII characters.
:param str name: The name of the new classifier. Encode special characters in
UTF-8.
:param file negative_examples: A .zip file of images that do not depict the visual
subject of any of the classes of the new classifier. Must contain a minimum of 10
images.
Encode special characters in the file name in UTF-8.
:param str negative_examples_filename: The filename for negative_examples.
:param file positive_examples: A .zip file of images that depict the visual
subject of a class in the new classifier. You can include more than one positive
example file in a call.
Specify the parameter name by appending `_positive_examples` to the class name.
For example, `goldenretriever_positive_examples` creates the class
**goldenretriever**.
Include at least 10 images in .jpg or .png format. The minimum recommended image
resolution is 32X32 pixels. The maximum number of images is 10,000 images or 100
MB per .zip file.
Encode special characters in the file name in UTF-8.
:param str positive_examples_filename: The filename for positive_examples.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if name is None:
raise ValueError('name must be provided')
positive_examples_keys = [
key for key in kwargs if re.match('^.+_positive_examples$', key)
]
if not positive_examples_keys:
raise ValueError(
'At least one <classname>_positive_examples parameter must be provided'
)
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
form_data = {}
form_data['name'] = (None, name, 'text/plain')
if negative_examples:
if not negative_examples_filename and hasattr(
negative_examples, 'name'):
negative_examples_filename = basename(negative_examples.name)
if not negative_examples_filename:
raise ValueError('negative_examples_filename must be provided')
form_data['negative_examples'] = (negative_examples_filename,
negative_examples,
'application/octet-stream')
for key in positive_examples_keys:
value = kwargs[key]
filename = kwargs.get(key + '_filename')
if not filename and hasattr(value, 'name'):
filename = basename(value.name)
form_data[key] = (filename, value, 'application/octet-stream')
url = '/v3/classifiers'
response = self.request(
method='POST',
url=url,
headers=headers,
params=params,
files=form_data,
accept_json=True)
return response
[docs] def delete_classifier(self, classifier_id, **kwargs):
"""
Delete a classifier.
:param str classifier_id: The ID of the classifier.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if classifier_id is None:
raise ValueError('classifier_id must be provided')
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
url = '/v3/classifiers/{0}'.format(
*self._encode_path_vars(classifier_id))
response = self.request(
method='DELETE',
url=url,
headers=headers,
params=params,
accept_json=True)
return response
[docs] def get_classifier(self, classifier_id, **kwargs):
"""
Retrieve classifier details.
Retrieve information about a custom classifier.
:param str classifier_id: The ID of the classifier.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if classifier_id is None:
raise ValueError('classifier_id must be provided')
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
url = '/v3/classifiers/{0}'.format(
*self._encode_path_vars(classifier_id))
response = self.request(
method='GET',
url=url,
headers=headers,
params=params,
accept_json=True)
return response
[docs] def list_classifiers(self, verbose=None, **kwargs):
"""
Retrieve a list of classifiers.
:param bool verbose: Specify `true` to return details about the classifiers. Omit
this parameter to return a brief list of classifiers.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version, 'verbose': verbose}
url = '/v3/classifiers'
response = self.request(
method='GET',
url=url,
headers=headers,
params=params,
accept_json=True)
return response
[docs] def update_classifier(self,
classifier_id,
negative_examples=None,
negative_examples_filename=None,
**kwargs):
"""
Update a classifier.
Update a custom classifier by adding new positive or negative classes (examples)
or by adding new images to existing classes. You must supply at least one set of
positive or negative examples. For details, see [Updating custom
classifiers](https://console.bluemix.net/docs/services/visual-recognition/customizing.html#updating-custom-classifiers).
Encode all names in UTF-8 if they contain non-ASCII characters (.zip and image
file names, and classifier and class names). The service assumes UTF-8 encoding if
it encounters non-ASCII characters.
**Tip:** Don't make retraining calls on a classifier until the status is ready.
When you submit retraining requests in parallel, the last request overwrites the
previous requests. The retrained property shows the last time the classifier
retraining finished.
:param str classifier_id: The ID of the classifier.
:param file negative_examples: A .zip file of images that do not depict the visual
subject of any of the classes of the new classifier. Must contain a minimum of 10
images.
Encode special characters in the file name in UTF-8.
:param str negative_examples_filename: The filename for negative_examples.
:param file positive_examples: A .zip file of images that depict the visual
subject of a class in the classifier. The positive examples create or update
classes in the classifier. You can include more than one positive example file in
a call.
Specify the parameter name by appending `_positive_examples` to the class name.
For example, `goldenretriever_positive_examples` creates the class
`goldenretriever`.
Include at least 10 images in .jpg or .png format. The minimum recommended image
resolution is 32X32 pixels. The maximum number of images is 10,000 images or 100
MB per .zip file.
Encode special characters in the file name in UTF-8.
:param str positive_examples_filename: The filename for positive_examples.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if classifier_id is None:
raise ValueError('classifier_id must be provided')
positive_examples_keys = [
key for key in kwargs if re.match('^.+_positive_examples$', key)
]
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
form_data = {}
if negative_examples:
if not negative_examples_filename and hasattr(
negative_examples, 'name'):
negative_examples_filename = basename(negative_examples.name)
if not negative_examples_filename:
raise ValueError('negative_examples_filename must be provided')
form_data['negative_examples'] = (negative_examples_filename,
negative_examples,
'application/octet-stream')
for key in positive_examples_keys:
value = kwargs[key]
filename = kwargs.get(key + '_filename')
if not filename and hasattr(value, 'name'):
filename = basename(value.name)
form_data[key] = (filename, value, 'application/octet-stream')
url = '/v3/classifiers/{0}'.format(
*self._encode_path_vars(classifier_id))
response = self.request(
method='POST',
url=url,
headers=headers,
params=params,
files=form_data,
accept_json=True)
return response
#########################
# Core ML
#########################
[docs] def get_core_ml_model(self, classifier_id, **kwargs):
"""
Retrieve a Core ML model of a classifier.
Download a Core ML model file (.mlmodel) of a custom classifier that returns
<tt>\"core_ml_enabled\": true</tt> in the classifier details.
:param str classifier_id: The ID of the classifier.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if classifier_id is None:
raise ValueError('classifier_id must be provided')
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version}
url = '/v3/classifiers/{0}/core_ml_model'.format(
*self._encode_path_vars(classifier_id))
response = self.request(
method='GET',
url=url,
headers=headers,
params=params,
accept_json=False)
return response
#########################
# User data
#########################
[docs] def delete_user_data(self, customer_id, **kwargs):
"""
Delete labeled data.
Deletes all data associated with a specified customer ID. The method has no effect
if no data is associated with the customer ID.
You associate a customer ID with data by passing the `X-Watson-Metadata` header
with a request that passes data. For more information about personal data and
customer IDs, see [Information
security](https://console.bluemix.net/docs/services/visual-recognition/information-security.html).
:param str customer_id: The customer ID for which all data is to be deleted.
:param dict headers: A `dict` containing the request headers
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
:rtype: DetailedResponse
"""
if customer_id is None:
raise ValueError('customer_id must be provided')
headers = {}
if 'headers' in kwargs:
headers.update(kwargs.get('headers'))
params = {'version': self.version, 'customer_id': customer_id}
url = '/v3/user_data'
response = self.request(
method='DELETE',
url=url,
headers=headers,
params=params,
accept_json=True)
return response
##############################################################################
# Models
##############################################################################
[docs]class Class(object):
"""
A category within a classifier.
:attr str class_name: The name of the class.
"""
def __init__(self, class_name):
"""
Initialize a Class object.
:param str class_name: The name of the class.
"""
self.class_name = class_name
@classmethod
def _from_dict(cls, _dict):
"""Initialize a Class object from a json dictionary."""
args = {}
if 'class' in _dict or 'class_name' in _dict:
args['class_name'] = _dict.get('class') or _dict.get('class_name')
else:
raise ValueError(
'Required property \'class\' not present in Class JSON')
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'class_name') and self.class_name is not None:
_dict['class'] = self.class_name
return _dict
def __str__(self):
"""Return a `str` version of this Class object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ClassResult(object):
"""
Result of a class within a classifier.
:attr str class_name: Name of the class.
:attr float score: Confidence score for the property in the range of 0 to 1. A higher
score indicates greater likelihood that the class is depicted in the image. The
default threshold for returning scores from a classifier is 0.5.
:attr str type_hierarchy: Knowledge graph of the property. For example,
`/fruit/pome/apple/eating apple/Granny Smith`. Included only if identified.
"""
def __init__(self, class_name, score, type_hierarchy):
"""
Initialize a ClassResult object.
:param str class_name: Name of the class.
:param float score: Confidence score for the property in the range of 0 to 1. A
higher score indicates greater likelihood that the class is depicted in the image.
The default threshold for returning scores from a classifier is 0.5.
:param str type_hierarchy: Knowledge graph of the property. For example,
`/fruit/pome/apple/eating apple/Granny Smith`. Included only if identified.
"""
self.class_name = class_name
self.score = score
self.type_hierarchy = type_hierarchy
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ClassResult object from a json dictionary."""
args = {}
if 'class' in _dict or 'class_name' in _dict:
args['class_name'] = _dict.get('class') or _dict.get('class_name')
else:
raise ValueError(
'Required property \'class\' not present in ClassResult JSON')
if 'score' in _dict:
args['score'] = _dict.get('score')
else:
raise ValueError(
'Required property \'score\' not present in ClassResult JSON')
if 'type_hierarchy' in _dict:
args['type_hierarchy'] = _dict.get('type_hierarchy')
else:
raise ValueError(
'Required property \'type_hierarchy\' not present in ClassResult JSON'
)
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'class_name') and self.class_name is not None:
_dict['class'] = self.class_name
if hasattr(self, 'score') and self.score is not None:
_dict['score'] = self.score
if hasattr(self, 'type_hierarchy') and self.type_hierarchy is not None:
_dict['type_hierarchy'] = self.type_hierarchy
return _dict
def __str__(self):
"""Return a `str` version of this ClassResult object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ClassifiedImage(object):
"""
Results for one image.
:attr str source_url: (optional) Source of the image before any redirects. Not
returned when the image is uploaded.
:attr str resolved_url: (optional) Fully resolved URL of the image after redirects are
followed. Not returned when the image is uploaded.
:attr str image: (optional) Relative path of the image file if uploaded directly. Not
returned when the image is passed by URL.
:attr ErrorInfo error: (optional) Information about what might have caused a failure,
such as an image that is too large. Not returned when there is no error.
:attr list[ClassifierResult] classifiers: The classifiers.
"""
def __init__(self,
classifiers,
source_url=None,
resolved_url=None,
image=None,
error=None):
"""
Initialize a ClassifiedImage object.
:param list[ClassifierResult] classifiers: The classifiers.
:param str source_url: (optional) Source of the image before any redirects. Not
returned when the image is uploaded.
:param str resolved_url: (optional) Fully resolved URL of the image after
redirects are followed. Not returned when the image is uploaded.
:param str image: (optional) Relative path of the image file if uploaded directly.
Not returned when the image is passed by URL.
:param ErrorInfo error: (optional) Information about what might have caused a
failure, such as an image that is too large. Not returned when there is no error.
"""
self.source_url = source_url
self.resolved_url = resolved_url
self.image = image
self.error = error
self.classifiers = classifiers
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ClassifiedImage object from a json dictionary."""
args = {}
if 'source_url' in _dict:
args['source_url'] = _dict.get('source_url')
if 'resolved_url' in _dict:
args['resolved_url'] = _dict.get('resolved_url')
if 'image' in _dict:
args['image'] = _dict.get('image')
if 'error' in _dict:
args['error'] = ErrorInfo._from_dict(_dict.get('error'))
if 'classifiers' in _dict:
args['classifiers'] = [
ClassifierResult._from_dict(x)
for x in (_dict.get('classifiers'))
]
else:
raise ValueError(
'Required property \'classifiers\' not present in ClassifiedImage JSON'
)
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'source_url') and self.source_url is not None:
_dict['source_url'] = self.source_url
if hasattr(self, 'resolved_url') and self.resolved_url is not None:
_dict['resolved_url'] = self.resolved_url
if hasattr(self, 'image') and self.image is not None:
_dict['image'] = self.image
if hasattr(self, 'error') and self.error is not None:
_dict['error'] = self.error._to_dict()
if hasattr(self, 'classifiers') and self.classifiers is not None:
_dict['classifiers'] = [x._to_dict() for x in self.classifiers]
return _dict
def __str__(self):
"""Return a `str` version of this ClassifiedImage object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ClassifiedImages(object):
"""
Results for all images.
:attr int custom_classes: Number of custom classes identified in the images.
:attr int images_processed: Number of images processed for the API call.
:attr list[ClassifiedImage] images: Classified images.
:attr list[WarningInfo] warnings: (optional) Information about what might cause less
than optimal output. For example, a request sent with a corrupt .zip file and a list
of image URLs will still complete, but does not return the expected output. Not
returned when there is no warning.
"""
def __init__(self, custom_classes, images_processed, images, warnings=None):
"""
Initialize a ClassifiedImages object.
:param int custom_classes: Number of custom classes identified in the images.
:param int images_processed: Number of images processed for the API call.
:param list[ClassifiedImage] images: Classified images.
:param list[WarningInfo] warnings: (optional) Information about what might cause
less than optimal output. For example, a request sent with a corrupt .zip file and
a list of image URLs will still complete, but does not return the expected output.
Not returned when there is no warning.
"""
self.custom_classes = custom_classes
self.images_processed = images_processed
self.images = images
self.warnings = warnings
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ClassifiedImages object from a json dictionary."""
args = {}
if 'custom_classes' in _dict:
args['custom_classes'] = _dict.get('custom_classes')
else:
raise ValueError(
'Required property \'custom_classes\' not present in ClassifiedImages JSON'
)
if 'images_processed' in _dict:
args['images_processed'] = _dict.get('images_processed')
else:
raise ValueError(
'Required property \'images_processed\' not present in ClassifiedImages JSON'
)
if 'images' in _dict:
args['images'] = [
ClassifiedImage._from_dict(x) for x in (_dict.get('images'))
]
else:
raise ValueError(
'Required property \'images\' not present in ClassifiedImages JSON'
)
if 'warnings' in _dict:
args['warnings'] = [
WarningInfo._from_dict(x) for x in (_dict.get('warnings'))
]
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'custom_classes') and self.custom_classes is not None:
_dict['custom_classes'] = self.custom_classes
if hasattr(self,
'images_processed') and self.images_processed is not None:
_dict['images_processed'] = self.images_processed
if hasattr(self, 'images') and self.images is not None:
_dict['images'] = [x._to_dict() for x in self.images]
if hasattr(self, 'warnings') and self.warnings is not None:
_dict['warnings'] = [x._to_dict() for x in self.warnings]
return _dict
def __str__(self):
"""Return a `str` version of this ClassifiedImages object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class Classifier(object):
"""
Information about a classifier.
:attr str classifier_id: ID of a classifier identified in the image.
:attr str name: Name of the classifier.
:attr str owner: (optional) Unique ID of the account who owns the classifier. Returned
when verbose=`true`. Might not be returned by some requests.
:attr str status: (optional) Training status of classifier.
:attr bool core_ml_enabled: (optional) Whether the classifier can be downloaded as a
Core ML model after the training status is `ready`.
:attr str explanation: (optional) If classifier training has failed, this field might
explain why.
:attr datetime created: (optional) Date and time in Coordinated Universal Time (UTC)
that the classifier was created.
:attr list[Class] classes: (optional) Classes that define a classifier.
:attr datetime retrained: (optional) Date and time in Coordinated Universal Time (UTC)
that the classifier was updated. Returned when verbose=`true`. Might not be returned
by some requests. Identical to `updated` and retained for backward compatibility.
:attr datetime updated: (optional) Date and time in Coordinated Universal Time (UTC)
that the classifier was most recently updated. The field matches either `retrained` or
`created`. Returned when verbose=`true`. Might not be returned by some requests.
"""
def __init__(self,
classifier_id,
name,
owner=None,
status=None,
core_ml_enabled=None,
explanation=None,
created=None,
classes=None,
retrained=None,
updated=None):
"""
Initialize a Classifier object.
:param str classifier_id: ID of a classifier identified in the image.
:param str name: Name of the classifier.
:param str owner: (optional) Unique ID of the account who owns the classifier.
Returned when verbose=`true`. Might not be returned by some requests.
:param str status: (optional) Training status of classifier.
:param bool core_ml_enabled: (optional) Whether the classifier can be downloaded
as a Core ML model after the training status is `ready`.
:param str explanation: (optional) If classifier training has failed, this field
might explain why.
:param datetime created: (optional) Date and time in Coordinated Universal Time
(UTC) that the classifier was created.
:param list[Class] classes: (optional) Classes that define a classifier.
:param datetime retrained: (optional) Date and time in Coordinated Universal Time
(UTC) that the classifier was updated. Returned when verbose=`true`. Might not be
returned by some requests. Identical to `updated` and retained for backward
compatibility.
:param datetime updated: (optional) Date and time in Coordinated Universal Time
(UTC) that the classifier was most recently updated. The field matches either
`retrained` or `created`. Returned when verbose=`true`. Might not be returned by
some requests.
"""
self.classifier_id = classifier_id
self.name = name
self.owner = owner
self.status = status
self.core_ml_enabled = core_ml_enabled
self.explanation = explanation
self.created = created
self.classes = classes
self.retrained = retrained
self.updated = updated
@classmethod
def _from_dict(cls, _dict):
"""Initialize a Classifier object from a json dictionary."""
args = {}
if 'classifier_id' in _dict:
args['classifier_id'] = _dict.get('classifier_id')
else:
raise ValueError(
'Required property \'classifier_id\' not present in Classifier JSON'
)
if 'name' in _dict:
args['name'] = _dict.get('name')
else:
raise ValueError(
'Required property \'name\' not present in Classifier JSON')
if 'owner' in _dict:
args['owner'] = _dict.get('owner')
if 'status' in _dict:
args['status'] = _dict.get('status')
if 'core_ml_enabled' in _dict:
args['core_ml_enabled'] = _dict.get('core_ml_enabled')
if 'explanation' in _dict:
args['explanation'] = _dict.get('explanation')
if 'created' in _dict:
args['created'] = string_to_datetime(_dict.get('created'))
if 'classes' in _dict:
args['classes'] = [
Class._from_dict(x) for x in (_dict.get('classes'))
]
if 'retrained' in _dict:
args['retrained'] = string_to_datetime(_dict.get('retrained'))
if 'updated' in _dict:
args['updated'] = string_to_datetime(_dict.get('updated'))
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'classifier_id') and self.classifier_id is not None:
_dict['classifier_id'] = self.classifier_id
if hasattr(self, 'name') and self.name is not None:
_dict['name'] = self.name
if hasattr(self, 'owner') and self.owner is not None:
_dict['owner'] = self.owner
if hasattr(self, 'status') and self.status is not None:
_dict['status'] = self.status
if hasattr(self,
'core_ml_enabled') and self.core_ml_enabled is not None:
_dict['core_ml_enabled'] = self.core_ml_enabled
if hasattr(self, 'explanation') and self.explanation is not None:
_dict['explanation'] = self.explanation
if hasattr(self, 'created') and self.created is not None:
_dict['created'] = datetime_to_string(self.created)
if hasattr(self, 'classes') and self.classes is not None:
_dict['classes'] = [x._to_dict() for x in self.classes]
if hasattr(self, 'retrained') and self.retrained is not None:
_dict['retrained'] = datetime_to_string(self.retrained)
if hasattr(self, 'updated') and self.updated is not None:
_dict['updated'] = datetime_to_string(self.updated)
return _dict
def __str__(self):
"""Return a `str` version of this Classifier object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ClassifierResult(object):
"""
Classifier and score combination.
:attr str name: Name of the classifier.
:attr str classifier_id: ID of a classifier identified in the image.
:attr list[ClassResult] classes: Classes within the classifier.
"""
def __init__(self, name, classifier_id, classes):
"""
Initialize a ClassifierResult object.
:param str name: Name of the classifier.
:param str classifier_id: ID of a classifier identified in the image.
:param list[ClassResult] classes: Classes within the classifier.
"""
self.name = name
self.classifier_id = classifier_id
self.classes = classes
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ClassifierResult object from a json dictionary."""
args = {}
if 'name' in _dict:
args['name'] = _dict.get('name')
else:
raise ValueError(
'Required property \'name\' not present in ClassifierResult JSON'
)
if 'classifier_id' in _dict:
args['classifier_id'] = _dict.get('classifier_id')
else:
raise ValueError(
'Required property \'classifier_id\' not present in ClassifierResult JSON'
)
if 'classes' in _dict:
args['classes'] = [
ClassResult._from_dict(x) for x in (_dict.get('classes'))
]
else:
raise ValueError(
'Required property \'classes\' not present in ClassifierResult JSON'
)
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'name') and self.name is not None:
_dict['name'] = self.name
if hasattr(self, 'classifier_id') and self.classifier_id is not None:
_dict['classifier_id'] = self.classifier_id
if hasattr(self, 'classes') and self.classes is not None:
_dict['classes'] = [x._to_dict() for x in self.classes]
return _dict
def __str__(self):
"""Return a `str` version of this ClassifierResult object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class Classifiers(object):
"""
A container for the list of classifiers.
:attr list[Classifier] classifiers: List of classifiers.
"""
def __init__(self, classifiers):
"""
Initialize a Classifiers object.
:param list[Classifier] classifiers: List of classifiers.
"""
self.classifiers = classifiers
@classmethod
def _from_dict(cls, _dict):
"""Initialize a Classifiers object from a json dictionary."""
args = {}
if 'classifiers' in _dict:
args['classifiers'] = [
Classifier._from_dict(x) for x in (_dict.get('classifiers'))
]
else:
raise ValueError(
'Required property \'classifiers\' not present in Classifiers JSON'
)
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'classifiers') and self.classifiers is not None:
_dict['classifiers'] = [x._to_dict() for x in self.classifiers]
return _dict
def __str__(self):
"""Return a `str` version of this Classifiers object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class DetectedFaces(object):
"""
Results for all faces.
:attr int images_processed: Number of images processed for the API call.
:attr list[ImageWithFaces] images: The images.
:attr list[WarningInfo] warnings: (optional) Information about what might cause less
than optimal output. For example, a request sent with a corrupt .zip file and a list
of image URLs will still complete, but does not return the expected output. Not
returned when there is no warning.
"""
def __init__(self, images_processed, images, warnings=None):
"""
Initialize a DetectedFaces object.
:param int images_processed: Number of images processed for the API call.
:param list[ImageWithFaces] images: The images.
:param list[WarningInfo] warnings: (optional) Information about what might cause
less than optimal output. For example, a request sent with a corrupt .zip file and
a list of image URLs will still complete, but does not return the expected output.
Not returned when there is no warning.
"""
self.images_processed = images_processed
self.images = images
self.warnings = warnings
@classmethod
def _from_dict(cls, _dict):
"""Initialize a DetectedFaces object from a json dictionary."""
args = {}
if 'images_processed' in _dict:
args['images_processed'] = _dict.get('images_processed')
else:
raise ValueError(
'Required property \'images_processed\' not present in DetectedFaces JSON'
)
if 'images' in _dict:
args['images'] = [
ImageWithFaces._from_dict(x) for x in (_dict.get('images'))
]
else:
raise ValueError(
'Required property \'images\' not present in DetectedFaces JSON'
)
if 'warnings' in _dict:
args['warnings'] = [
WarningInfo._from_dict(x) for x in (_dict.get('warnings'))
]
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self,
'images_processed') and self.images_processed is not None:
_dict['images_processed'] = self.images_processed
if hasattr(self, 'images') and self.images is not None:
_dict['images'] = [x._to_dict() for x in self.images]
if hasattr(self, 'warnings') and self.warnings is not None:
_dict['warnings'] = [x._to_dict() for x in self.warnings]
return _dict
def __str__(self):
"""Return a `str` version of this DetectedFaces object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ErrorInfo(object):
"""
Information about what might have caused a failure, such as an image that is too
large. Not returned when there is no error.
:attr int code: HTTP status code.
:attr str description: Human-readable error description. For example, `File size limit
exceeded`.
:attr str error_id: Codified error string. For example, `limit_exceeded`.
"""
def __init__(self, code, description, error_id):
"""
Initialize a ErrorInfo object.
:param int code: HTTP status code.
:param str description: Human-readable error description. For example, `File size
limit exceeded`.
:param str error_id: Codified error string. For example, `limit_exceeded`.
"""
self.code = code
self.description = description
self.error_id = error_id
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ErrorInfo object from a json dictionary."""
args = {}
if 'code' in _dict:
args['code'] = _dict.get('code')
else:
raise ValueError(
'Required property \'code\' not present in ErrorInfo JSON')
if 'description' in _dict:
args['description'] = _dict.get('description')
else:
raise ValueError(
'Required property \'description\' not present in ErrorInfo JSON'
)
if 'error_id' in _dict:
args['error_id'] = _dict.get('error_id')
else:
raise ValueError(
'Required property \'error_id\' not present in ErrorInfo JSON')
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'code') and self.code is not None:
_dict['code'] = self.code
if hasattr(self, 'description') and self.description is not None:
_dict['description'] = self.description
if hasattr(self, 'error_id') and self.error_id is not None:
_dict['error_id'] = self.error_id
return _dict
def __str__(self):
"""Return a `str` version of this ErrorInfo object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class Face(object):
"""
Information about the face.
:attr FaceAge age: (optional) Age information about a face.
:attr FaceGender gender: (optional) Information about the gender of the face.
:attr FaceLocation face_location: (optional) The location of the bounding box around
the face.
"""
def __init__(self, age=None, gender=None, face_location=None):
"""
Initialize a Face object.
:param FaceAge age: (optional) Age information about a face.
:param FaceGender gender: (optional) Information about the gender of the face.
:param FaceLocation face_location: (optional) The location of the bounding box
around the face.
"""
self.age = age
self.gender = gender
self.face_location = face_location
@classmethod
def _from_dict(cls, _dict):
"""Initialize a Face object from a json dictionary."""
args = {}
if 'age' in _dict:
args['age'] = FaceAge._from_dict(_dict.get('age'))
if 'gender' in _dict:
args['gender'] = FaceGender._from_dict(_dict.get('gender'))
if 'face_location' in _dict:
args['face_location'] = FaceLocation._from_dict(
_dict.get('face_location'))
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'age') and self.age is not None:
_dict['age'] = self.age._to_dict()
if hasattr(self, 'gender') and self.gender is not None:
_dict['gender'] = self.gender._to_dict()
if hasattr(self, 'face_location') and self.face_location is not None:
_dict['face_location'] = self.face_location._to_dict()
return _dict
def __str__(self):
"""Return a `str` version of this Face object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class FaceAge(object):
"""
Age information about a face.
:attr int min: (optional) Estimated minimum age.
:attr int max: (optional) Estimated maximum age.
:attr float score: Confidence score in the range of 0 to 1. A higher score indicates
greater confidence in the estimated value for the property.
"""
def __init__(self, score, min=None, max=None):
"""
Initialize a FaceAge object.
:param float score: Confidence score in the range of 0 to 1. A higher score
indicates greater confidence in the estimated value for the property.
:param int min: (optional) Estimated minimum age.
:param int max: (optional) Estimated maximum age.
"""
self.min = min
self.max = max
self.score = score
@classmethod
def _from_dict(cls, _dict):
"""Initialize a FaceAge object from a json dictionary."""
args = {}
if 'min' in _dict:
args['min'] = _dict.get('min')
if 'max' in _dict:
args['max'] = _dict.get('max')
if 'score' in _dict:
args['score'] = _dict.get('score')
else:
raise ValueError(
'Required property \'score\' not present in FaceAge JSON')
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'min') and self.min is not None:
_dict['min'] = self.min
if hasattr(self, 'max') and self.max is not None:
_dict['max'] = self.max
if hasattr(self, 'score') and self.score is not None:
_dict['score'] = self.score
return _dict
def __str__(self):
"""Return a `str` version of this FaceAge object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class FaceGender(object):
"""
Information about the gender of the face.
:attr str gender: Gender identified by the face. For example, `MALE` or `FEMALE`.
:attr float score: Confidence score in the range of 0 to 1. A higher score indicates
greater confidence in the estimated value for the property.
"""
def __init__(self, gender, score):
"""
Initialize a FaceGender object.
:param str gender: Gender identified by the face. For example, `MALE` or `FEMALE`.
:param float score: Confidence score in the range of 0 to 1. A higher score
indicates greater confidence in the estimated value for the property.
"""
self.gender = gender
self.score = score
@classmethod
def _from_dict(cls, _dict):
"""Initialize a FaceGender object from a json dictionary."""
args = {}
if 'gender' in _dict:
args['gender'] = _dict.get('gender')
else:
raise ValueError(
'Required property \'gender\' not present in FaceGender JSON')
if 'score' in _dict:
args['score'] = _dict.get('score')
else:
raise ValueError(
'Required property \'score\' not present in FaceGender JSON')
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'gender') and self.gender is not None:
_dict['gender'] = self.gender
if hasattr(self, 'score') and self.score is not None:
_dict['score'] = self.score
return _dict
def __str__(self):
"""Return a `str` version of this FaceGender object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class FaceLocation(object):
"""
The location of the bounding box around the face.
:attr float width: Width in pixels of face region.
:attr float height: Height in pixels of face region.
:attr float left: X-position of top-left pixel of face region.
:attr float top: Y-position of top-left pixel of face region.
"""
def __init__(self, width, height, left, top):
"""
Initialize a FaceLocation object.
:param float width: Width in pixels of face region.
:param float height: Height in pixels of face region.
:param float left: X-position of top-left pixel of face region.
:param float top: Y-position of top-left pixel of face region.
"""
self.width = width
self.height = height
self.left = left
self.top = top
@classmethod
def _from_dict(cls, _dict):
"""Initialize a FaceLocation object from a json dictionary."""
args = {}
if 'width' in _dict:
args['width'] = _dict.get('width')
else:
raise ValueError(
'Required property \'width\' not present in FaceLocation JSON')
if 'height' in _dict:
args['height'] = _dict.get('height')
else:
raise ValueError(
'Required property \'height\' not present in FaceLocation JSON')
if 'left' in _dict:
args['left'] = _dict.get('left')
else:
raise ValueError(
'Required property \'left\' not present in FaceLocation JSON')
if 'top' in _dict:
args['top'] = _dict.get('top')
else:
raise ValueError(
'Required property \'top\' not present in FaceLocation JSON')
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'width') and self.width is not None:
_dict['width'] = self.width
if hasattr(self, 'height') and self.height is not None:
_dict['height'] = self.height
if hasattr(self, 'left') and self.left is not None:
_dict['left'] = self.left
if hasattr(self, 'top') and self.top is not None:
_dict['top'] = self.top
return _dict
def __str__(self):
"""Return a `str` version of this FaceLocation object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class ImageWithFaces(object):
"""
Information about faces in the image.
:attr list[Face] faces: Faces detected in the images.
:attr str image: (optional) Relative path of the image file if uploaded directly. Not
returned when the image is passed by URL.
:attr str source_url: (optional) Source of the image before any redirects. Not
returned when the image is uploaded.
:attr str resolved_url: (optional) Fully resolved URL of the image after redirects are
followed. Not returned when the image is uploaded.
:attr ErrorInfo error: (optional) Information about what might have caused a failure,
such as an image that is too large. Not returned when there is no error.
"""
def __init__(self,
faces,
image=None,
source_url=None,
resolved_url=None,
error=None):
"""
Initialize a ImageWithFaces object.
:param list[Face] faces: Faces detected in the images.
:param str image: (optional) Relative path of the image file if uploaded directly.
Not returned when the image is passed by URL.
:param str source_url: (optional) Source of the image before any redirects. Not
returned when the image is uploaded.
:param str resolved_url: (optional) Fully resolved URL of the image after
redirects are followed. Not returned when the image is uploaded.
:param ErrorInfo error: (optional) Information about what might have caused a
failure, such as an image that is too large. Not returned when there is no error.
"""
self.faces = faces
self.image = image
self.source_url = source_url
self.resolved_url = resolved_url
self.error = error
@classmethod
def _from_dict(cls, _dict):
"""Initialize a ImageWithFaces object from a json dictionary."""
args = {}
if 'faces' in _dict:
args['faces'] = [Face._from_dict(x) for x in (_dict.get('faces'))]
else:
raise ValueError(
'Required property \'faces\' not present in ImageWithFaces JSON'
)
if 'image' in _dict:
args['image'] = _dict.get('image')
if 'source_url' in _dict:
args['source_url'] = _dict.get('source_url')
if 'resolved_url' in _dict:
args['resolved_url'] = _dict.get('resolved_url')
if 'error' in _dict:
args['error'] = ErrorInfo._from_dict(_dict.get('error'))
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'faces') and self.faces is not None:
_dict['faces'] = [x._to_dict() for x in self.faces]
if hasattr(self, 'image') and self.image is not None:
_dict['image'] = self.image
if hasattr(self, 'source_url') and self.source_url is not None:
_dict['source_url'] = self.source_url
if hasattr(self, 'resolved_url') and self.resolved_url is not None:
_dict['resolved_url'] = self.resolved_url
if hasattr(self, 'error') and self.error is not None:
_dict['error'] = self.error._to_dict()
return _dict
def __str__(self):
"""Return a `str` version of this ImageWithFaces object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other
[docs]class WarningInfo(object):
"""
Information about something that went wrong.
:attr str warning_id: Codified warning string, such as `limit_reached`.
:attr str description: Information about the error.
"""
def __init__(self, warning_id, description):
"""
Initialize a WarningInfo object.
:param str warning_id: Codified warning string, such as `limit_reached`.
:param str description: Information about the error.
"""
self.warning_id = warning_id
self.description = description
@classmethod
def _from_dict(cls, _dict):
"""Initialize a WarningInfo object from a json dictionary."""
args = {}
if 'warning_id' in _dict:
args['warning_id'] = _dict.get('warning_id')
else:
raise ValueError(
'Required property \'warning_id\' not present in WarningInfo JSON'
)
if 'description' in _dict:
args['description'] = _dict.get('description')
else:
raise ValueError(
'Required property \'description\' not present in WarningInfo JSON'
)
return cls(**args)
def _to_dict(self):
"""Return a json dictionary representing this model."""
_dict = {}
if hasattr(self, 'warning_id') and self.warning_id is not None:
_dict['warning_id'] = self.warning_id
if hasattr(self, 'description') and self.description is not None:
_dict['description'] = self.description
return _dict
def __str__(self):
"""Return a `str` version of this WarningInfo object."""
return json.dumps(self._to_dict(), indent=2)
def __eq__(self, other):
"""Return `true` when self and other are equal, false otherwise."""
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Return `true` when self and other are not equal, false otherwise."""
return not self == other