Search code examples
pythonapirestpython-3.11

Python, "TypeError: string indices must be integers, not 'str'" while not using any indices


there! Currently trying to code my first program to automate an API, but got stuck at the moment where I transfer 2 arguments from earlier functions to the 3-rd function.

BTW, feel free to leave any suggestions for the whole code, apart for the error.

Here I'm authenticating and extract the cookie token:

import requests
import json

from workfiles import general_http_methods

base_url = 'https://restful-booker.herokuapp.com'

"""Authentication"""

def booker_auth_method():
    auth_resource = '/auth'
    auth_url = base_url + auth_resource
    print(auth_url)
    auth_body = {'username': 'admin',
                 'password': 'password123'}
    result_auth_token = general_http_methods.general_post_method(auth_url, auth_body)
    json_result_auth_token = result_auth_token.json()
    value_of_the_cookie_json_result_auth_token = str(json_result_auth_token.get('token'))
    adding_token_to_value = 'token=' + value_of_the_cookie_json_result_auth_token
    result_auth_cookie_token = {'Cookie': adding_token_to_value}
    print(result_auth_cookie_token)
    return result_auth_cookie_token


booker_auth_method_var = booker_auth_method()['Cookie']

Then I create a booking:

"""Creating a booking"""


def booker_create_booking_method():
    create_booking_resource = '/booking'
    create_booking_body = {
        "firstname": 'Python',
        "lastname": "Tester",
        "totalprice": 111,
        "depositpaid": True,
        "bookingdates": {
            "checkin": "2023-01-01",
            "checkout": "2023-01-02"},
        "additionalneeds": "Breakfast"}
    create_booking_url = base_url + create_booking_resource
    print(create_booking_url)
    create_booking_result = general_http_methods.general_post_method(create_booking_url, create_booking_body)
    json_create_booking_result = create_booking_result.json()
    booking_id = json_create_booking_result.get('bookingid')
    print(json_create_booking_result)
    print(booking_id)
    return booking_id


booker_create_booking_method_var = booker_create_booking_method()

Finally, I wanna pass the return values from the 2 previous functions into the function below. To do that, I saved the return values in the variables (booker_auth_method_var, booker_create_booking_method_var) and pass them as arguments into my next function.

"Updating the WHOLE booking"


def booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var):
    update_booking_resource = '/booking/'
    update_booking_cookie_token = booker_auth_method_var  #
    update_booking_id = str(booker_create_booking_method_var)  #
    update_booking_url = base_url + update_booking_resource + update_booking_id
    update_booking_body = {
        "firstname": "Python",
        "lastname": "QA Engineer",
        "totalprice": 777,
        "depositpaid": False,
        "bookingdates": {
            "checkin": "2023-07-08",
            "checkout": "2023-07-15"},
        "additionalneeds": "ALL INCLUSIVE"}
    update_booking_result = general_http_methods.general_put_method(update_booking_url, update_booking_cookie_token, update_booking_body)
    print(update_booking_cookie_token)
    print(update_booking_url)
    print(update_booking_result.text)
    return update_booking_result


booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)

However, at the result I get the topic error, even though I don't even use any indices:

