summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel G. Taylor <danielgtaylor@gmail.com>2014-04-17 16:35:08 -0700
committerDaniel G. Taylor <danielgtaylor@gmail.com>2014-04-17 16:35:08 -0700
commit0f93bbad88c0ed66eb945e8bf6b03008ffb2a87b (patch)
tree68956df2f6c5ffe67199c833d7888e1bb2e097ff
parent5ec8c7cb1bd778be3dbd01d2f005775ea910217a (diff)
downloadboto-0f93bbad88c0ed66eb945e8bf6b03008ffb2a87b.tar.gz
CloudSearch2 updates
Changes the following: * Generated layer1.py from service model * Layer1 -> CloudSearchConnection * Layer1 now uses JSON instead of XML responses * Updated layer2 objects to use JSON and generated layer1 * Updated doc service to remove attributes which are no longer valid * Updated search service to remove attributes which are no longer valid and modify existing attributes which have changed * Updated unit tests and integration tests for all of the above
-rw-r--r--boto/cloudsearch2/__init__.py9
-rw-r--r--boto/cloudsearch2/document.py57
-rw-r--r--boto/cloudsearch2/domain.py238
-rw-r--r--boto/cloudsearch2/exceptions.py46
-rw-r--r--boto/cloudsearch2/layer1.py1440
-rw-r--r--boto/cloudsearch2/layer2.py21
-rw-r--r--boto/cloudsearch2/optionstatus.py50
-rw-r--r--boto/cloudsearch2/search.py8
-rw-r--r--docs/source/ref/cloudsearch.rst49
-rw-r--r--docs/source/ref/cloudsearch2.rst61
-rw-r--r--setup.py3
-rw-r--r--tests/integration/cloudsearch2/test_layers.py11
-rw-r--r--tests/unit/cloudsearch2/test_connection.py240
-rw-r--r--tests/unit/cloudsearch2/test_document.py71
-rw-r--r--tests/unit/cloudsearch2/test_search.py161
15 files changed, 1261 insertions, 1204 deletions
diff --git a/boto/cloudsearch2/__init__.py b/boto/cloudsearch2/__init__.py
index bffa50d9..d14c9179 100644
--- a/boto/cloudsearch2/__init__.py
+++ b/boto/cloudsearch2/__init__.py
@@ -1,6 +1,4 @@
-# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
-# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
-# All Rights Reserved
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -20,8 +18,7 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
-#
-from boto.regioninfo import RegionInfo, get_regions
+from boto.regioninfo import get_regions
def regions():
@@ -34,7 +31,7 @@ def regions():
import boto.cloudsearch2.layer1
return get_regions(
'cloudsearch',
- connection_cls=boto.cloudsearch2.layer1.Layer1
+ connection_cls=boto.cloudsearch2.layer1.CloudSearchConnection
)
diff --git a/boto/cloudsearch2/document.py b/boto/cloudsearch2/document.py
index 7ce4b3fb..ed0f6c3f 100644
--- a/boto/cloudsearch2/document.py
+++ b/boto/cloudsearch2/document.py
@@ -1,6 +1,5 @@
# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
-# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
-# All Rights Reserved
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -62,13 +61,14 @@ class DocumentServiceConnection(object):
A CloudSearch document service.
The DocumentServiceConection is used to add, remove and update documents in
- CloudSearch. Commands are uploaded to CloudSearch in SDF (Search Document Format).
+ CloudSearch. Commands are uploaded to CloudSearch in SDF (Search Document
+ Format).
To generate an appropriate SDF, use :func:`add` to add or update documents,
as well as :func:`delete` to remove documents.
- Once the set of documents is ready to be index, use :func:`commit` to send the
- commands to CloudSearch.
+ Once the set of documents is ready to be index, use :func:`commit` to send
+ the commands to CloudSearch.
If there are a lot of documents to index, it may be preferable to split the
generation of SDF data and the actual uploading into CloudSearch. Retrieve
@@ -91,7 +91,7 @@ class DocumentServiceConnection(object):
self.documents_batch = []
self._sdf = None
- def add(self, _id, version, fields, lang='en'):
+ def add(self, _id, fields):
"""
Add a document to be processed by the DocumentService
@@ -100,39 +100,25 @@ class DocumentServiceConnection(object):
:type _id: string
:param _id: A unique ID used to refer to this document.
- :type version: int
- :param version: Version of the document being indexed. If a file is
- being reindexed, the version should be higher than the existing one
- in CloudSearch.
-
:type fields: dict
:param fields: A dictionary of key-value pairs to be uploaded .
-
- :type lang: string
- :param lang: The language code the data is in. Only 'en' is currently
- supported
"""
- d = {'type': 'add', 'id': _id, 'version': version, 'lang': lang,
- 'fields': fields}
+ d = {'type': 'add', 'id': _id, 'fields': fields}
self.documents_batch.append(d)
- def delete(self, _id, version):
+ def delete(self, _id):
"""
Schedule a document to be removed from the CloudSearch service
- The document will not actually be scheduled for removal until :func:`commit` is called
+ The document will not actually be scheduled for removal until
+ :func:`commit` is called
:type _id: string
:param _id: The unique ID of this document.
-
- :type version: int
- :param version: Version of the document to remove. The delete will only
- occur if this version number is higher than the version currently
- in the index.
"""
- d = {'type': 'delete', 'id': _id, 'version': version}
+ d = {'type': 'delete', 'id': _id}
self.documents_batch.append(d)
def get_sdf(self):
@@ -149,8 +135,8 @@ class DocumentServiceConnection(object):
"""
Clear the working documents from this DocumentServiceConnection
- This should be used after :func:`commit` if the connection will be reused
- for another set of documents.
+ This should be used after :func:`commit` if the connection will be
+ reused for another set of documents.
"""
self._sdf = None
@@ -184,8 +170,8 @@ class DocumentServiceConnection(object):
sdf = self.get_sdf()
if ': null' in sdf:
- boto.log.error('null value in sdf detected. This will probably raise '
- '500 error.')
+ boto.log.error('null value in sdf detected. This will probably '
+ 'raise 500 error.')
index = sdf.index(': null')
boto.log.error(sdf[index - 100:index + 100])
@@ -203,7 +189,8 @@ class DocumentServiceConnection(object):
)
session.mount('http://', adapter)
session.mount('https://', adapter)
- r = session.post(url, data=sdf, headers={'Content-Type': 'application/json'})
+ r = session.post(url, data=sdf,
+ headers={'Content-Type': 'application/json'})
return CommitResponse(r, self, sdf)
@@ -231,14 +218,15 @@ class CommitResponse(object):
try:
self.content = json.loads(response.content)
except:
- boto.log.error('Error indexing documents.\nResponse Content:\n{0}\n\n'
- 'SDF:\n{1}'.format(response.content, self.sdf))
+ boto.log.error('Error indexing documents.\nResponse Content:\n{0}'
+ '\n\nSDF:\n{1}'.format(response.content, self.sdf))
raise boto.exception.BotoServerError(self.response.status_code, '',
body=response.content)
self.status = self.content['status']
if self.status == 'error':
- self.errors = [e.get('message') for e in self.content.get('errors', [])]
+ self.errors = [e.get('message') for e in self.content.get('errors',
+ [])]
for e in self.errors:
if "Illegal Unicode character" in e:
raise EncodingError("Illegal Unicode character in document")
@@ -267,6 +255,7 @@ class CommitResponse(object):
if d['type'] == type_])
if response_num != commit_num:
+ boto.log.debug(self.response.content)
raise CommitMismatchError(
- 'Incorrect number of {0}s returned. Commit: {1} Response: {2}'\
+ 'Incorrect number of {0}s returned. Commit: {1} Response: {2}'
.format(type_, commit_num, response_num))
diff --git a/boto/cloudsearch2/domain.py b/boto/cloudsearch2/domain.py
index cca13c19..0643eaf8 100644
--- a/boto/cloudsearch2/domain.py
+++ b/boto/cloudsearch2/domain.py
@@ -1,6 +1,4 @@
-# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
-# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
-# All Rights Reserved
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -22,7 +20,6 @@
# IN THE SOFTWARE.
#
-import boto
from .optionstatus import IndexFieldStatus
from .optionstatus import ServicePoliciesStatus
from .optionstatus import ExpressionStatus
@@ -90,18 +87,18 @@ class Domain(object):
self.update_from_data(data)
def update_from_data(self, data):
- self.created = data['created']
- self.deleted = data['deleted']
- self.processing = data['processing']
- self.requires_index_documents = data['requires_index_documents']
- self.domain_id = data['domain_id']
- self.domain_name = data['domain_name']
- self.search_instance_count = data['search_instance_count']
- self.search_instance_type = data.get('search_instance_type', None)
- self.search_partition_count = data['search_partition_count']
- self._doc_service = data['doc_service']
- self._service_arn = data['arn']
- self._search_service = data['search_service']
+ self.created = data['Created']
+ self.deleted = data['Deleted']
+ self.processing = data['Processing']
+ self.requires_index_documents = data['RequiresIndexDocuments']
+ self.domain_id = data['DomainId']
+ self.domain_name = data['DomainName']
+ self.search_instance_count = data['SearchInstanceCount']
+ self.search_instance_type = data.get('SearchInstanceType', None)
+ self.search_partition_count = data['SearchPartitionCount']
+ self._doc_service = data['DocService']
+ self._service_arn = data['ARN']
+ self._search_service = data['SearchService']
@property
def service_arn(self):
@@ -109,11 +106,11 @@ class Domain(object):
@property
def doc_service_endpoint(self):
- return self._doc_service['endpoint']
+ return self._doc_service['Endpoint']
@property
def search_service_endpoint(self):
- return self._search_service['endpoint']
+ return self._search_service['Endpoint']
@property
def created(self):
@@ -189,11 +186,15 @@ class Domain(object):
object representing the currently defined availability options for
the domain.
:return: OptionsStatus object
- :rtype: :class:`boto.cloudsearch2.option.AvailabilityOptionsStatus` object
+ :rtype: :class:`boto.cloudsearch2.option.AvailabilityOptionsStatus`
+ object
"""
return AvailabilityOptionsStatus(
- self, None, self.layer1.describe_availability_options,
- self.layer1.update_availability_options)
+ self, refresh_fn=self.layer1.describe_availability_options,
+ refresh_key=['DescribeAvailabilityOptionsResponse',
+ 'DescribeAvailabilityOptionsResult',
+ 'AvailabilityOptions'],
+ save_fn=self.layer1.update_availability_options)
def get_scaling_options(self):
"""
@@ -201,12 +202,15 @@ class Domain(object):
object representing the currently defined scaling options for the
domain.
:return: ScalingParametersStatus object
- :rtype: :class:`boto.cloudsearch2.option.ScalingParametersStatus` object
+ :rtype: :class:`boto.cloudsearch2.option.ScalingParametersStatus`
+ object
"""
return ScalingParametersStatus(
- self, None,
- self.layer1.describe_scaling_parameters,
- self.layer1.update_scaling_parameters)
+ self, refresh_fn=self.layer1.describe_scaling_parameters,
+ refresh_key=['DescribeScalingParametersResponse',
+ 'DescribeScalingParametersResult',
+ 'ScalingParameters'],
+ save_fn=self.layer1.update_scaling_parameters)
def get_access_policies(self):
"""
@@ -216,9 +220,12 @@ class Domain(object):
:return: ServicePoliciesStatus object
:rtype: :class:`boto.cloudsearch2.option.ServicePoliciesStatus` object
"""
- return ServicePoliciesStatus(self, None,
- self.layer1.describe_service_access_policies,
- self.layer1.update_service_access_policies)
+ return ServicePoliciesStatus(
+ self, refresh_fn=self.layer1.describe_service_access_policies,
+ refresh_key=['DescribeServiceAccessPoliciesResponse',
+ 'DescribeServiceAccessPoliciesResult',
+ 'AccessPolicies'],
+ save_fn=self.layer1.update_service_access_policies)
def index_documents(self):
"""
@@ -234,9 +241,15 @@ class Domain(object):
"""
Return a list of index fields defined for this domain.
:return: list of IndexFieldStatus objects
- :rtype: list of :class:`boto.cloudsearch2.option.IndexFieldStatus` object
+ :rtype: list of :class:`boto.cloudsearch2.option.IndexFieldStatus`
+ object
"""
data = self.layer1.describe_index_fields(self.name, field_names)
+
+ data = (data['DescribeIndexFieldsResponse']
+ ['DescribeIndexFieldsResult']
+ ['IndexFields'])
+
return [IndexFieldStatus(self, d) for d in data]
def create_index_field(self, field_name, field_type,
@@ -308,14 +321,141 @@ class Domain(object):
:raises: BaseException, InternalException, LimitExceededException,
InvalidTypeException, ResourceNotFoundException
"""
- data = self.layer1.define_index_field(self.name, field_name, field_type,
- default=default, facet=facet,
- returnable=returnable,
- searchable=searchable,
- sortable=sortable,
- highlight=highlight,
- source_field=source_field,
- analysis_scheme=analysis_scheme)
+ index = {
+ 'IndexFieldName': field_name,
+ 'IndexFieldType': field_type
+ }
+ if field_type == 'literal':
+ index['LiteralOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['LiteralOptions']['DefaultValue'] = default
+ if source_field:
+ index['LiteralOptions']['SourceField'] = source_field
+ elif field_type == 'literal-array':
+ index['LiteralArrayOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable
+ }
+ if default:
+ index['LiteralArrayOptions']['DefaultValue'] = default
+ if source_field:
+ index['LiteralArrayOptions']['SourceFields'] = \
+ ','.join(source_field)
+ elif field_type == 'int':
+ index['IntOptions'] = {
+ 'DefaultValue': default,
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['IntOptions']['DefaultValue'] = default
+ if source_field:
+ index['IntOptions']['SourceField'] = source_field
+ elif field_type == 'int-array':
+ index['IntArrayOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable
+ }
+ if default:
+ index['IntArrayOptions']['DefaultValue'] = default
+ if source_field:
+ index['IntArrayOptions']['SourceFields'] = \
+ ','.join(source_field)
+ elif field_type == 'date':
+ index['DateOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['DateOptions']['DefaultValue'] = default
+ if source_field:
+ index['DateOptions']['SourceField'] = source_field
+ elif field_type == 'date-array':
+ index['DateArrayOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable
+ }
+ if default:
+ index['DateArrayOptions']['DefaultValue'] = default
+ if source_field:
+ index['DateArrayOptions']['SourceFields'] = \
+ ','.join(source_field)
+ elif field_type == 'double':
+ index['DoubleOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['DoubleOptions']['DefaultValue'] = default
+ if source_field:
+ index['DoubleOptions']['SourceField'] = source_field
+ elif field_type == 'double-array':
+ index['DoubleArrayOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable
+ }
+ if default:
+ index['DoubleArrayOptions']['DefaultValue'] = default
+ if source_field:
+ index['DoubleArrayOptions']['SourceFields'] = \
+ ','.join(source_field)
+ elif field_type == 'text':
+ index['TextOptions'] = {
+ 'ReturnEnabled': returnable,
+ 'HighlightEnabled': highlight,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['TextOptions']['DefaultValue'] = default
+ if source_field:
+ index['TextOptions']['SourceField'] = source_field
+ if analysis_scheme:
+ index['TextOptions']['AnalysisScheme'] = analysis_scheme
+ elif field_type == 'text-array':
+ index['TextArrayOptions'] = {
+ 'ReturnEnabled': returnable,
+ 'HighlightEnabled': highlight
+ }
+ if default:
+ index['TextArrayOptions']['DefaultValue'] = default
+ if source_field:
+ index['TextArrayOptions']['SourceFields'] = \
+ ','.join(source_field)
+ if analysis_scheme:
+ index['TextArrayOptions']['AnalysisScheme'] = analysis_scheme
+ elif field_type == 'latlon':
+ index['LatLonOptions'] = {
+ 'FacetEnabled': facet,
+ 'ReturnEnabled': returnable,
+ 'SearchEnabled': searchable,
+ 'SortEnabled': sortable
+ }
+ if default:
+ index['LatLonOptions']['DefaultValue'] = default
+ if source_field:
+ index['LatLonOptions']['SourceField'] = source_field
+
+ data = self.layer1.define_index_field(self.name, index)
+
+ data = (data['DefineIndexFieldResponse']
+ ['DefineIndexFieldResult']
+ ['IndexField'])
+
return IndexFieldStatus(self, data,
self.layer1.describe_index_fields)
@@ -323,10 +463,16 @@ class Domain(object):
"""
Return a list of rank expressions defined for this domain.
:return: list of ExpressionStatus objects
- :rtype: list of :class:`boto.cloudsearch2.option.ExpressionStatus` object
+ :rtype: list of :class:`boto.cloudsearch2.option.ExpressionStatus`
+ object
"""
fn = self.layer1.describe_expressions
data = fn(self.name, names)
+
+ data = (data['DescribeExpressionsResponse']
+ ['DescribeExpressionsResult']
+ ['Expressions'])
+
return [ExpressionStatus(self, d, fn) for d in data]
def create_expression(self, name, value):
@@ -345,7 +491,8 @@ class Domain(object):
* Single value, sort enabled numeric fields (int, double, date)
* Other expressions
- * The _score variable, which references a document's relevance score
+ * The _score variable, which references a document's relevance
+ score
* The _time variable, which references the current epoch time
* Integer, floating point, hex, and octal literals
* Arithmetic operators: + - * / %
@@ -361,10 +508,10 @@ class Domain(object):
Expressions always return an integer value from 0 to the maximum
64-bit signed integer value (2^63 - 1). Intermediate results are
calculated as double-precision floating point values and the return
- value is rounded to the nearest integer. If the expression is invalid
- or evaluates to a negative value, it returns 0. If the expression
- evaluates to a value greater than the maximum, it returns the maximum
- value.
+ value is rounded to the nearest integer. If the expression is
+ invalid or evaluates to a negative value, it returns 0. If the
+ expression evaluates to a value greater than the maximum, it
+ returns the maximum value.
The source data for an Expression can be the name of an
IndexField of type int or double, another Expression or the
@@ -386,6 +533,11 @@ class Domain(object):
InvalidTypeException, ResourceNotFoundException
"""
data = self.layer1.define_expression(self.name, name, value)
+
+ data = (data['DefineExpressionResponse']
+ ['DefineExpressionResult']
+ ['Expression'])
+
return ExpressionStatus(self, data,
self.layer1.describe_expressions)
diff --git a/boto/cloudsearch2/exceptions.py b/boto/cloudsearch2/exceptions.py
new file mode 100644
index 00000000..c1141139
--- /dev/null
+++ b/boto/cloudsearch2/exceptions.py
@@ -0,0 +1,46 @@
+"""
+Exceptions that are specific to the cloudsearch2 module.
+"""
+from boto.exception import BotoServerError
+
+
+class InvalidTypeException(BotoServerError):
+ """
+ Raised when an invalid record type is passed to CloudSearch.
+ """
+ pass
+
+
+class LimitExceededException(BotoServerError):
+ """
+ Raised when a limit has been exceeded.
+ """
+ pass
+
+
+class InternalException(BotoServerError):
+ """
+ A generic server-side error.
+ """
+ pass
+
+
+class DisabledOperationException(BotoServerError):
+ """
+ Raised when an operation has been disabled.
+ """
+ pass
+
+
+class ResourceNotFoundException(BotoServerError):
+ """
+ Raised when a requested resource does not exist.
+ """
+ pass
+
+
+class BaseException(BotoServerError):
+ """
+ A generic server-side error.
+ """
+ pass
diff --git a/boto/cloudsearch2/layer1.py b/boto/cloudsearch2/layer1.py
index 08c52e85..2604ee97 100644
--- a/boto/cloudsearch2/layer1.py
+++ b/boto/cloudsearch2/layer1.py
@@ -1,6 +1,4 @@
-# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
-# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
-# All Rights Reserved
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -20,897 +18,767 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
+#
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
import boto
-import boto.jsonresponse
-from boto.compat import json
from boto.connection import AWSQueryConnection
from boto.regioninfo import RegionInfo
-
-#boto.set_stream_logger('cloudsearch')
-
-
-def do_bool(val):
- return 'true' if val in [True, 1, '1', 'true'] else 'false'
-
-
-class Layer1(AWSQueryConnection):
-
- APIVersion = '2013-01-01'
- #AuthServiceName = 'sqs'
- DefaultRegionName = boto.config.get('Boto', 'cs_region_name', 'us-east-1')
- DefaultRegionEndpoint = boto.config.get('Boto', 'cs_region_endpoint',
- 'cloudsearch.us-east-1.amazonaws.com')
-
- def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
- is_secure=True, host=None, port=None,
- proxy=None, proxy_port=None,
- proxy_user=None, proxy_pass=None, debug=0,
- https_connection_factory=None, region=None, path='/',
- api_version=None, security_token=None,
- validate_certs=True, profile_name=None):
+from boto.exception import JSONResponseError
+from boto.cloudsearch2 import exceptions
+
+
+class CloudSearchConnection(AWSQueryConnection):
+ """
+ Amazon CloudSearch Configuration Service
+ You use the Amazon CloudSearch configuration service to create,
+ configure, and manage search domains. Configuration service
+ requests are submitted using the AWS Query protocol. AWS Query
+ requests are HTTP or HTTPS requests submitted via HTTP GET or POST
+ with a query parameter named Action.
+
+ The endpoint for configuration service requests is region-
+ specific: cloudsearch. region .amazonaws.com. For example,
+ cloudsearch.us-east-1.amazonaws.com. For a current list of
+ supported regions and endpoints, see `Regions and Endpoints`_.
+ """
+ APIVersion = "2013-01-01"
+ DefaultRegionName = "us-east-1"
+ DefaultRegionEndpoint = "cloudsearch.us-east-1.amazonaws.com"
+ ResponseError = JSONResponseError
+
+ _faults = {
+ "InvalidTypeException": exceptions.InvalidTypeException,
+ "LimitExceededException": exceptions.LimitExceededException,
+ "InternalException": exceptions.InternalException,
+ "DisabledOperationException": exceptions.DisabledOperationException,
+ "ResourceNotFoundException": exceptions.ResourceNotFoundException,
+ "BaseException": exceptions.BaseException,
+ }
+
+
+ def __init__(self, **kwargs):
+ region = kwargs.pop('region', None)
if not region:
region = RegionInfo(self, self.DefaultRegionName,
self.DefaultRegionEndpoint)
+
+ if 'host' not in kwargs or kwargs['host'] is None:
+ kwargs['host'] = region.endpoint
+
+ super(CloudSearchConnection, self).__init__(**kwargs)
self.region = region
- AWSQueryConnection.__init__(
- self,
- host=self.region.endpoint,
- aws_access_key_id=aws_access_key_id,
- aws_secret_access_key=aws_secret_access_key,
- is_secure=is_secure,
- port=port,
- proxy=proxy,
- proxy_port=proxy_port,
- proxy_user=proxy_user,
- proxy_pass=proxy_pass,
- debug=debug,
- https_connection_factory=https_connection_factory,
- path=path,
- security_token=security_token,
- validate_certs=validate_certs,
- profile_name=profile_name)
def _required_auth_capability(self):
return ['hmac-v4']
- def get_response(self, doc_path, action, params, path='/',
- parent=None, verb='GET', list_marker=None):
- if not parent:
- parent = self
- response = self.make_request(action, params, path, verb)
- body = response.read()
- boto.log.debug(body)
- if response.status == 200:
- e = boto.jsonresponse.Element(
- list_marker=list_marker if list_marker else 'Set',
- pythonize_name=True)
- h = boto.jsonresponse.XmlHandler(e, parent)
- h.parse(body)
- inner = e
- for p in doc_path:
- inner = inner.get(p)
- if not inner:
- return None if list_marker is None else []
- if isinstance(inner, list):
- return inner
- else:
- return dict(**inner)
- else:
- raise self.ResponseError(response.status, response.reason, body)
+ def build_suggesters(self, domain_name):
+ """
+ Indexes the search suggestions.
+
+ :type domain_name: string
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ """
+ params = {'DomainName': domain_name, }
+ return self._make_request(
+ action='BuildSuggesters',
+ verb='POST',
+ path='/', params=params)
def create_domain(self, domain_name):
"""
- Create a new search domain.
+ Creates a new search domain. For more information, see
+ `Creating a Search Domain`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: A name for the domain you are creating. Allowed
+ characters are a-z (lower-case letters), 0-9, and hyphen (-).
+ Domain names must start with a letter or number and be at least 3
+ and no more than 28 characters long.
- :raises: BaseException, InternalException, LimitExceededException
"""
- doc_path = ('create_domain_response',
- 'create_domain_result',
- 'domain_status')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'CreateDomain',
- params, verb='POST')
+ params = {'DomainName': domain_name, }
+ return self._make_request(
+ action='CreateDomain',
+ verb='POST',
+ path='/', params=params)
- def define_analysis_scheme(self, domain_name, name, language,
- algorithmic_stemming="none", stemming_dictionary=None,
- stopwords=None, synonyms=None):
+ def define_analysis_scheme(self, domain_name, analysis_scheme):
"""
- Updates stemming options used by indexing for the search domain.
+ Configures an analysis scheme for a domain. An analysis scheme
+ defines language-specific text processing options for a `text`
+ field. For more information, see `Configuring Analysis
+ Schemes`_ in the Amazon CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type name: str
- :param name: Name of the analysis scheme
-
- :type language: str
- :param language: IETF RFC 4646 lang code or 'mul' for multiple
- languages.
-
- :type algorithmic_stemming: str
- :param algorithmic_stemming: Which type of stemming to use.
- one of ``none | minimal | light | full``
-
- :type stemming_dictionary: dict
- :param stemming_dictionary: dict of stemming words
- ``{"running": "run", "jumping": "jump"}``
-
- :type stopwords: list of strings
- :param stopwords: list of stopwords
-
- :type synonyms: dict
- :param synonyms: dict of Array of words to use as synonyms
- ``{"aliases": {"running": ["run", "ran"], "jumping": ["jump", "jumped"]},
- "groups": [["sit", "sitting", "sat"], ["hit", "hitting"]]}``
-
- :raises: BaseException, InternalException, InvalidTypeException,
- LimitExceededException, ResourceNotFoundException
- """
- doc_path = ('define_analysis_scheme_response',
- 'define_analysis_scheme_result',
- 'analysis_scheme')
- params = {'DomainName': domain_name, 'AnalysisScheme.AnalysisSchemeName': name,
- 'AnalysisScheme.AnalysisSchemeLanguage': language,
- 'AnalysisScheme.AnalysisOptions.AlgorithmicStemming': algorithmic_stemming,
- 'AnalysisScheme.AnalysisOptions.StemmingDictionary':
- json.dumps(stemming_dictionary) if stemming_dictionary else dict(),
- 'AnalysisScheme.AnalysisOptions.Stopwords':
- json.dumps(stopwords) if stopwords else list(),
- 'AnalysisScheme.AnalysisOptions.Synonyms':
- json.dumps(synonyms) if synonyms else dict(),
- }
-
- return self.get_response(doc_path, 'DefineAnalysisScheme',
- params, verb='POST')
-
- def define_expression(self, domain_name, name, value):
- """
- Defines an Expression, either replacing an existing
- definition or creating a new one.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type analysis_scheme: dict
+ :param analysis_scheme: Configuration information for an analysis
+ scheme. Each analysis scheme has a unique name and specifies the
+ language of the text to be processed. The following options can be
+ configured for an analysis scheme: `Synonyms`, `Stopwords`,
+ `StemmingDictionary`, and `AlgorithmicStemming`.
+
+ """
+ params = {'DomainName': domain_name, }
+ self.build_complex_param(params, 'AnalysisScheme',
+ analysis_scheme)
+ return self._make_request(
+ action='DefineAnalysisScheme',
+ verb='POST',
+ path='/', params=params)
+
+ def define_expression(self, domain_name, expression):
+ """
+ Configures an `Expression` for the search domain. Used to
+ create new expressions and modify existing ones. If the
+ expression exists, the new configuration replaces the old one.
+ For more information, see `Configuring Expressions`_ in the
+ Amazon CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type name: string
- :param name: The name of an expression.
-
- :type value: string
- :param value: The expression to evaluate for ranking or
- thresholding while processing a search request. The
- Expression syntax is based on JavaScript and supports:
-
- * Single value, sort enabled numeric fields (int, double, date)
- * Other expressions
- * The _score variable, which references a document's relevance score
- * The _time variable, which references the current epoch time
- * Integer, floating point, hex, and octal literals
- * Arithmetic operators: + - * / %
- * Bitwise operators: | & ^ ~ << >> >>>
- * Boolean operators (including the ternary operator): && || ! ?:
- * Comparison operators: < <= == >= >
- * Mathematical functions: abs ceil exp floor ln log2 log10 logn
- max min pow sqrt pow
- * Trigonometric functions: acos acosh asin asinh atan atan2 atanh
- cos cosh sin sinh tanh tan
- * The haversin distance function
-
- Expressions always return an integer value from 0 to the maximum
- 64-bit signed integer value (2^63 - 1). Intermediate results are
- calculated as double-precision floating point values and the return
- value is rounded to the nearest integer. If the expression is invalid
- or evaluates to a negative value, it returns 0. If the expression
- evaluates to a value greater than the maximum, it returns the maximum
- value.
-
- The source data for an Expression can be the name of an
- IndexField of type int or double, another Expression or the
- reserved name _score, or the functions above. The _score source is
- defined to return as a double with a floor of 0 to
- indicate how relevant a document is to the search request,
- taking into account repetition of search terms in the
- document and proximity of search terms to each other in
- each matching IndexField in the document.
-
- For more information about using expressions to customize results,
- see the Amazon CloudSearch Developer Guide.
-
- :raises: BaseException, InternalException, LimitExceededException,
- InvalidTypeException, ResourceNotFoundException
- """
- doc_path = ('define_expression_response',
- 'define_expression_result',
- 'expression')
- params = {'DomainName': domain_name,
- 'Expression.ExpressionValue': value,
- 'Expression.ExpressionName': name}
- return self.get_response(doc_path, 'DefineExpression',
- params, verb='POST')
-
- def define_index_field(self, domain_name, field_name, field_type,
- default=None, facet=False, returnable=False,
- searchable=False, sortable=False,
- highlight=False, source_field=None,
- analysis_scheme=None):
- """
- Defines an ``IndexField``, either replacing an existing
- definition or creating a new one.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type expression: dict
+ :param expression: A named expression that can be evaluated at search
+ time. Can be used for sorting and filtering search results and
+ constructing other expressions.
+
+ """
+ params = {'DomainName': domain_name, }
+ self.build_complex_param(params, 'Expression',
+ expression)
+ return self._make_request(
+ action='DefineExpression',
+ verb='POST',
+ path='/', params=params)
+
+ def define_index_field(self, domain_name, index_field):
+ """
+ Configures an `IndexField` for the search domain. Used to
+ create new fields and modify existing ones. You must specify
+ the name of the domain you are configuring and an index field
+ configuration. The index field configuration specifies a
+ unique name, the index field type, and the options you want to
+ configure for the field. The options you can specify depend on
+ the `IndexFieldType`. If the field exists, the new
+ configuration replaces the old one. For more information, see
+ `Configuring Index Fields`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type field_name: string
- :param field_name: The name of a field in the search index.
-
- :type field_type: string
- :param field_type: The type of field. Valid values are
- int | double | literal | text | date | latlon |
- int-array | double-array | literal-array | text-array | date-array
-
- :type default: string or int
- :param default: The default value for the field. If the
- field is of type ``int`` this should be an integer value.
- Otherwise, it's a string.
-
- :type facet: bool
- :param facet: A boolean to indicate whether facets
- are enabled for this field or not. Does not apply to
- fields of type ``int, int-array, text, text-array``.
-
- :type returnable: bool
- :param returnable: A boolean to indicate whether values
- of this field can be returned in search results or
- used in ranking.
-
- :type searchable: bool
- :param searchable: A boolean to indicate whether search
- is enabled for this field or not.
-
- :type sortable: bool
- :param sortable: A boolean to indicate whether sorting
- is enabled for this field or not. Does not apply to
- fields of array types.
-
- :type highlight: bool
- :param highlight: A boolean to indicate whether highlighting
- is enabled for this field or not. Does not apply to
- fields of type ``double, int, date, latlon``
-
- :type source_field: list of strings or string
- :param source_field: For array types, this is the list of fields
- to treat as the source. For singular types, pass a string only.
-
- :type analysis_scheme: string
- :param analysis_scheme: The analysis scheme to use for this field.
- Only applies to ``text | text-array`` field types
-
- :raises: BaseException, InternalException, LimitExceededException,
- InvalidTypeException, ResourceNotFoundException
- """
- doc_path = ('define_index_field_response',
- 'define_index_field_result',
- 'index_field')
- params = {'DomainName': domain_name,
- 'IndexField.IndexFieldName': field_name,
- 'IndexField.IndexFieldType': field_type}
- if field_type == 'literal':
- if default:
- params['IndexField.LiteralOptions.DefaultValue'] = default
- params['IndexField.LiteralOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.LiteralOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.LiteralOptions.SearchEnabled'] = do_bool(searchable)
- params['IndexField.LiteralOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.LiteralOptions.SourceField'] = source_field
- elif field_type == 'literal-array':
- if default:
- params['IndexField.LiteralArrayOptions.DefaultValue'] = default
- params['IndexField.LiteralArrayOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.LiteralArrayOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.LiteralArrayOptions.SearchEnabled'] = do_bool(searchable)
- if source_field:
- params['IndexField.LiteralArrayOptions.SourceFields'] = ','.join(source_field)
- elif field_type == 'int':
- if default:
- params['IndexField.IntOptions.DefaultValue'] = default
- params['IndexField.IntOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.IntOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.IntOptions.SearchEnabled'] = do_bool(searchable)
- params['IndexField.IntOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.IntOptions.SourceField'] = source_field
- elif field_type == 'int-array':
- if default:
- params['IndexField.IntArrayOptions.DefaultValue'] = default
- params['IndexField.IntArrayOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.IntArrayOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.IntArrayOptions.SearchEnabled'] = do_bool(searchable)
- if source_field:
- params['IndexField.IntArrayOptions.SourceFields'] = ','.join(source_field)
- elif field_type == 'date':
- if default:
- params['IndexField.DateOptions.DefaultValue'] = default
- params['IndexField.DateOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.DateOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.DateOptions.SearchEnabled'] = do_bool(searchable)
- params['IndexField.DateOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.DateOptions.SourceField'] = source_field
- elif field_type == 'date-array':
- if default:
- params['IndexField.DateArrayOptions.DefaultValue'] = default
- params['IndexField.DateArrayOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.DateArrayOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.DateArrayOptions.SearchEnabled'] = do_bool(searchable)
- if source_field:
- params['IndexField.DateArrayOptions.SourceFields'] = ','.join(source_field)
- elif field_type == 'double':
- if default:
- params['IndexField.DoubleOptions.DefaultValue'] = default
- params['IndexField.DoubleOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.DoubleOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.DoubleOptions.SearchEnabled'] = do_bool(searchable)
- params['IndexField.DoubleOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.DoubleOptions.SourceField'] = source_field
- elif field_type == 'double-array':
- if default:
- params['IndexField.DoubleArrayOptions.DefaultValue'] = default
- params['IndexField.DoubleArrayOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.DoubleArrayOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.DoubleArrayOptions.SearchEnabled'] = do_bool(searchable)
- if source_field:
- params['IndexField.DoubleArrayOptions.SourceFields'] = ','.join(source_field)
- elif field_type == 'text':
- if default:
- params['IndexField.TextOptions.DefaultValue'] = default
- params['IndexField.TextOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.TextOptions.HighlightEnabled'] = do_bool(highlight)
- params['IndexField.TextOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.TextOptions.SourceField'] = source_field
- if analysis_scheme:
- params['IndexField.TextOptions.AnalysisScheme'] = analysis_scheme
- elif field_type == 'text-array':
- if default:
- params['IndexField.TextArrayOptions.DefaultValue'] = default
- params['IndexField.TextArrayOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.TextArrayOptions.HighlightEnabled'] = do_bool(highlight)
- if source_field:
- params['IndexField.TextArrayOptions.SourceFields'] = ','.join(source_field)
- if analysis_scheme:
- params['IndexField.TextArrayOptions.AnalysisScheme'] = analysis_scheme
- elif field_type == 'latlon':
- if default:
- params['IndexField.LatLonOptions.DefaultValue'] = default
- params['IndexField.LatLonOptions.FacetEnabled'] = do_bool(facet)
- params['IndexField.LatLonOptions.ReturnEnabled'] = do_bool(returnable)
- params['IndexField.LatLonOptions.SearchEnabled'] = do_bool(searchable)
- params['IndexField.LatLonOptions.SortEnabled'] = do_bool(sortable)
- if source_field:
- params['IndexField.LatLonOptions.SourceField'] = source_field
-
- return self.get_response(doc_path, 'DefineIndexField',
- params, verb='POST')
-
- def define_suggester(self, domain_name, name, source_field,
- fuzzy_matching=None, sort_expression=None):
- """
- Defines an Expression, either replacing an existing
- definition or creating a new one.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type index_field: dict
+ :param index_field: The index field and field options you want to
+ configure.
+
+ """
+ params = {'DomainName': domain_name, }
+ self.build_complex_param(params, 'IndexField',
+ index_field)
+ return self._make_request(
+ action='DefineIndexField',
+ verb='POST',
+ path='/', params=params)
+
+ def define_suggester(self, domain_name, suggester):
+ """
+ Configures a suggester for a domain. A suggester enables you
+ to display possible matches before users finish typing their
+ queries. When you configure a suggester, you must specify the
+ name of the text field you want to search for possible matches
+ and a unique name for the suggester. For more information, see
+ `Getting Search Suggestions`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type name: string
- :param name: The name of an suggester to use.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
- :type source_field: string
- :param source_field: The source field name to use for the ``Suggester``
+ :type suggester: dict
+ :param suggester: Configuration information for a search suggester.
+ Each suggester has a unique name and specifies the text field you
+ want to use for suggestions. The following options can be
+ configured for a suggester: `FuzzyMatching`, `SortExpression`.
- :type fuzzy_matching: string or None
- :param fuzzy_matching: The optional type of fuzzy matching to use. One of
- none | low | high
-
- :type sort_expression: string or None
- :param sort_expression: The optional sort expression to use
-
- :raises: BaseException, InternalException, LimitExceededException,
- InvalidTypeException, ResourceNotFoundException
"""
- doc_path = ('define_expression_response',
- 'define_expression_result',
- 'expression')
- params = {'DomainName': domain_name,
- 'Suggester.SuggesterName': name,
- 'Suggester.DocumentSuggesterOptions.SourceField': source_field}
- if fuzzy_matching is not None:
- params['Suggester.DocumentSuggesterOptions.FuzzyMatching'] = fuzzy_matching
- if sort_expression is not None:
- params['Suggester.DocumentSuggesterOptions.SortExpression'] = sort_expression
+ params = {'DomainName': domain_name, }
+ self.build_complex_param(params, 'Suggester',
+ suggester)
+ return self._make_request(
+ action='DefineSuggester',
+ verb='POST',
+ path='/', params=params)
- return self.get_response(doc_path, 'DefineExpression', params,
- verb='POST')
-
- def delete_analysis_scheme(self, domain_name, scheme_name):
+ def delete_analysis_scheme(self, domain_name, analysis_scheme_name):
"""
- Deletes an existing ``AnalysisScheme`` from the search domain.
+ Deletes an analysis scheme. For more information, see
+ `Configuring Analysis Schemes`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type scheme_name: string
- :param scheme_name: The analysis scheme name to delete
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('delete_analysis_scheme_response',
- 'delete_analysis_scheme_result',
- 'analysis_scheme')
- params = {'DomainName': domain_name,
- 'AnalysisSchemeName': scheme_name}
- return self.get_response(doc_path, 'DeleteAnalysisScheme',
- params, verb='POST')
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type analysis_scheme_name: string
+ :param analysis_scheme_name: The name of the analysis scheme you want
+ to delete.
+
+ """
+ params = {
+ 'DomainName': domain_name,
+ 'AnalysisSchemeName': analysis_scheme_name,
+ }
+ return self._make_request(
+ action='DeleteAnalysisScheme',
+ verb='POST',
+ path='/', params=params)
def delete_domain(self, domain_name):
"""
- Delete a search domain.
+ Permanently deletes a search domain and all of its data. Once
+ a domain has been deleted, it cannot be recovered. For more
+ information, see `Deleting a Search Domain`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: The name of the domain you want to permanently
+ delete.
- :raises: BaseException, InternalException
"""
- doc_path = ('delete_domain_response',
- 'delete_domain_result',
- 'domain_status')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'DeleteDomain',
- params, verb='POST')
+ params = {'DomainName': domain_name, }
+ return self._make_request(
+ action='DeleteDomain',
+ verb='POST',
+ path='/', params=params)
- def delete_index_field(self, domain_name, field_name):
+ def delete_expression(self, domain_name, expression_name):
"""
- Deletes an existing ``IndexField`` from the search domain.
+ Removes an `Expression` from the search domain. For more
+ information, see `Configuring Expressions`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type field_name: string
- :param field_name: A string that represents the name of
- an index field. Field names must begin with a letter and
- can contain the following characters: a-z (lowercase),
- 0-9, and _ (underscore). Uppercase letters and hyphens are
- not allowed. The names "body", "docid", and
- "text_relevance" are reserved and cannot be specified as
- field or rank expression names.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('delete_index_field_response',
- 'delete_index_field_result',
- 'index_field')
- params = {'DomainName': domain_name,
- 'IndexFieldName': field_name}
- return self.get_response(doc_path, 'DeleteIndexField',
- params, verb='POST')
-
- def delete_expression(self, domain_name, name):
- """
- Deletes an existing ``Expression`` from the search domain.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
- :type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :type expression_name: string
+ :param expression_name: The name of the `Expression` to delete.
- :type name: string
- :param name: Name of the ``Expression`` to delete.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
"""
- doc_path = ('delete_expression_response',
- 'delete_expression_result',
- 'expression')
- params = {'DomainName': domain_name, 'ExpressionName': name}
- return self.get_response(doc_path, 'DeleteExpression',
- params, verb='POST')
+ params = {
+ 'DomainName': domain_name,
+ 'ExpressionName': expression_name,
+ }
+ return self._make_request(
+ action='DeleteExpression',
+ verb='POST',
+ path='/', params=params)
- def delete_suggester(self, domain_name, name):
+ def delete_index_field(self, domain_name, index_field_name):
"""
- Deletes an existing ``Suggester`` from the search domain.
+ Removes an `IndexField` from the search domain. For more
+ information, see `Configuring Index Fields`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
- :type name: string
- :param name: Name of the ``Suggester`` to delete.
+ :type index_field_name: string
+ :param index_field_name: The name of the index field your want to
+ remove from the domain's indexing options.
- :raises: BaseException, InternalException, ResourceNotFoundException
"""
- doc_path = ('delete_suggester_response',
- 'delete_suggester_result',
- 'suggester')
- params = {'DomainName': domain_name, 'SuggesterName': name}
- return self.get_response(doc_path, 'DeleteSuggester',
- params, verb='POST')
+ params = {
+ 'DomainName': domain_name,
+ 'IndexFieldName': index_field_name,
+ }
+ return self._make_request(
+ action='DeleteIndexField',
+ verb='POST',
+ path='/', params=params)
- def describe_analysis_schemes(self, domain_name):
+ def delete_suggester(self, domain_name, suggester_name):
"""
- Describes analysis schemes used by indexing for the search domain.
+ Deletes a suggester. For more information, see `Getting Search
+ Suggestions`_ in the Amazon CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_analysis_schemes_response',
- 'describe_analysis_schemes_result',
- 'analysis_schemes')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'DescribeAnalysisSchemes',
- params, verb='POST')
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type suggester_name: string
+ :param suggester_name: Specifies the name of the suggester you want to
+ delete.
+
+ """
+ params = {
+ 'DomainName': domain_name,
+ 'SuggesterName': suggester_name,
+ }
+ return self._make_request(
+ action='DeleteSuggester',
+ verb='POST',
+ path='/', params=params)
+
+ def describe_analysis_schemes(self, domain_name,
+ analysis_scheme_names=None, deployed=None):
+ """
+ Gets the analysis schemes configured for a domain. An analysis
+ scheme defines language-specific text processing options for a
+ `text` field. Can be limited to specific analysis schemes by
+ name. By default, shows all analysis schemes and includes any
+ pending changes to the configuration. Set the `Deployed`
+ option to `True` to show the active configuration and exclude
+ pending changes. For more information, see `Configuring
+ Analysis Schemes`_ in the Amazon CloudSearch Developer Guide .
- def describe_availability_options(self, domain_name):
- """
- Describes the availability options for the search domain.
+ :type domain_name: string
+ :param domain_name: The name of the domain you want to describe.
+
+ :type analysis_scheme_names: list
+ :param analysis_scheme_names: The analysis schemes you want to
+ describe.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if analysis_scheme_names is not None:
+ self.build_list_params(params,
+ analysis_scheme_names,
+ 'AnalysisSchemeNames.member')
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeAnalysisSchemes',
+ verb='POST',
+ path='/', params=params)
+
+ def describe_availability_options(self, domain_name, deployed=None):
+ """
+ Gets the availability options configured for a domain. By
+ default, shows the configuration with any pending changes. Set
+ the `Deployed` option to `True` to show the active
+ configuration and exclude pending changes. For more
+ information, see `Configuring Availability Options`_ in the
+ Amazon CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_availability_options_response',
- 'describe_availability_options_result',
- 'availability_options')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'DescribeAvailabilityOptions',
- params, verb='POST')
+ :param domain_name: The name of the domain you want to describe.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeAvailabilityOptions',
+ verb='POST',
+ path='/', params=params)
def describe_domains(self, domain_names=None):
"""
- Describes the domains (optionally limited to one or more
- domains by name) owned by this account.
+ Gets information about the search domains owned by this
+ account. Can be limited to specific domains. Shows all domains
+ by default. For more information, see `Getting Information
+ about a Search Domain`_ in the Amazon CloudSearch Developer
+ Guide .
:type domain_names: list
- :param domain_names: Limits the response to the specified domains.
+ :param domain_names: The names of the domains you want to include in
+ the response.
- :raises: BaseException, InternalException
"""
- doc_path = ('describe_domains_response',
- 'describe_domains_result',
- 'domain_status_list')
params = {}
- if domain_names:
- for i, domain_name in enumerate(domain_names, 1):
- params['DomainNames.member.%d' % i] = domain_name
- return self.get_response(doc_path, 'DescribeDomains',
- params, verb='POST',
- list_marker='DomainStatusList')
-
- def describe_expressions(self, domain_name, names=None):
- """
- Describes RankExpressions in the search domain, optionally
- limited to a single expression.
+ if domain_names is not None:
+ self.build_list_params(params,
+ domain_names,
+ 'DomainNames.member')
+ return self._make_request(
+ action='DescribeDomains',
+ verb='POST',
+ path='/', params=params)
+
+ def describe_expressions(self, domain_name, expression_names=None,
+ deployed=None):
+ """
+ Gets the expressions configured for the search domain. Can be
+ limited to specific expressions by name. By default, shows all
+ expressions and includes any pending changes to the
+ configuration. Set the `Deployed` option to `True` to show the
+ active configuration and exclude pending changes. For more
+ information, see `Configuring Expressions`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type names: list
- :param names: Limit response to the specified names.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_expressions_response',
- 'describe_expressions_result',
- 'expressions')
- params = {'DomainName': domain_name}
- if names:
- for i, expr_name in enumerate(names, 1):
- params['ExpressionNames.member.%d' % i] = expr_name
- return self.get_response(doc_path, 'DescribeExpressions',
- params, verb='POST',
- list_marker='Expressions')
-
- def describe_index_fields(self, domain_name, field_names=None):
- """
- Describes index fields in the search domain, optionally
- limited to a single ``IndexField``.
+ :param domain_name: The name of the domain you want to describe.
+
+ :type expression_names: list
+ :param expression_names: Limits the `DescribeExpressions` response to
+ the specified expressions. If not specified, all expressions are
+ shown.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if expression_names is not None:
+ self.build_list_params(params,
+ expression_names,
+ 'ExpressionNames.member')
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeExpressions',
+ verb='POST',
+ path='/', params=params)
+
+ def describe_index_fields(self, domain_name, field_names=None,
+ deployed=None):
+ """
+ Gets information about the index fields configured for the
+ search domain. Can be limited to specific fields by name. By
+ default, shows all fields and includes any pending changes to
+ the configuration. Set the `Deployed` option to `True` to show
+ the active configuration and exclude pending changes. For more
+ information, see `Getting Domain Information`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: The name of the domain you want to describe.
:type field_names: list
- :param field_names: Limits the response to the specified fields.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_index_fields_response',
- 'describe_index_fields_result',
- 'index_fields')
- params = {'DomainName': domain_name}
- if field_names:
- for i, field_name in enumerate(field_names, 1):
- params['FieldNames.member.%d' % i] = field_name
- return self.get_response(doc_path, 'DescribeIndexFields',
- params, verb='POST',
- list_marker='IndexFields')
+ :param field_names: A list of the index fields you want to describe. If
+ not specified, information is returned for all configured index
+ fields.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if field_names is not None:
+ self.build_list_params(params,
+ field_names,
+ 'FieldNames.member')
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeIndexFields',
+ verb='POST',
+ path='/', params=params)
def describe_scaling_parameters(self, domain_name):
"""
- Describes the scaling parameters for the search domain.
+ Gets the scaling parameters configured for a domain. A
+ domain's scaling parameters specify the desired search
+ instance type and replication count. For more information, see
+ `Configuring Scaling Options`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
- :raises: BaseException, InternalException, ResourceNotFoundException
"""
- doc_path = ('describe_scaling_parameters_response',
- 'describe_scaling_parameters_result',
- 'scaling_parameters')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'DescribeScalingParameters',
- params, verb='POST')
+ params = {'DomainName': domain_name, }
+ return self._make_request(
+ action='DescribeScalingParameters',
+ verb='POST',
+ path='/', params=params)
- def describe_service_access_policies(self, domain_name):
+ def describe_service_access_policies(self, domain_name, deployed=None):
"""
- Describes the resource-based policies controlling access to
- the services in this search domain.
+ Gets information about the access policies that control access
+ to the domain's document and search endpoints. By default,
+ shows the configuration with any pending changes. Set the
+ `Deployed` option to `True` to show the active configuration
+ and exclude pending changes. For more information, see
+ `Configuring Access for a Search Domain`_ in the Amazon
+ CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: The name of the domain you want to describe.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeServiceAccessPolicies',
+ verb='POST',
+ path='/', params=params)
+
+ def describe_suggesters(self, domain_name, suggester_names=None,
+ deployed=None):
+ """
+ Gets the suggesters configured for a domain. A suggester
+ enables you to display possible matches before users finish
+ typing their queries. Can be limited to specific suggesters by
+ name. By default, shows all suggesters and includes any
+ pending changes to the configuration. Set the `Deployed`
+ option to `True` to show the active configuration and exclude
+ pending changes. For more information, see `Getting Search
+ Suggestions`_ in the Amazon CloudSearch Developer Guide .
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_service_access_policies_response',
- 'describe_service_access_policies_result',
- 'access_policies')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'DescribeServiceAccessPolicies',
- params, verb='POST')
+ :type domain_name: string
+ :param domain_name: The name of the domain you want to describe.
+
+ :type suggester_names: list
+ :param suggester_names: The suggesters you want to describe.
+
+ :type deployed: boolean
+ :param deployed: Whether to display the deployed configuration (
+ `True`) or include any pending changes ( `False`). Defaults to
+ `False`.
+
+ """
+ params = {'DomainName': domain_name, }
+ if suggester_names is not None:
+ self.build_list_params(params,
+ suggester_names,
+ 'SuggesterNames.member')
+ if deployed is not None:
+ params['Deployed'] = str(
+ deployed).lower()
+ return self._make_request(
+ action='DescribeSuggesters',
+ verb='POST',
+ path='/', params=params)
- def describe_suggesters(self, domain_name, names=None):
+ def index_documents(self, domain_name):
"""
- Describes the suggesters for the search domain.
+ Tells the search domain to start indexing its documents using
+ the latest indexing options. This operation must be invoked to
+ activate options whose OptionStatus is
+ `RequiresIndexDocuments`.
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type names: list
- :param names: Limit response to the specified names.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('describe_suggesters_response',
- 'describe_suggesters_result',
- 'suggesters')
- params = {'DomainName': domain_name}
- if names:
- for i, suggester_name in enumerate(names, 1):
- params['SuggesterNames.member.%d' % i] = suggester_name
-
- return self.get_response(doc_path, 'DescribeSuggesters',
- params, verb='POST', list_marker="Suggesters")
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
- def index_documents(self, domain_name):
"""
- Tells the search domain to start scanning its documents using
- the latest text processing options and ``IndexFields``. This
- operation must be invoked to make visible in searches any
- options whose <a>OptionStatus</a> has ``OptionState`` of
- ``RequiresIndexDocuments``.
+ params = {'DomainName': domain_name, }
+ return self._make_request(
+ action='IndexDocuments',
+ verb='POST',
+ path='/', params=params)
- :type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :raises: BaseException, InternalException, ResourceNotFoundException
- """
- doc_path = ('index_documents_response',
- 'index_documents_result',
- 'field_names')
- params = {'DomainName': domain_name}
- return self.get_response(doc_path, 'IndexDocuments', params,
- verb='POST', list_marker='FieldNames')
+ def list_domain_names(self):
+ """
+ Lists all search domains owned by an account.
+
+
+ """
+ params = {}
+ return self._make_request(
+ action='ListDomainNames',
+ verb='POST',
+ path='/', params=params)
def update_availability_options(self, domain_name, multi_az):
"""
- Updates availability options for the search domain.
+ Configures the availability options for a domain. Enabling the
+ Multi-AZ option expands an Amazon CloudSearch domain to an
+ additional Availability Zone in the same Region to increase
+ fault tolerance in the event of a service disruption. Changes
+ to the Multi-AZ option can take about half an hour to become
+ active. For more information, see `Configuring Availability
+ Options`_ in the Amazon CloudSearch Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type multi_az: bool
- :param multi_az: Should the domain be setup in multiple
- Availability Zones
-
- :raises: BaseException, InternalException, InvalidTypeException,
- LimitExceededException, ResourceNotFoundException
- """
- doc_path = ('update_availability_options_response',
- 'update_availability_options_result',
- 'availability_options')
- params = {'DomainName': domain_name,
- 'MultiAZ': do_bool(multi_az)}
- return self.get_response(doc_path, 'UpdateAvailabilityOptions',
- params, verb='POST')
-
- def update_scaling_parameters(self, domain_name, instance_type=None,
- replication_count=0):
- """
- Updates scaling parameters for the search domain.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type multi_az: boolean
+ :param multi_az: You expand an existing search domain to a second
+ Availability Zone by setting the Multi-AZ option to true.
+ Similarly, you can turn off the Multi-AZ option to downgrade the
+ domain to a single Availability Zone by setting the Multi-AZ option
+ to `False`.
+
+ """
+ params = {'DomainName': domain_name, 'MultiAZ': multi_az, }
+ return self._make_request(
+ action='UpdateAvailabilityOptions',
+ verb='POST',
+ path='/', params=params)
+
+ def update_scaling_parameters(self, domain_name, scaling_parameters):
+ """
+ Configures scaling parameters for a domain. A domain's scaling
+ parameters specify the desired search instance type and
+ replication count. Amazon CloudSearch will still automatically
+ scale your domain based on the volume of data and traffic, but
+ not below the desired instance type and replication count. If
+ the Multi-AZ option is enabled, these values control the
+ resources used per Availability Zone. For more information,
+ see `Configuring Scaling Options`_ in the Amazon CloudSearch
+ Developer Guide .
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
-
- :type instance_type: str or None
- :param instance_type: The type of instance to use. One of
- None | search.m1.small | search.m1.large | search.m2.xlarge | search.m2.2xlarge
-
- :type replication_count: int
- :param replication_count: The desired number of replicas. A
- value of 0 will reset to the default.
-
- :raises: BaseException, InternalException, InvalidTypeException,
- LimitExceededException, ResourceNotFoundException
- """
- doc_path = ('update_scaling_parameters_response',
- 'update_scaling_parameters_result',
- 'scaling_parameters')
- params = {'DomainName': domain_name}
- if instance_type is not None:
- params["ScalingParameters.DesiredInstanceType"] = instance_type
- if replication_count is not None:
- params["ScalingParameters.DesiredReplicationCount"] = replication_count
- return self.get_response(doc_path, 'UpdateScalingParameters',
- params, verb='POST')
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
+
+ :type scaling_parameters: dict
+ :param scaling_parameters: The desired instance type and desired number
+ of replicas of each index partition.
+
+ """
+ params = {'DomainName': domain_name, }
+ self.build_complex_param(params, 'ScalingParameters',
+ scaling_parameters)
+ return self._make_request(
+ action='UpdateScalingParameters',
+ verb='POST',
+ path='/', params=params)
def update_service_access_policies(self, domain_name, access_policies):
"""
- Updates the policies controlling access to the services in
- this search domain.
+ Configures the access rules that control access to the
+ domain's document and search endpoints. For more information,
+ see ` Configuring Access for an Amazon CloudSearch Domain`_.
:type domain_name: string
- :param domain_name: A string that represents the name of a
- domain. Domain names must be unique across the domains
- owned by an account within an AWS region. Domain names
- must start with a letter or number and can contain the
- following characters: a-z (lowercase), 0-9, and -
- (hyphen). Uppercase letters and underscores are not
- allowed.
+ :param domain_name: A string that represents the name of a domain.
+ Domain names are unique across the domains owned by an account
+ within an AWS region. Domain names start with a letter or number
+ and can contain the following characters: a-z (lowercase), 0-9, and
+ - (hyphen).
:type access_policies: string
- :param access_policies: An IAM access policy as described in
- The Access Policy Language in Using AWS Identity and
- Access Management. The maximum size of an access policy
- document is 100KB.
-
- :raises: BaseException, InternalException, LimitExceededException,
- ResourceNotFoundException, InvalidTypeException
- """
- doc_path = ('update_service_access_policies_response',
- 'update_service_access_policies_result',
- 'access_policies')
- params = {'AccessPolicies': access_policies,
- 'DomainName': domain_name}
- return self.get_response(doc_path, 'UpdateServiceAccessPolicies',
- params, verb='POST')
+ :param access_policies: The access rules you want to configure. These
+ rules replace any existing rules.
+
+ """
+ params = {
+ 'DomainName': domain_name,
+ 'AccessPolicies': access_policies,
+ }
+ return self._make_request(
+ action='UpdateServiceAccessPolicies',
+ verb='POST',
+ path='/', params=params)
+
+ def build_complex_param(self, params, label, value):
+ """Serialize a structure.
+
+ For example::
+
+ param_type = 'structure'
+ label = 'IndexField'
+ value = {'IndexFieldName': 'a', 'IntOptions': {'DefaultValue': 5}}
+
+ would result in the params dict being updated with these params::
+
+ IndexField.IndexFieldName = a
+ IndexField.IntOptions.DefaultValue = 5
+
+ :type params: dict
+ :param params: The params dict. The complex list params
+ will be added to this dict.
+
+ :type label: str
+ :param label: String label for param key
+
+ :type value: any
+ :param value: The value to serialize
+ """
+ for k, v in value.items():
+ if type(v) in [dict]:
+ for k2, v2 in v.items():
+ self.build_complex_param(params, label + '.' + k, v)
+ elif type(v) in [bool]:
+ params['%s.%s' % (label, k)] = v and 'true' or 'false'
+ else:
+ params['%s.%s' % (label, k)] = v
+
+ def _make_request(self, action, verb, path, params):
+ params['ContentType'] = 'JSON'
+ response = self.make_request(action=action, verb='POST',
+ path='/', params=params)
+ body = response.read()
+ boto.log.debug(body)
+ if response.status == 200:
+ return json.loads(body)
+ else:
+ json_body = json.loads(body)
+ fault_name = json_body.get('Error', {}).get('Code', None)
+ exception_class = self._faults.get(fault_name, self.ResponseError)
+ raise exception_class(response.status, response.reason,
+ body=json_body)
diff --git a/boto/cloudsearch2/layer2.py b/boto/cloudsearch2/layer2.py
index bd73e523..d76c25e8 100644
--- a/boto/cloudsearch2/layer2.py
+++ b/boto/cloudsearch2/layer2.py
@@ -22,7 +22,7 @@
# IN THE SOFTWARE.
#
-from .layer1 import Layer1
+from .layer1 import CloudSearchConnection
from .domain import Domain
@@ -32,7 +32,15 @@ class Layer2(object):
is_secure=True, port=None, proxy=None, proxy_port=None,
host=None, debug=0, session_token=None, region=None,
validate_certs=True):
- self.layer1 = Layer1(
+
+ if type(region) in [str, unicode]:
+ import boto.cloudsearch2
+ for region_info in boto.cloudsearch2.regions():
+ if region_info.name == region:
+ region = region_info
+ break
+
+ self.layer1 = CloudSearchConnection(
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
is_secure=is_secure,
@@ -52,6 +60,11 @@ class Layer2(object):
:rtype: list of :class:`boto.cloudsearch2.domain.Domain`
"""
domain_data = self.layer1.describe_domains(domain_names)
+
+ domain_data = (domain_data['DescribeDomainsResponse']
+ ['DescribeDomainsResult']
+ ['DomainStatusList'])
+
return [Domain(self.layer1, data) for data in domain_data]
def create_domain(self, domain_name):
@@ -61,7 +74,9 @@ class Layer2(object):
:rtype: :class:`boto.cloudsearch2.domain.Domain`
"""
data = self.layer1.create_domain(domain_name)
- return Domain(self.layer1, data)
+ return Domain(self.layer1, data['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
def lookup(self, domain_name):
"""
diff --git a/boto/cloudsearch2/optionstatus.py b/boto/cloudsearch2/optionstatus.py
index a633eba0..9531ca85 100644
--- a/boto/cloudsearch2/optionstatus.py
+++ b/boto/cloudsearch2/optionstatus.py
@@ -51,21 +51,23 @@ class OptionStatus(dict):
option was last updated.
"""
- def __init__(self, domain, data=None, refresh_fn=None, save_fn=None):
+ def __init__(self, domain, data=None, refresh_fn=None, refresh_key=None,
+ save_fn=None):
self.domain = domain
self.refresh_fn = refresh_fn
+ self.refresh_key = refresh_key
self.save_fn = save_fn
self.refresh(data)
def _update_status(self, status):
- self.creation_date = status['creation_date']
- self.status = status['state']
- self.update_date = status['update_date']
- self.update_version = int(status['update_version'])
+ self.creation_date = status['CreationDate']
+ self.status = status['State']
+ self.update_date = status['UpdateDate']
+ self.update_version = int(status['UpdateVersion'])
def _update_options(self, options):
if options:
- self.update(json.loads(options))
+ self.update(options)
def refresh(self, data=None):
"""
@@ -76,9 +78,14 @@ class OptionStatus(dict):
if not data:
if self.refresh_fn:
data = self.refresh_fn(self.domain.name)
+
+ if data and self.refresh_key:
+ # Attempt to pull out the right nested bag of data
+ for key in self.refresh_key:
+ data = data[key]
if data:
- self._update_status(data['status'])
- self._update_options(data['options'])
+ self._update_status(data['Status'])
+ self._update_options(data['Options'])
def to_json(self):
"""
@@ -86,23 +93,6 @@ class OptionStatus(dict):
"""
return json.dumps(self)
- def startElement(self, name, attrs, connection):
- return None
-
- def endElement(self, name, value, connection):
- if name == 'CreationDate':
- self.created = value
- elif name == 'State':
- self.state = value
- elif name == 'UpdateDate':
- self.updated = value
- elif name == 'UpdateVersion':
- self.update_version = int(value)
- elif name == 'Options':
- self.update_from_json_doc(value)
- else:
- setattr(self, name, value)
-
def save(self):
"""
Write the current state of the local object back to the
@@ -123,30 +113,20 @@ class OptionStatus(dict):
class IndexFieldStatus(OptionStatus):
-
- def _update_options(self, options):
- self.update(options)
-
def save(self):
pass
class AvailabilityOptionsStatus(OptionStatus):
-
- def _update_options(self, options):
- self.update(MultiAZ=json.loads(options))
-
def save(self):
pass
class ScalingParametersStatus(IndexFieldStatus):
-
pass
class ExpressionStatus(IndexFieldStatus):
-
pass
diff --git a/boto/cloudsearch2/search.py b/boto/cloudsearch2/search.py
index 03155816..bfeca5a9 100644
--- a/boto/cloudsearch2/search.py
+++ b/boto/cloudsearch2/search.py
@@ -21,6 +21,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
+import json
from math import ceil
import boto
from boto.compat import json
@@ -43,13 +44,10 @@ class CommitMismatchError(Exception):
class SearchResults(object):
def __init__(self, **attrs):
self.rid = attrs['status']['rid']
- # self.doc_coverage_pct = attrs['info']['doc-coverage-pct']
self.time_ms = attrs['status']['time-ms']
self.hits = attrs['hits']['found']
self.docs = attrs['hits']['hit']
self.start = attrs['hits']['start']
- #self.rank = attrs['rank']
- #self.match_expression = attrs['match-expr']
self.query = attrs['query']
self.search_service = attrs['search_service']
@@ -57,7 +55,7 @@ class SearchResults(object):
if 'facets' in attrs:
for (facet, values) in attrs['facets'].iteritems():
if 'buckets' in values:
- self.facets[facet] = dict((k, v) for (k, v) in map(lambda x: (x['value'], x['count']), values['buckets']))
+ self.facets[facet] = dict((k, v) for (k, v) in map(lambda x: (x['value'], x['count']), values.get('buckets', [])))
self.num_pages_needed = ceil(self.hits / self.query.real_size)
@@ -131,6 +129,8 @@ class Query(object):
if self.facet:
for k, v in self.facet.iteritems():
+ if type(v) not in [str, unicode]:
+ v = json.dumps(v)
params['facet.%s' % k] = v
if self.highlight:
diff --git a/docs/source/ref/cloudsearch.rst b/docs/source/ref/cloudsearch.rst
index 1610200a..98d4a224 100644
--- a/docs/source/ref/cloudsearch.rst
+++ b/docs/source/ref/cloudsearch.rst
@@ -4,56 +4,51 @@
Cloudsearch
===========
-boto.cloudsearch
-----------------
+boto.cloudsearch2
+-----------------
-.. automodule:: boto.cloudsearch
- :members:
+.. automodule:: boto.cloudsearch2
+ :members:
:undoc-members:
-boto.cloudsearch.domain
------------------------
+boto.cloudsearch2.domain
+------------------------
-.. automodule:: boto.cloudsearch.domain
+.. automodule:: boto.cloudsearch2.domain
:members:
:undoc-members:
-boto.cloudsearch.layer1
------------------------
+boto.cloudsearch2.layer1
+------------------------
-.. automodule:: boto.cloudsearch.layer1
+.. automodule:: boto.cloudsearch2.layer1
:members:
:undoc-members:
-boto.cloudsearch.layer2
------------------------
+boto.cloudsearch2.layer2
+------------------------
-.. automodule:: boto.cloudsearch.layer2
+.. automodule:: boto.cloudsearch2.layer2
:members:
:undoc-members:
-boto.cloudsearch.optionstatus
------------------------------
+boto.cloudsearch2.optionstatus
+------------------------------
-.. automodule:: boto.cloudsearch.optionstatus
+.. automodule:: boto.cloudsearch2.optionstatus
:members:
:undoc-members:
-boto.cloudsearch.search
------------------------
+boto.cloudsearch2.search
+------------------------
-.. automodule:: boto.cloudsearch.search
+.. automodule:: boto.cloudsearch2.search
:members:
:undoc-members:
-boto.cloudsearch.document
--------------------------
+boto.cloudsearch2.document
+--------------------------
-.. automodule:: boto.cloudsearch.document
+.. automodule:: boto.cloudsearch2.document
:members:
:undoc-members:
-
-
-
-
-
diff --git a/docs/source/ref/cloudsearch2.rst b/docs/source/ref/cloudsearch2.rst
new file mode 100644
index 00000000..bac2d866
--- /dev/null
+++ b/docs/source/ref/cloudsearch2.rst
@@ -0,0 +1,61 @@
+.. ref-cloudsearch
+
+===========
+Cloudsearch
+===========
+
+boto.cloudsearch
+----------------
+
+.. automodule:: boto.cloudsearch
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.domain
+-----------------------
+
+.. automodule:: boto.cloudsearch.domain
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.exceptions
+-----------------------
+
+.. automodule:: boto.cloudsearch.exceptions
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.layer1
+-----------------------
+
+.. automodule:: boto.cloudsearch.layer1
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.layer2
+-----------------------
+
+.. automodule:: boto.cloudsearch.layer2
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.optionstatus
+-----------------------------
+
+.. automodule:: boto.cloudsearch.optionstatus
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.search
+-----------------------
+
+.. automodule:: boto.cloudsearch.search
+ :members:
+ :undoc-members:
+
+boto.cloudsearch.document
+-------------------------
+
+.. automodule:: boto.cloudsearch.document
+ :members:
+ :undoc-members:
diff --git a/setup.py b/setup.py
index 7e39e93a..c14b88bb 100644
--- a/setup.py
+++ b/setup.py
@@ -75,7 +75,8 @@ setup(name = "boto",
"boto.beanstalk", "boto.datapipeline", "boto.elasticache",
"boto.elastictranscoder", "boto.opsworks", "boto.redshift",
"boto.dynamodb2", "boto.support", "boto.cloudtrail",
- "boto.directconnect", "boto.kinesis", "boto.rds2"],
+ "boto.directconnect", "boto.kinesis", "boto.rds2",
+ "boto.cloudsearch2"],
package_data = {
"boto.cacerts": ["cacerts.txt"],
"boto": ["endpoints.json"],
diff --git a/tests/integration/cloudsearch2/test_layers.py b/tests/integration/cloudsearch2/test_layers.py
index 90ceda46..d2b13756 100644
--- a/tests/integration/cloudsearch2/test_layers.py
+++ b/tests/integration/cloudsearch2/test_layers.py
@@ -26,7 +26,7 @@ Tests for Layer1 of Cloudsearch
import time
from tests.unit import unittest
-from boto.cloudsearch2.layer1 import Layer1
+from boto.cloudsearch2.layer1 import CloudSearchConnection
from boto.cloudsearch2.layer2 import Layer2
from boto.regioninfo import RegionInfo
@@ -36,13 +36,18 @@ class CloudSearchLayer1Test(unittest.TestCase):
def setUp(self):
super(CloudSearchLayer1Test, self).setUp()
- self.layer1 = Layer1()
+ self.layer1 = CloudSearchConnection()
self.domain_name = 'test-%d' % int(time.time())
def test_create_domain(self):
resp = self.layer1.create_domain(self.domain_name)
+
+ resp = (resp['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
+
self.addCleanup(self.layer1.delete_domain, self.domain_name)
- self.assertTrue(resp.get('created', False))
+ self.assertTrue(resp.get('Created', False))
class CloudSearchLayer2Test(unittest.TestCase):
diff --git a/tests/unit/cloudsearch2/test_connection.py b/tests/unit/cloudsearch2/test_connection.py
index 6a2a0200..e31d7190 100644
--- a/tests/unit/cloudsearch2/test_connection.py
+++ b/tests/unit/cloudsearch2/test_connection.py
@@ -3,48 +3,50 @@
from tests.unit import AWSMockServiceTestCase
from boto.cloudsearch2.domain import Domain
-from boto.cloudsearch2.layer1 import Layer1
+from boto.cloudsearch2.layer1 import CloudSearchConnection
-import json
class TestCloudSearchCreateDomain(AWSMockServiceTestCase):
- connection_class = Layer1
+ connection_class = CloudSearchConnection
def default_body(self):
return """
-<CreateDomainResponse xmlns="http://cloudsearch.amazonaws.com/doc/2013-01-01">
- <CreateDomainResult>
- <DomainStatus>
- <SearchPartitionCount>0</SearchPartitionCount>
- <SearchService>
- <Arn>arn:aws:cs:us-east-1:1234567890:domain/demo</Arn>
- <Endpoint>search-demo-userdomain.us-east-1.cloudsearch.amazonaws.com</Endpoint>
- </SearchService>
- <Created>true</Created>
- <DomainId>1234567890/demo</DomainId>
- <Processing>false</Processing>
- <SearchInstanceCount>0</SearchInstanceCount>
- <DomainName>demo</DomainName>
- <RequiresIndexDocuments>false</RequiresIndexDocuments>
- <Deleted>false</Deleted>
- <DocService>
- <Arn>arn:aws:cs:us-east-1:1234567890:domain/demo</Arn>
- <Endpoint>doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com</Endpoint>
- </DocService>
- </DomainStatus>
- </CreateDomainResult>
- <ResponseMetadata>
- <RequestId>00000000-0000-0000-0000-000000000000</RequestId>
- </ResponseMetadata>
-</CreateDomainResponse>
+{
+ "CreateDomainResponse": {
+ "CreateDomainResult": {
+ "DomainStatus": {
+ "SearchInstanceType": null,
+ "DomainId": "1234567890/demo",
+ "DomainName": "demo",
+ "Deleted": false,
+ "SearchInstanceCount": 0,
+ "Created": true,
+ "SearchService": {
+ "Endpoint": "search-demo.us-east-1.cloudsearch.amazonaws.com"
+ },
+ "RequiresIndexDocuments": false,
+ "Processing": false,
+ "DocService": {
+ "Endpoint": "doc-demo.us-east-1.cloudsearch.amazonaws.com"
+ },
+ "ARN": "arn:aws:cs:us-east-1:1234567890:domain/demo",
+ "SearchPartitionCount": 0
+ }
+ },
+ "ResponseMetadata": {
+ "RequestId": "00000000-0000-0000-0000-000000000000"
+ }
+ }
+}
"""
def test_create_domain(self):
self.set_http_response(status_code=200)
- api_response = self.service_connection.create_domain('demo')
+ self.service_connection.create_domain('demo')
self.assert_request_parameters({
'Action': 'CreateDomain',
+ 'ContentType': 'JSON',
'DomainName': 'demo',
'Version': '2013-01-01',
})
@@ -54,22 +56,26 @@ class TestCloudSearchCreateDomain(AWSMockServiceTestCase):
self.set_http_response(status_code=200)
api_response = self.service_connection.create_domain('demo')
- domain = Domain(self, api_response)
+ domain = Domain(self, api_response['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
self.assertEqual(
domain.doc_service_endpoint,
- "doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
+ "doc-demo.us-east-1.cloudsearch.amazonaws.com")
self.assertEqual(domain.service_arn,
"arn:aws:cs:us-east-1:1234567890:domain/demo")
self.assertEqual(
domain.search_service_endpoint,
- "search-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
+ "search-demo.us-east-1.cloudsearch.amazonaws.com")
def test_cloudsearch_connect_result_statuses(self):
"""Check that domain statuses are correctly returned from AWS"""
self.set_http_response(status_code=200)
api_response = self.service_connection.create_domain('demo')
- domain = Domain(self, api_response)
+ domain = Domain(self, api_response['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
self.assertEqual(domain.created, True)
self.assertEqual(domain.processing, False)
@@ -80,7 +86,9 @@ class TestCloudSearchCreateDomain(AWSMockServiceTestCase):
"""Check that the domain information is correctly returned from AWS"""
self.set_http_response(status_code=200)
api_response = self.service_connection.create_domain('demo')
- domain = Domain(self, api_response)
+ domain = Domain(self, api_response['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
self.assertEqual(domain.id, "1234567890/demo")
self.assertEqual(domain.name, "demo")
@@ -88,56 +96,62 @@ class TestCloudSearchCreateDomain(AWSMockServiceTestCase):
def test_cloudsearch_documentservice_creation(self):
self.set_http_response(status_code=200)
api_response = self.service_connection.create_domain('demo')
- domain = Domain(self, api_response)
+ domain = Domain(self, api_response['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
document = domain.get_document_service()
self.assertEqual(
document.endpoint,
- "doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
+ "doc-demo.us-east-1.cloudsearch.amazonaws.com")
def test_cloudsearch_searchservice_creation(self):
self.set_http_response(status_code=200)
api_response = self.service_connection.create_domain('demo')
- domain = Domain(self, api_response)
+ domain = Domain(self, api_response['CreateDomainResponse']
+ ['CreateDomainResult']
+ ['DomainStatus'])
search = domain.get_search_service()
self.assertEqual(
search.endpoint,
- "search-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
+ "search-demo.us-east-1.cloudsearch.amazonaws.com")
class CloudSearchConnectionDeletionTest(AWSMockServiceTestCase):
- connection_class = Layer1
+ connection_class = CloudSearchConnection
def default_body(self):
return """
-<DeleteDomainResponse xmlns="http://cloudsearch.amazonaws.com/doc/2013-01-01">
- <DeleteDomainResult>
- <DomainStatus>
- <SearchPartitionCount>0</SearchPartitionCount>
- <SearchService>
- <Arn>arn:aws:cs:us-east-1:1234567890:search/demo</Arn>
- <Endpoint>search-demo-userdomain.us-east-1.cloudsearch.amazonaws.com</Endpoint>
- </SearchService>
- <Created>true</Created>
- <DomainId>1234567890/demo</DomainId>
- <Processing>false</Processing>
- <SearchInstanceCount>0</SearchInstanceCount>
- <DomainName>demo</DomainName>
- <RequiresIndexDocuments>false</RequiresIndexDocuments>
- <Deleted>false</Deleted>
- <DocService>
- <Arn>arn:aws:cs:us-east-1:1234567890:doc/demo</Arn>
- <Endpoint>doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com</Endpoint>
- </DocService>
- </DomainStatus>
- </DeleteDomainResult>
- <ResponseMetadata>
- <RequestId>00000000-0000-0000-0000-000000000000</RequestId>
- </ResponseMetadata>
-</DeleteDomainResponse>
+{
+ "DeleteDomainResponse": {
+ "DeleteDomainResult": {
+ "DomainStatus": {
+ "SearchInstanceType": null,
+ "DomainId": "1234567890/demo",
+ "DomainName": "test",
+ "Deleted": true,
+ "SearchInstanceCount": 0,
+ "Created": true,
+ "SearchService": {
+ "Endpoint": null
+ },
+ "RequiresIndexDocuments": false,
+ "Processing": false,
+ "DocService": {
+ "Endpoint": null
+ },
+ "ARN": "arn:aws:cs:us-east-1:1234567890:domain/demo",
+ "SearchPartitionCount": 0
+ }
+ },
+ "ResponseMetadata": {
+ "RequestId": "00000000-0000-0000-0000-000000000000"
+ }
+ }
+}
"""
def test_cloudsearch_deletion(self):
@@ -146,52 +160,55 @@ class CloudSearchConnectionDeletionTest(AWSMockServiceTestCase):
cloudsearch connection.
"""
self.set_http_response(status_code=200)
- api_response = self.service_connection.delete_domain('demo')
+ self.service_connection.delete_domain('demo')
self.assert_request_parameters({
'Action': 'DeleteDomain',
+ 'ContentType': 'JSON',
'DomainName': 'demo',
'Version': '2013-01-01',
})
class CloudSearchConnectionIndexDocumentTest(AWSMockServiceTestCase):
- connection_class = Layer1
+ connection_class = CloudSearchConnection
def default_body(self):
return """
-<IndexDocumentsResponse xmlns="http://cloudsearch.amazonaws.com/doc/2013-01-01">
- <IndexDocumentsResult>
- <FieldNames>
- <member>average_score</member>
- <member>brand_id</member>
- <member>colors</member>
- <member>context</member>
- <member>context_owner</member>
- <member>created_at</member>
- <member>creator_id</member>
- <member>description</member>
- <member>file_size</member>
- <member>format</member>
- <member>has_logo</member>
- <member>has_messaging</member>
- <member>height</member>
- <member>image_id</member>
- <member>ingested_from</member>
- <member>is_advertising</member>
- <member>is_photo</member>
- <member>is_reviewed</member>
- <member>modified_at</member>
- <member>subject_date</member>
- <member>tags</member>
- <member>title</member>
- <member>width</member>
- </FieldNames>
- </IndexDocumentsResult>
- <ResponseMetadata>
- <RequestId>eb2b2390-6bbd-11e2-ab66-93f3a90dcf2a</RequestId>
- </ResponseMetadata>
-</IndexDocumentsResponse>
+{
+ "IndexDocumentsResponse": {
+ "IndexDocumentsResult": {
+ "FieldNames": [
+ "average_score",
+ "brand_id",
+ "colors",
+ "context",
+ "context_owner",
+ "created_at",
+ "creator_id",
+ "description",
+ "file_size",
+ "format",
+ "has_logo",
+ "has_messaging",
+ "height",
+ "image_id",
+ "ingested_from",
+ "is_advertising",
+ "is_photo",
+ "is_reviewed",
+ "modified_at",
+ "subject_date",
+ "tags",
+ "title",
+ "width"
+ ]
+ },
+ "ResponseMetadata": {
+ "RequestId": "42e618d9-c4d9-11e3-8242-c32da3041159"
+ }
+ }
+}
"""
def test_cloudsearch_index_documents(self):
@@ -200,10 +217,11 @@ class CloudSearchConnectionIndexDocumentTest(AWSMockServiceTestCase):
domain.
"""
self.set_http_response(status_code=200)
- api_response = self.service_connection.index_documents('demo')
+ self.service_connection.index_documents('demo')
self.assert_request_parameters({
'Action': 'IndexDocuments',
+ 'ContentType': 'JSON',
'DomainName': 'demo',
'Version': '2013-01-01',
})
@@ -216,13 +234,17 @@ class CloudSearchConnectionIndexDocumentTest(AWSMockServiceTestCase):
self.set_http_response(status_code=200)
api_response = self.service_connection.index_documents('demo')
- self.assertEqual(api_response, ['average_score', 'brand_id', 'colors',
- 'context', 'context_owner',
- 'created_at', 'creator_id',
- 'description', 'file_size', 'format',
- 'has_logo', 'has_messaging', 'height',
- 'image_id', 'ingested_from',
- 'is_advertising', 'is_photo',
- 'is_reviewed', 'modified_at',
- 'subject_date', 'tags', 'title',
- 'width'])
+ fields = (api_response['IndexDocumentsResponse']
+ ['IndexDocumentsResult']
+ ['FieldNames'])
+
+ self.assertEqual(fields, ['average_score', 'brand_id', 'colors',
+ 'context', 'context_owner',
+ 'created_at', 'creator_id',
+ 'description', 'file_size', 'format',
+ 'has_logo', 'has_messaging', 'height',
+ 'image_id', 'ingested_from',
+ 'is_advertising', 'is_photo',
+ 'is_reviewed', 'modified_at',
+ 'subject_date', 'tags', 'title',
+ 'width'])
diff --git a/tests/unit/cloudsearch2/test_document.py b/tests/unit/cloudsearch2/test_document.py
index 7d9d011f..fc42403c 100644
--- a/tests/unit/cloudsearch2/test_document.py
+++ b/tests/unit/cloudsearch2/test_document.py
@@ -41,13 +41,12 @@ class CloudSearchDocumentSingleTest(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
document.commit()
args = json.loads(HTTPretty.last_request.body)[0]
- self.assertEqual(args['lang'], 'en')
self.assertEqual(args['type'], 'add')
def test_cloudsearch_add_single_basic(self):
@@ -57,14 +56,13 @@ class CloudSearchDocumentSingleTest(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
document.commit()
args = json.loads(HTTPretty.last_request.body)[0]
self.assertEqual(args['id'], '1234')
- self.assertEqual(args['version'], 10)
self.assertEqual(args['type'], 'add')
def test_cloudsearch_add_single_fields(self):
@@ -73,8 +71,8 @@ class CloudSearchDocumentSingleTest(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
document.commit()
args = json.loads(HTTPretty.last_request.body)[0]
@@ -90,8 +88,8 @@ class CloudSearchDocumentSingleTest(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
doc = document.commit()
self.assertEqual(doc.status, 'success')
@@ -111,17 +109,15 @@ class CloudSearchDocumentMultipleAddTest(CloudSearchDocumentTest):
objs = {
'1234': {
- 'version': 10, 'fields': {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b",
- "cat_c"]}},
+ 'fields': {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]}},
'1235': {
- 'version': 11, 'fields': {"id": "1235", "title": "Title 2",
+ 'fields': {"id": "1235", "title": "Title 2",
"category": ["cat_b", "cat_c",
"cat_d"]}},
'1236': {
- 'version': 12, 'fields': {"id": "1236", "title": "Title 3",
- "category": ["cat_e", "cat_f",
- "cat_g"]}},
+ 'fields': {"id": "1236", "title": "Title 3",
+ "category": ["cat_e", "cat_f", "cat_g"]}},
}
@@ -130,14 +126,13 @@ class CloudSearchDocumentMultipleAddTest(CloudSearchDocumentTest):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
for (key, obj) in self.objs.items():
- document.add(key, obj['version'], obj['fields'])
+ document.add(key, obj['fields'])
document.commit()
args = json.loads(HTTPretty.last_request.body)
for arg in args:
self.assertTrue(arg['id'] in self.objs)
- self.assertEqual(arg['version'], self.objs[arg['id']]['version'])
self.assertEqual(arg['fields']['id'],
self.objs[arg['id']]['fields']['id'])
self.assertEqual(arg['fields']['title'],
@@ -153,7 +148,7 @@ class CloudSearchDocumentMultipleAddTest(CloudSearchDocumentTest):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
for (key, obj) in self.objs.items():
- document.add(key, obj['version'], obj['fields'])
+ document.add(key, obj['fields'])
doc = document.commit()
self.assertEqual(doc.status, 'success')
@@ -175,11 +170,10 @@ class CloudSearchDocumentDelete(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.delete("5", "10")
+ document.delete("5")
document.commit()
args = json.loads(HTTPretty.last_request.body)[0]
- self.assertEqual(args['version'], '10')
self.assertEqual(args['type'], 'delete')
self.assertEqual(args['id'], '5')
@@ -189,7 +183,7 @@ class CloudSearchDocumentDelete(CloudSearchDocumentTest):
"""
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.delete("5", "10")
+ document.delete("5")
doc = document.commit()
self.assertEqual(doc.status, 'success')
@@ -207,8 +201,8 @@ class CloudSearchDocumentDeleteMultiple(CloudSearchDocumentTest):
def test_cloudsearch_delete_multiples(self):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.delete("5", "10")
- document.delete("6", "11")
+ document.delete("5")
+ document.delete("6")
document.commit()
args = json.loads(HTTPretty.last_request.body)
@@ -216,13 +210,6 @@ class CloudSearchDocumentDeleteMultiple(CloudSearchDocumentTest):
for arg in args:
self.assertEqual(arg['type'], 'delete')
- if arg['id'] == '5':
- self.assertEqual(arg['version'], '10')
- elif arg['id'] == '6':
- self.assertEqual(arg['version'], '11')
- else: # Unknown result out of AWS that shouldn't be there
- self.assertTrue(False)
-
class CloudSearchSDFManipulation(CloudSearchDocumentTest):
response = {
@@ -242,8 +229,8 @@ class CloudSearchSDFManipulation(CloudSearchDocumentTest):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
self.assertNotEqual(document.get_sdf(), '[]')
@@ -264,8 +251,8 @@ class CloudSearchBadSDFTesting(CloudSearchDocumentTest):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": None,
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": None,
+ "category": ["cat_a", "cat_b", "cat_c"]})
document.commit()
self.assertNotEqual(len(boto.log.error.call_args_list), 1)
@@ -284,8 +271,8 @@ class CloudSearchDocumentErrorBadUnicode(CloudSearchDocumentTest):
def test_fake_bad_unicode(self):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
self.assertRaises(EncodingError, document.commit)
@@ -300,8 +287,8 @@ class CloudSearchDocumentErrorDocsTooBig(CloudSearchDocumentTest):
def test_fake_docs_too_big(self):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
self.assertRaises(ContentTooLongError, document.commit)
@@ -318,7 +305,7 @@ class CloudSearchDocumentErrorMismatch(CloudSearchDocumentTest):
document = DocumentServiceConnection(
endpoint="doc-demo-userdomain.us-east-1.cloudsearch.amazonaws.com")
- document.add("1234", 10, {"id": "1234", "title": "Title 1",
- "category": ["cat_a", "cat_b", "cat_c"]})
+ document.add("1234", {"id": "1234", "title": "Title 1",
+ "category": ["cat_a", "cat_b", "cat_c"]})
self.assertRaises(CommitMismatchError, document.commit)
diff --git a/tests/unit/cloudsearch2/test_search.py b/tests/unit/cloudsearch2/test_search.py
index 63ac2f4f..e40dc396 100644
--- a/tests/unit/cloudsearch2/test_search.py
+++ b/tests/unit/cloudsearch2/test_search.py
@@ -19,31 +19,52 @@ class CloudSearchSearchBaseTest(unittest.TestCase):
hits = [
{
'id': '12341',
- 'title': 'Document 1',
+ 'fields': {
+ 'title': 'Document 1',
+ 'rank': 1
+ }
},
{
'id': '12342',
- 'title': 'Document 2',
+ 'fields': {
+ 'title': 'Document 2',
+ 'rank': 2
+ }
},
{
'id': '12343',
- 'title': 'Document 3',
+ 'fields': {
+ 'title': 'Document 3',
+ 'rank': 3
+ }
},
{
'id': '12344',
- 'title': 'Document 4',
+ 'fields': {
+ 'title': 'Document 4',
+ 'rank': 4
+ }
},
{
'id': '12345',
- 'title': 'Document 5',
+ 'fields': {
+ 'title': 'Document 5',
+ 'rank': 5
+ }
},
{
'id': '12346',
- 'title': 'Document 6',
+ 'fields': {
+ 'title': 'Document 6',
+ 'rank': 6
+ }
},
{
'id': '12347',
- 'title': 'Document 7',
+ 'fields': {
+ 'title': 'Document 7',
+ 'rank': 7
+ }
},
]
@@ -80,7 +101,7 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
'start': 0,
'hit':CloudSearchSearchBaseTest.hits
},
- 'info': {
+ 'status': {
'rid':'b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08',
'time-ms': 2,
'cpu-time-ms': 0
@@ -99,14 +120,6 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
self.assertEqual(args['start'], ["0"])
self.assertEqual(args['size'], ["10"])
- def test_cloudsearch_bqsearch(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(bq="'Test'")
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['bq'], ["'Test'"])
def test_cloudsearch_search_details(self):
search = SearchConnection(endpoint=HOSTNAME)
@@ -119,34 +132,16 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
self.assertEqual(args['size'], ["50"])
self.assertEqual(args['start'], ["20"])
- def test_cloudsearch_facet_single(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', facet=["Author"])
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['facet'], ["Author"])
-
- def test_cloudsearch_facet_multiple(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', facet=["author", "cat"])
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['facet'], ["author,cat"])
-
def test_cloudsearch_facet_constraint_single(self):
search = SearchConnection(endpoint=HOSTNAME)
search.search(
q='Test',
- facet_constraints={'author': "'John Smith','Mark Smith'"})
+ facet={'author': "'John Smith','Mark Smith'"})
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['facet-author-constraints'],
+ self.assertEqual(args['facet.author'],
["'John Smith','Mark Smith'"])
def test_cloudsearch_facet_constraint_multiple(self):
@@ -154,72 +149,37 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
search.search(
q='Test',
- facet_constraints={'author': "'John Smith','Mark Smith'",
- 'category': "'News','Reviews'"})
+ facet={'author': "'John Smith','Mark Smith'",
+ 'category': "'News','Reviews'"})
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['facet-author-constraints'],
+ self.assertEqual(args['facet.author'],
["'John Smith','Mark Smith'"])
- self.assertEqual(args['facet-category-constraints'],
+ self.assertEqual(args['facet.category'],
["'News','Reviews'"])
def test_cloudsearch_facet_sort_single(self):
search = SearchConnection(endpoint=HOSTNAME)
- search.search(q='Test', facet_sort={'author': 'alpha'})
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['facet-author-sort'], ['alpha'])
-
- def test_cloudsearch_facet_sort_multiple(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', facet_sort={'author': 'alpha',
- 'cat': 'count'})
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['facet-author-sort'], ['alpha'])
- self.assertEqual(args['facet-cat-sort'], ['count'])
-
- def test_cloudsearch_top_n_single(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', facet_top_n={'author': 5})
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['facet-author-top-n'], ['5'])
-
- def test_cloudsearch_top_n_multiple(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', facet_top_n={'author': 5, 'cat': 10})
+ search.search(q='Test', facet={'author': {'sort':'alpha'}})
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['facet-author-top-n'], ['5'])
- self.assertEqual(args['facet-cat-top-n'], ['10'])
-
- def test_cloudsearch_rank_single(self):
- search = SearchConnection(endpoint=HOSTNAME)
+ print args
- search.search(q='Test', rank=["date"])
+ self.assertEqual(args['facet.author'], ['{"sort": "alpha"}'])
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['rank'], ['date'])
-
- def test_cloudsearch_rank_multiple(self):
+ def test_cloudsearch_facet_sort_multiple(self):
search = SearchConnection(endpoint=HOSTNAME)
- search.search(q='Test', rank=["date", "score"])
+ search.search(q='Test', facet={'author': {'sort': 'alpha'},
+ 'cat': {'sort': 'count'}})
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['rank'], ['date,score'])
+ self.assertEqual(args['facet.author'], ['{"sort": "alpha"}'])
+ self.assertEqual(args['facet.cat'], ['{"sort": "count"}'])
def test_cloudsearch_result_fields_single(self):
search = SearchConnection(endpoint=HOSTNAME)
@@ -228,7 +188,7 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['return-fields'], ['author'])
+ self.assertEqual(args['return'], ['author'])
def test_cloudsearch_result_fields_multiple(self):
search = SearchConnection(endpoint=HOSTNAME)
@@ -237,28 +197,7 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
args = self.get_args(HTTPretty.last_request.raw_requestline)
- self.assertEqual(args['return-fields'], ['author,title'])
-
-
- def test_cloudsearch_t_field_single(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', t={'year':'2001..2007'})
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['t-year'], ['2001..2007'])
-
- def test_cloudsearch_t_field_multiple(self):
- search = SearchConnection(endpoint=HOSTNAME)
-
- search.search(q='Test', t={'year':'2001..2007', 'score':'10..50'})
-
- args = self.get_args(HTTPretty.last_request.raw_requestline)
-
- self.assertEqual(args['t-year'], ['2001..2007'])
- self.assertEqual(args['t-score'], ['10..50'])
-
+ self.assertEqual(args['return'], ['author,title'])
def test_cloudsearch_results_meta(self):
"""Check returned metadata is parsed correctly"""
@@ -267,8 +206,8 @@ class CloudSearchSearchTest(CloudSearchSearchBaseTest):
results = search.search(q='Test')
# These rely on the default response which is fed into HTTPretty
- self.assertEqual(results.rank, "-text_relevance")
- self.assertEqual(results.match_expression, "Test")
+ self.assertEqual(results.hits, 30)
+ self.assertEqual(results.docs[0]['fields']['rank'], 1)
def test_cloudsearch_results_info(self):
"""Check num_pages_needed is calculated correctly"""
@@ -345,14 +284,14 @@ class CloudSearchSearchFacetTest(CloudSearchSearchBaseTest):
'start': 0,
'hit':CloudSearchSearchBaseTest.hits
},
- 'info': {
+ 'status': {
'rid':'b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08',
'time-ms': 2,
'cpu-time-ms': 0
},
'facets': {
'tags': {},
- 'animals': {'constraints': [{'count': '2', 'value': 'fish'}, {'count': '1', 'value':'lions'}]},
+ 'animals': {'buckets': [{'count': '2', 'value': 'fish'}, {'count': '1', 'value':'lions'}]},
}
}
@@ -361,7 +300,7 @@ class CloudSearchSearchFacetTest(CloudSearchSearchBaseTest):
search = SearchConnection(endpoint=HOSTNAME)
- results = search.search(q='Test', facet=['tags'])
+ results = search.search(q='Test', facet={'tags': {}})
self.assertTrue('tags' not in results.facets)
self.assertEqual(results.facets['animals'], {u'lions': u'1', u'fish': u'2'})