capless/kev

AttributeError: 'int' object has no attribute 'lower'

Miserlou opened this issue · 7 comments

Continuing from the previous ticket..

Using the same documentation example..

In [10]: kevin = models.TestDocument(name='Kevin Ismyfriend',is_active=True,no_subscriptions=3,state='NC',gpa=3.25)

In [11]: kevin
Out[11]: <TestDocument: Kevin Ismyfriend:None >

In [12]: kevin.save()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-e3970196d46e> in <module>()
----> 1 kevin.save()

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/document.pyc in save(self)
    114 
    115     def save(self):
--> 116         self._db.save(self)
    117 
    118 

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/s3/db.pyc in save(self, doc_obj)
     43             doc_obj.__class__,doc_obj._id)).put(
     44                 Body=json.dumps(doc))
---> 45         self.add_indexes(doc_obj, doc)
     46         self.remove_indexes(doc_obj)
     47         return doc_obj

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/s3/db.pyc in add_indexes(self, doc_obj, doc)
     94             # if index_value:
     95             self._db.Object(self.bucket,'{0}/{1}'.format(
---> 96                 doc_obj.get_index_name(prop, index_value),
     97                 doc_obj._id)).put(Body='')
     98 

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/document.pyc in get_index_name(cls, prop, index_value)
     90     def get_index_name(cls, prop, index_value):
     91         if cls.get_db().backend_id != 'dynamodb':
---> 92             index_value = index_value.lower()
     93         return '{0}:{1}:indexes:{2}:{3}'.format(
     94             cls.get_db().backend_id.lower(),

AttributeError: 'int' object has no attribute 'lower'

This one I'm not as sure about though!

This is for a pure S3 backend.

Changing to Dynamo causes:

In [3]: kevin.save()
---------------------------------------------------------------------------
ClientError                               Traceback (most recent call last)
<ipython-input-3-e3970196d46e> in <module>()
----> 1 kevin.save()

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/document.pyc in save(self)
    114 
    115     def save(self):
--> 116         self._db.save(self)
    117 
    118 

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/dynamodb/db.pyc in save(self, doc_obj)
     24     # CRUD Operations
     25     def save(self, doc_obj):
---> 26         doc_obj, doc = self._save(doc_obj)
     27         # DynamoDB requires Decimal type instead of Float
     28         for key, value in list(doc.items()):

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/__init__.pyc in _save(self, doc_obj)
     57             raw_value = prop.get_python_value(doc.get(key))
     58             if prop.unique:
---> 59                 self.check_unique(doc_obj, key, raw_value)
     60             value = prop.get_db_value(raw_value)
     61             doc[key] = value

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/__init__.pyc in check_unique(self, doc_obj, key, value)
     42     def check_unique(self, doc_obj, key, value):
     43         obj = doc_obj.objects().filter({key: value})
---> 44         if len(obj) == 0:
     45             return True
     46         if hasattr(doc_obj, '_id') and len(obj) == 1:

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/query.pyc in __len__(self)
     59 
     60     def __len__(self):
---> 61         self._fetch_all()
     62         return len(self._result_cache)
     63 

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/query.pyc in _fetch_all(self)
     74     def _fetch_all(self):
     75         if self._result_cache is None:
---> 76             self._result_cache = list(self.evaluate())
     77 
     78     def count(self):

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/dynamodb/db.pyc in evaluate(self, filters_list, doc_class)
     82 
     83     def evaluate(self, filters_list, doc_class):
---> 84          docs_list = self.get_doc_list(filters_list)
     85          for doc in docs_list:
     86              yield doc_class(**doc)

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/kev/backends/dynamodb/db.pyc in get_doc_list(self, filters_list)
     59     def get_doc_list(self, filters_list):
     60         query_params = self.parse_filters(filters_list)
---> 61         response = self._indexer.query(**query_params)
     62         return response['Items']
     63 

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/boto3/resources/factory.pyc in do_action(self, *args, **kwargs)
    518             # instance via ``self``.
    519             def do_action(self, *args, **kwargs):
--> 520                 response = action(self, *args, **kwargs)
    521 
    522                 if hasattr(self, 'load'):

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/boto3/resources/action.pyc in __call__(self, parent, *args, **kwargs)
     81                     operation_name, params)
     82 
---> 83         response = getattr(parent.meta.client, operation_name)(**params)
     84 
     85         logger.debug('Response: %r', response)

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/botocore/client.pyc in _api_call(self, *args, **kwargs)
    251                     "%s() only accepts keyword arguments." % py_operation_name)
    252             # The "self" in this scope is referring to the BaseClient.
--> 253             return self._make_api_call(operation_name, kwargs)
    254 
    255         _api_call.__name__ = str(py_operation_name)

/Users/rjones/Projects/RedString/env/lib/python2.7/site-packages/botocore/client.pyc in _make_api_call(self, operation_name, api_params)
    541             error_code = parsed_response.get("Error", {}).get("Code")
    542             error_class = self.exceptions.from_code(error_code)
--> 543             raise error_class(parsed_response, operation_name)
    544         else:
    545             return parsed_response

ClientError: An error occurred (ValidationException) when calling the Query operation: The table does not have the specified index: name-index

@Miserlou Can you share the Document (model) that you are using?

Also can you share your handler? Please omit any secrets and change the table or bucket name.

Oops didn't read where you said you used the model from the docs.

This should be fixed in 0.8.1

The reason the DynamoDB didn't work is probably because the index names on the DynamoDB table either weren't there or they didn't end with "-index".