IBM / cloudant-python-sdk

Cloudant SDK for Python
Apache License 2.0
46 stars 20 forks source link

Trying to create a new Design Document with options parameter included in a database Returns: "AttributeError: 'dict' object has no attribute 'to_dict'" #119

Closed aanagnostou closed 3 years ago

aanagnostou commented 3 years ago

Describe the bug

Can not create a Design Document in a database with function: put_design_document if you include the options parameter, despite if the value is True or False

To Reproduce

Code snippet slightly different from: Api Docs

from ibmcloudant.cloudant_v1 import (
    DesignDocument,
    CloudantV1,
    DesignDocumentViewsMapReduce,
    SearchIndexDefinition,
)

try:
    from dotenv import load_dotenv, find_dotenv

    load_dotenv(find_dotenv())
except ModuleNotFoundError as e:
    print("ERROR")

service = CloudantV1.new_instance(service_name="ADMIN")

product_map = DesignDocumentViewsMapReduce(
    map="function(doc) { emit(doc.productid, [doc.brand, doc.name, doc.description]) }"
)

price_index = SearchIndexDefinition(
    index='function (doc) {  index("price", doc.price);}'
)

partitioned_design_doc = DesignDocument(
    views={"byApplianceProdId": product_map},
    indexes={"findByPrice": price_index},
    options={"partitioned": True},
)

response = service.put_design_document(
    db='products',
    design_document=partitioned_design_doc,
    ddoc="appliances",
).get_result()

print(response)

Expected behavior

Should return: {'ok': True, 'id': '_design/appliances', 'rev': '1-**************************************'}

Traceback

Traceback (most recent call last): File "/home/**/bug1.py", line 31, in <module> response = service.put_design_document( File "/home/**/venv/lib/python3.8/site-packages/ibmcloudant/cloudant_v1.py", line 2628, in put_design_document design_document = convert_model(design_document) File "/home/**/venv/lib/python3.8/site-packages/ibm_cloud_sdk_core/utils.py", line 215, in convert_model return val.to_dict() File "/home/**/venv/lib/python3.8/site-packages/ibmcloudant/cloudant_v1.py", line 10779, in to_dict _dict['options'] = self.options.to_dict() AttributeError: 'dict' object has no attribute 'to_dict'

Additional context

Knowing that this design_document = convert_model(design_document) returns a Dict..

I was able to avoid this problem by changing this line:

https://github.com/IBM/cloudant-python-sdk/blob/cc169b21832b3db8c2f898edf7dd12c4c91a15ab/ibmcloudant/cloudant_v1.py#L10779

with: _dict["options"] = self.options

emlaver commented 3 years ago

Hello @aanagnostou, you'll either need to use all model classes or use all dictionaries. The options model class for this endpoint is DesignDocumentOptions:

...
design_document_options = DesignDocumentOptions(
    partitioned=True
)
partitioned_design_doc = DesignDocument(
    views={"byApplianceProdId": product_map},
    indexes={"findByPrice": price_index},
    options=design_document_options,
)
...

Here's an example if you want to do all dictionaries:

...
product_map = {'map':"function(doc) { emit(doc.productid, [doc.brand, doc.name, doc.description]) }"}
price_index = {'index': 'function (doc) {  index("price", doc.price);}'}
partitioned_design_doc = {
    'views': {"byApplianceProdId": product_map},
    'indexes': {"findByPrice": price_index},
    'options': {"partitioned": True},
)
...

Screenshot of options for PUT /{db}/_design/{ddoc} in API Docs:

Screen Shot 2021-06-30 at 10 27 18 AM
aanagnostou commented 3 years ago

Hi @emlaver ,

Thanks for clarifying that.

As you can imagine it's working as it should.

Thank you for your time