https://restful-booker.herokuapp.com/auth
{'Cookie': 'token=006b0313b7e7bb1'}
https://restful-booker.herokuapp.com/booking
{'bookingid': 8187, 'booking': {'firstname': 'Python', 'lastname': 'Tester', 'totalprice': 111, 'depositpaid': True, 'bookingdates': {'checkin': '2023-01-01', 'checkout': '2023-01-02'}, 'additionalneeds': 'Breakfast'}}
8187
Traceback (most recent call last):
  File "/Users/usr/PycharmProjects/booker_automation/workfiles/booker_http_methods.py", line 80, in <module>
    booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)
  File "/Users/usr/PycharmProjects/booker_automation/workfiles/booker_http_methods.py", line 72, in booker_update_booking_method
    update_booking_result = general_http_methods.general_put_method(update_booking_url, update_booking_cookie_token,
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/booker_automation/workfiles/general_http_methods.py", line 20, in general_put_method
    result = requests.put(url, headers=headers, cookies=cookies, json=body)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/api.py", line 130, in put
    return request("put", url, data=data, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/sessions.py", line 573, in request
    prep = self.prepare_request(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/sessions.py", line 471, in prepare_request
    cookies = cookiejar_from_dict(cookies)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/cookies.py", line 537, in cookiejar_from_dict
    cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
                                             ~~~~~~~~~~~^^^^^^
TypeError: string indices must be integers, not 'str'

Process finished with exit code 1

The key issue for me here is how to pass the booking id from func 2 into the resource path in the final function. I need to transform it from int to str to concatenate with base_url and update_booking_resource, but it causes the error.

I have already tried to workaround, but it causes other mistakes like

  • 'int' object is not subscriptable
  • dict object is not callable

so I believe I have to deal with exactly this mistake but do not understand how


Solution

  • So I finally found out the reason:

    In the first block I had to call not the key of the dict from the method, but the method itself as only it could be considered as cookie by the function below from my general_http_methods file:

    def general_put_method(url, cookies, body):
            result = requests.put(url, headers=headers, cookies=cookies, json=body)
            return result
    

    And using it as the parameter in the third method straightly, without passing into update_booking_cookie_token variable.

    So the final code looks like this:

    """HTTP-methods for booker API"""
    import requests
    import json
    
    from workfiles import general_http_methods
    
    base_url = 'https://restful-booker.herokuapp.com'
    
    """Authentication"""
    
    def booker_auth_method():
        auth_resource = '/auth'
        auth_url = base_url + auth_resource
        print(auth_url)
        auth_body = {'username': 'admin',
                     'password': 'password123'}
        result_auth_token = general_http_methods.general_post_method(auth_url, auth_body)
        json_result_auth_token = result_auth_token.json()
        value_of_the_cookie_json_result_auth_token = str(json_result_auth_token.get('token'))
        adding_token_to_auth_token_value = 'token=' + value_of_the_cookie_json_result_auth_token
        result_auth_cookie_token = {'Cookie': adding_token_to_auth_token_value}
        print(result_auth_cookie_token)
        return result_auth_cookie_token
    
    
    booker_auth_method_var = booker_auth_method()
    
    """Creating a booking"""
    
    def booker_create_booking_method():
        create_booking_resource = '/booking'
        create_booking_body = {
            "firstname": 'Python',
            "lastname": "Tester",
            "totalprice": 111,
            "depositpaid": True,
            "bookingdates": {
                "checkin": "2023-01-01",
                "checkout": "2023-01-02"},
            "additionalneeds": "Breakfast"}
        create_booking_url = base_url + create_booking_resource
        print(create_booking_url)
        create_booking_result = general_http_methods.general_post_method(create_booking_url, create_booking_body)
        str_json_create_booking_result = str(create_booking_result.json()['bookingid'])
        print(create_booking_result, str_json_create_booking_result)
        return str_json_create_booking_result
    
    booker_create_booking_method_var = booker_create_booking_method()
    
    "Updating the WHOLE booking"
    
    def booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var):
        update_booking_resource = '/booking/'
        update_booking_url = base_url + update_booking_resource + booker_create_booking_method_var
        update_booking_body = {
            "firstname": "Python",
            "lastname": "QA Engineer",
            "totalprice": 777,
            "depositpaid": False,
            "bookingdates": {
                "checkin": "2023-07-08",
                "checkout": "2023-07-15"},
            "additionalneeds": "ALL INCLUSIVE"}
        update_booking_result = general_http_methods.general_put_method(update_booking_url, booker_auth_method_var, update_booking_body)
        print(update_booking_url, update_booking_result, update_booking_result.text)
        return update_booking_result
    
    
    booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)
    

    And here is code from the general_http_methods file:

    """General HTTP-methods"""
    
    import requests
    
    headers = {
        'Content-Type':'application/json',
        'Accept':'application/json'}
    
    def general_get_meothod(url):
        result = requests.get(url)
        return result
    
    
    def general_post_method(url, body):
        result = requests.post(url, headers=headers, json=body)
        return result
    
    
    def general_put_method(url, cookies, body):
        result = requests.put(url, headers=headers, cookies=cookies, json=body)
        return result
    
    
    def general_patch_method(url, cookies, body):
        result = requests.patch(url, headers=headers, cookies=cookies, json=body)
        return result
    
    
    def general_delete_method(url, cookies, body):
        result = requests.patch(url, headers=headers, cookies=cookies, json=body)
        return result
    

    How it will help somehow in case you gonna have similar issue.