Package thingiverse

Expand source code
__version__ = "0.0.7.dev"

from thingiverse.types.exceptions import (
    ResourceNotFound, SearchException,
    ThingiverseException, UnathenticatedException, UserException)
from thingiverse.types.search import SearchResponse
from thingiverse.types.users import ThingiverseUser
from typing import Dict, List, Optional, Text, Union
from box import Box
import requests
import logging


logging.basicConfig(format='%(asctime)s |%(levelname)s|%(message)s')


class Thingiverse(object):
    def __init__(self, access_token=None):
        """A user-created :class:`Thingiverse <Thingiverse>` object.

        Parameters
        ----------
        access_token : str
            Thingiverse access_token after OAuth2

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_term("Raspberry Pi", term_library=False, autocomplete=True)
        <SearchResult   >
        """
        if not access_token:
            exception = UnathenticatedException("'access_token' not provided")
            logging.exception(exception)
            raise exception
        self.base_url = "https://api.thingiverse.com"
        self.oauth_url = "https://www.thingiverse.com/login/oauth/authorize"
        self.access_token = access_token
        logging.info("Thingiverse initialized.")

    # TODO
    # def authorize(self,
    #               client_id: Text,
    #               redirect_uri: Optional[Text] = None,
    #               response_type: Optional[Text] = None):
    #     """Authorizes the client given a clientId

    #     :param client_id: The Thingiverse App Client ID
    #     :param redirect_url: The Thingiverse App redirect URL
    #     :param response_type: The OAuth response type. Defaults to 'code' by Thingiverse API

    #     Usage:
    #     >>> from thingiverse import Thingiverse
    #     >>> thingy = Thingiverse(access_token="abc")
    #     >>> thingy.authorize(client_id="abc",
    #                          redirect_uri="https://example.com",
    #                          response_type="token")
    #     """
    #     url = self.oauth_url + f"?client_id={client_id}"
    #     if redirect_uri:
    #         url += f"&redirect_url={redirect_uri}"
    #     if response_type:
    #         url += f"&response_type={response_type}"

    #     print(url)

    #     res = requests.get(url, allow_redirects=True)
    #     print("URL")
    #     print(res.url)
    #     if res.url != url:
    #         new_res = requests.get(res.url, allow_redirects=True)
    #         print("New res")
    #         print(new_res.url)

    #     return res

    def handle_response_error(self, response: requests.Response, message: Text):
        """Simply checks for invalid response and raises errors if any"""
        if response.status_code == 404:
            exception = ResourceNotFound(message)
            logging.exception(exception)
            raise exception
        elif response.status_code != 200:
            exception = ThingiverseException(f"Unknown error: {response.json()}")
            logging.error(f"Error requesting url:\n\t{response.url}")
            logging.exception(exception)
            raise exception

    def get_user_by_username(self, username: Text = "me") -> ThingiverseUser:
        """Get user personal information by `username`

        Parameters
        ----------
        username : str, default="me"
            Username to fetch for.

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> user = thingy.get_user_by_username(username="me")
        """
        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get user by username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"User with username {username} not found.")

        res_json = res.json()
        user_box = Box(res_json)
        logging.info(f"Successfully retrieved user with username {username}")

        return user_box

    def get_users_data(self, username: Text = None, term: Text = None):
        """Get user things data by `username`

        Parameters
        -----------
        username: str
            Username to fetch for
        term: str
            The search query to perform

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> user = thingy.get_users_data(username="m4t0n", term="RPi")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/search"
        if term:
            path += f"/{term}"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get username data: {username}; term: {term}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        thing_box = Box(res_json)
        logging.info(f"Successfully retrieved user data with username {username}")

        return thing_box

    def get_username_things(self, username: Text = None):
        """Gets a list of things by `username`

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_things_by_username(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/things"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get things for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # thing_box = Box(res_json)
        logging.info(f"Successfully retrieved things for username {username}")

        return res_json

    def get_username_collected_things(self, username: Text = None):
        """Gets a list of collected things by `username`

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_collected_things(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/all-collected-things"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get collected things for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        things_box = Box(res_json)

        logging.info(f"Successfully retrieved collected things for username {username}")

        return things_box

    def get_username_unread_message_count(self, username: Text = None):
        """Gets unread message count

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_unread_message_count()
        """

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/unread-message-count"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get message count for username {username}")
        res = requests.get(url)

        error_msg = f"Something went wrong while fetching message count for username {username}."
        self.handle_response_error(res, error_msg)

        res_json = res.json()
        # message_count_box = Box(res_json)
        logging.info(f"Successfully retrieved message count for username {username}")
        print("Unread messages")
        print(res_json)
        return res_json

    def get_username_favorites(self, username: Text = None):
        """Gets a list of favorites by `username`

        Parameters
        ----------
        username: str
            username to search favorites for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_favorites(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/favorites"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get favorites for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # favorites_box = Box(res_json)
        logging.info(f"Successfully retrieved favorites for username {username}")

        return res_json

    def get_username_likes(self, username: Text = None):
        """Gets a list of likes by `username`

        Parameters
        ----------
        username: str
            username to search likes for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_likes(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/likes"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get likes for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # likes_box = Box(res_json)
        logging.info(f"Successfully retrieved likes for username {username}")

        return res_json

    def get_username_copies(self, username: Text = None):
        """Gets a list of copies by `username`

        Parameters
        ----------
        username: str
            username to search copies for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_copies(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/copies"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get copies for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # copies_box = Box(res_json)
        logging.info(f"Successfully retrieved copies for username {username}")

        return res_json

    def get_username_collections(self, username: Text = None, paginate: bool = True):
        """Gets a list of copies by `username`

        Parameters
        ----------
        username: str
            username to search copies for

        paginate: bool, default=True
            return a paginated response, if `False`, a full list will be returned

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_collections(username="m4t0n", paginate=False)
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/collections"

        if paginate:
            path += "/all"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get collections for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # collections_box = Box(res_json)
        logging.info(f"Successfully retrieved collections for username {username}")

        return res_json

    def get_username_downloads(self, username: Text = None):
        """Gets a list of downloads by `username`

        Parameters
        ----------
        username: str
            username to search downloads for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_downloads(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/downloads"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get copies for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # downloads_box = Box(res_json)
        logging.info(f"Successfully retrieved copies for username {username}")

        return res_json

    def get_thing_by_id(self, thing_id: int = None):
        """Gets a thing by `thing_id`

        Parameters
        ----------
        thing_id: int
            id of the thing to get

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.thing_by_id(thing_id=123)
        """

        if not thing_id:
            exception = ThingiverseException("'thing_id' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/things/{thing_id}/"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get thing by id: {thing_id}")
        res = requests.get(url)

        self.handle_response_error(res, f"Thing with id {thing_id} not found.")

        res_json = res.json()
        thing_box = Box(res_json)
        logging.info(f"Successfully retrieved thing with id {thing_id}")

        return thing_box

    def get_images_by_thing(self,
                            thing_id: int = None,
                            image_id: Optional[int] = None,
                            image_type: Optional[Text] = None,
                            image_size: Optional[Text] = None) -> Union[Dict, List]:
        """Gets image(s) for a thing

        Parameters
        ----------
        thing_id: int
            Thing to fetch images for

        image_id: int, optional
            If not given, an array of images will be returned

        image_type: str, optional
            Image type to look for

        image_size: str, optional
            Image size to look for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> images = thingy.get_images_for_thing(thing_id=1234)
        >>> image = thingy.get_images_for_thing(thing_id=1234, image_id=4321)
        """
        if not thing_id:
            exception = ThingiverseException("'thing_id' is required")
            logging.exception(exception)
            raise exception

        if image_size and not image_type:
            # based on their API Docs `type` is required if umage_size is given
            # https://www.thingiverse.com/developers/rest-api-reference#things
            exception = ThingiverseException("'image_type' is required is 'image_size' is given")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/things/{thing_id}/images/"

        if image_id:
            path += str(image_id)

        path += access_token_param
        if image_size:
            path + f"&size={image_size}"

        if image_type:
            path += f"&type={image_type}"

        url = self.base_url + path
        logging.info(f"Making request to get thing by id: {thing_id}")
        res = requests.get(url)

        self.handle_response_error(res, f"Thing with id {thing_id} not found.")

        res_json = res.json()
        # images_box = Box(res_json)
        logging.info(f"Successfully images for thing with id {thing_id}")

        return res_json

    # Search endpoints
    def search_term(self,
                    term: Text = None) -> SearchResponse:
        """Searches for a term on Thingiverse

        Parameters
        ----------
        term: str
            Term to search for

        term_library: bool
            Will be requesting libraries for term

        autocomplete: bool
            Will be requesting autocomplete endpoint

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_term(term="Raspberry Pi",
                               term_library=False,
                               autocomplete=True)
        """
        if not term:
            exception = SearchException("'term' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/search/{term}"

        url = self.base_url + path + access_token_param
        logging.info(f"Making search term request to {url}")
        res = requests.get(url)
        res_json = res.json()
        search_box = Box(res_json)
        logging.info(f"Successfully retrieved search results for term {term}")

        return search_box

    def search_tag(self, tag: Text = None) -> SearchResponse:
        """Searches for a tag on Thingiverse

        Parameters
        ----------

        tag: str
            Tag to search for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_tag(tag="Raspberry Pi")
        """
        if not tag:
            exception = SearchException("'tag' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/search/{tag}/tag"

        url = self.base_url + path + access_token_param
        logging.info(f"Making search tag request to {url}")
        res = requests.get(url)
        res_json = res.json()
        search_box = Box(res_json)
        logging.info(f"Successfully retrieved search results for term {tag}")

        return search_box

Sub-modules

thingiverse.types

Classes

class Thingiverse (access_token=None)

A user-created :class:Thingiverse <Thingiverse> object.

Parameters

access_token : str
Thingiverse access_token after OAuth2

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thingy.search_term("Raspberry Pi", term_library=False, autocomplete=True)
<SearchResult   >
Expand source code
class Thingiverse(object):
    def __init__(self, access_token=None):
        """A user-created :class:`Thingiverse <Thingiverse>` object.

        Parameters
        ----------
        access_token : str
            Thingiverse access_token after OAuth2

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_term("Raspberry Pi", term_library=False, autocomplete=True)
        <SearchResult   >
        """
        if not access_token:
            exception = UnathenticatedException("'access_token' not provided")
            logging.exception(exception)
            raise exception
        self.base_url = "https://api.thingiverse.com"
        self.oauth_url = "https://www.thingiverse.com/login/oauth/authorize"
        self.access_token = access_token
        logging.info("Thingiverse initialized.")

    # TODO
    # def authorize(self,
    #               client_id: Text,
    #               redirect_uri: Optional[Text] = None,
    #               response_type: Optional[Text] = None):
    #     """Authorizes the client given a clientId

    #     :param client_id: The Thingiverse App Client ID
    #     :param redirect_url: The Thingiverse App redirect URL
    #     :param response_type: The OAuth response type. Defaults to 'code' by Thingiverse API

    #     Usage:
    #     >>> from thingiverse import Thingiverse
    #     >>> thingy = Thingiverse(access_token="abc")
    #     >>> thingy.authorize(client_id="abc",
    #                          redirect_uri="https://example.com",
    #                          response_type="token")
    #     """
    #     url = self.oauth_url + f"?client_id={client_id}"
    #     if redirect_uri:
    #         url += f"&redirect_url={redirect_uri}"
    #     if response_type:
    #         url += f"&response_type={response_type}"

    #     print(url)

    #     res = requests.get(url, allow_redirects=True)
    #     print("URL")
    #     print(res.url)
    #     if res.url != url:
    #         new_res = requests.get(res.url, allow_redirects=True)
    #         print("New res")
    #         print(new_res.url)

    #     return res

    def handle_response_error(self, response: requests.Response, message: Text):
        """Simply checks for invalid response and raises errors if any"""
        if response.status_code == 404:
            exception = ResourceNotFound(message)
            logging.exception(exception)
            raise exception
        elif response.status_code != 200:
            exception = ThingiverseException(f"Unknown error: {response.json()}")
            logging.error(f"Error requesting url:\n\t{response.url}")
            logging.exception(exception)
            raise exception

    def get_user_by_username(self, username: Text = "me") -> ThingiverseUser:
        """Get user personal information by `username`

        Parameters
        ----------
        username : str, default="me"
            Username to fetch for.

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> user = thingy.get_user_by_username(username="me")
        """
        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get user by username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"User with username {username} not found.")

        res_json = res.json()
        user_box = Box(res_json)
        logging.info(f"Successfully retrieved user with username {username}")

        return user_box

    def get_users_data(self, username: Text = None, term: Text = None):
        """Get user things data by `username`

        Parameters
        -----------
        username: str
            Username to fetch for
        term: str
            The search query to perform

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> user = thingy.get_users_data(username="m4t0n", term="RPi")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/search"
        if term:
            path += f"/{term}"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get username data: {username}; term: {term}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        thing_box = Box(res_json)
        logging.info(f"Successfully retrieved user data with username {username}")

        return thing_box

    def get_username_things(self, username: Text = None):
        """Gets a list of things by `username`

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_things_by_username(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/things"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get things for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # thing_box = Box(res_json)
        logging.info(f"Successfully retrieved things for username {username}")

        return res_json

    def get_username_collected_things(self, username: Text = None):
        """Gets a list of collected things by `username`

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_collected_things(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/all-collected-things"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get collected things for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        things_box = Box(res_json)

        logging.info(f"Successfully retrieved collected things for username {username}")

        return things_box

    def get_username_unread_message_count(self, username: Text = None):
        """Gets unread message count

        Parameters
        ----------
        username: str
            username to search things for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_unread_message_count()
        """

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/unread-message-count"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get message count for username {username}")
        res = requests.get(url)

        error_msg = f"Something went wrong while fetching message count for username {username}."
        self.handle_response_error(res, error_msg)

        res_json = res.json()
        # message_count_box = Box(res_json)
        logging.info(f"Successfully retrieved message count for username {username}")
        print("Unread messages")
        print(res_json)
        return res_json

    def get_username_favorites(self, username: Text = None):
        """Gets a list of favorites by `username`

        Parameters
        ----------
        username: str
            username to search favorites for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_favorites(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/favorites"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get favorites for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # favorites_box = Box(res_json)
        logging.info(f"Successfully retrieved favorites for username {username}")

        return res_json

    def get_username_likes(self, username: Text = None):
        """Gets a list of likes by `username`

        Parameters
        ----------
        username: str
            username to search likes for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_likes(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/likes"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get likes for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # likes_box = Box(res_json)
        logging.info(f"Successfully retrieved likes for username {username}")

        return res_json

    def get_username_copies(self, username: Text = None):
        """Gets a list of copies by `username`

        Parameters
        ----------
        username: str
            username to search copies for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_copies(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/copies"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get copies for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # copies_box = Box(res_json)
        logging.info(f"Successfully retrieved copies for username {username}")

        return res_json

    def get_username_collections(self, username: Text = None, paginate: bool = True):
        """Gets a list of copies by `username`

        Parameters
        ----------
        username: str
            username to search copies for

        paginate: bool, default=True
            return a paginated response, if `False`, a full list will be returned

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_collections(username="m4t0n", paginate=False)
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/collections"

        if paginate:
            path += "/all"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get collections for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # collections_box = Box(res_json)
        logging.info(f"Successfully retrieved collections for username {username}")

        return res_json

    def get_username_downloads(self, username: Text = None):
        """Gets a list of downloads by `username`

        Parameters
        ----------
        username: str
            username to search downloads for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.get_username_downloads(username="m4t0n")
        """
        if not username:
            exception = UserException("'username' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/users/{username}/downloads"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get copies for username: {username}")
        res = requests.get(url)

        self.handle_response_error(res, f"Username with username {username} not found.")

        res_json = res.json()
        # downloads_box = Box(res_json)
        logging.info(f"Successfully retrieved copies for username {username}")

        return res_json

    def get_thing_by_id(self, thing_id: int = None):
        """Gets a thing by `thing_id`

        Parameters
        ----------
        thing_id: int
            id of the thing to get

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thing = thingy.thing_by_id(thing_id=123)
        """

        if not thing_id:
            exception = ThingiverseException("'thing_id' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/things/{thing_id}/"

        url = self.base_url + path + access_token_param
        logging.info(f"Making request to get thing by id: {thing_id}")
        res = requests.get(url)

        self.handle_response_error(res, f"Thing with id {thing_id} not found.")

        res_json = res.json()
        thing_box = Box(res_json)
        logging.info(f"Successfully retrieved thing with id {thing_id}")

        return thing_box

    def get_images_by_thing(self,
                            thing_id: int = None,
                            image_id: Optional[int] = None,
                            image_type: Optional[Text] = None,
                            image_size: Optional[Text] = None) -> Union[Dict, List]:
        """Gets image(s) for a thing

        Parameters
        ----------
        thing_id: int
            Thing to fetch images for

        image_id: int, optional
            If not given, an array of images will be returned

        image_type: str, optional
            Image type to look for

        image_size: str, optional
            Image size to look for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> images = thingy.get_images_for_thing(thing_id=1234)
        >>> image = thingy.get_images_for_thing(thing_id=1234, image_id=4321)
        """
        if not thing_id:
            exception = ThingiverseException("'thing_id' is required")
            logging.exception(exception)
            raise exception

        if image_size and not image_type:
            # based on their API Docs `type` is required if umage_size is given
            # https://www.thingiverse.com/developers/rest-api-reference#things
            exception = ThingiverseException("'image_type' is required is 'image_size' is given")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/things/{thing_id}/images/"

        if image_id:
            path += str(image_id)

        path += access_token_param
        if image_size:
            path + f"&size={image_size}"

        if image_type:
            path += f"&type={image_type}"

        url = self.base_url + path
        logging.info(f"Making request to get thing by id: {thing_id}")
        res = requests.get(url)

        self.handle_response_error(res, f"Thing with id {thing_id} not found.")

        res_json = res.json()
        # images_box = Box(res_json)
        logging.info(f"Successfully images for thing with id {thing_id}")

        return res_json

    # Search endpoints
    def search_term(self,
                    term: Text = None) -> SearchResponse:
        """Searches for a term on Thingiverse

        Parameters
        ----------
        term: str
            Term to search for

        term_library: bool
            Will be requesting libraries for term

        autocomplete: bool
            Will be requesting autocomplete endpoint

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_term(term="Raspberry Pi",
                               term_library=False,
                               autocomplete=True)
        """
        if not term:
            exception = SearchException("'term' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/search/{term}"

        url = self.base_url + path + access_token_param
        logging.info(f"Making search term request to {url}")
        res = requests.get(url)
        res_json = res.json()
        search_box = Box(res_json)
        logging.info(f"Successfully retrieved search results for term {term}")

        return search_box

    def search_tag(self, tag: Text = None) -> SearchResponse:
        """Searches for a tag on Thingiverse

        Parameters
        ----------

        tag: str
            Tag to search for

        Usage:
        >>> from thingiverse import Thingiverse
        >>> thingy = Thingiverse(access_token="abc")
        >>> thingy.search_tag(tag="Raspberry Pi")
        """
        if not tag:
            exception = SearchException("'tag' is required")
            logging.exception(exception)
            raise exception

        access_token_param = f"?access_token={self.access_token}"
        path = f"/search/{tag}/tag"

        url = self.base_url + path + access_token_param
        logging.info(f"Making search tag request to {url}")
        res = requests.get(url)
        res_json = res.json()
        search_box = Box(res_json)
        logging.info(f"Successfully retrieved search results for term {tag}")

        return search_box

Methods

def get_images_by_thing(self, thing_id: int = None, image_id: Optional[int] = None, image_type: Optional[str] = None, image_size: Optional[str] = None) ‑> Union[Dict, List]

Gets image(s) for a thing

Parameters

thing_id : int
Thing to fetch images for
image_id : int, optional
If not given, an array of images will be returned
image_type : str, optional
Image type to look for
image_size : str, optional
Image size to look for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> images = thingy.get_images_for_thing(thing_id=1234)
>>> image = thingy.get_images_for_thing(thing_id=1234, image_id=4321)
Expand source code
def get_images_by_thing(self,
                        thing_id: int = None,
                        image_id: Optional[int] = None,
                        image_type: Optional[Text] = None,
                        image_size: Optional[Text] = None) -> Union[Dict, List]:
    """Gets image(s) for a thing

    Parameters
    ----------
    thing_id: int
        Thing to fetch images for

    image_id: int, optional
        If not given, an array of images will be returned

    image_type: str, optional
        Image type to look for

    image_size: str, optional
        Image size to look for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> images = thingy.get_images_for_thing(thing_id=1234)
    >>> image = thingy.get_images_for_thing(thing_id=1234, image_id=4321)
    """
    if not thing_id:
        exception = ThingiverseException("'thing_id' is required")
        logging.exception(exception)
        raise exception

    if image_size and not image_type:
        # based on their API Docs `type` is required if umage_size is given
        # https://www.thingiverse.com/developers/rest-api-reference#things
        exception = ThingiverseException("'image_type' is required is 'image_size' is given")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/things/{thing_id}/images/"

    if image_id:
        path += str(image_id)

    path += access_token_param
    if image_size:
        path + f"&size={image_size}"

    if image_type:
        path += f"&type={image_type}"

    url = self.base_url + path
    logging.info(f"Making request to get thing by id: {thing_id}")
    res = requests.get(url)

    self.handle_response_error(res, f"Thing with id {thing_id} not found.")

    res_json = res.json()
    # images_box = Box(res_json)
    logging.info(f"Successfully images for thing with id {thing_id}")

    return res_json
def get_thing_by_id(self, thing_id: int = None)

Gets a thing by thing_id

Parameters

thing_id : int
id of the thing to get

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.thing_by_id(thing_id=123)
Expand source code
def get_thing_by_id(self, thing_id: int = None):
    """Gets a thing by `thing_id`

    Parameters
    ----------
    thing_id: int
        id of the thing to get

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.thing_by_id(thing_id=123)
    """

    if not thing_id:
        exception = ThingiverseException("'thing_id' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/things/{thing_id}/"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get thing by id: {thing_id}")
    res = requests.get(url)

    self.handle_response_error(res, f"Thing with id {thing_id} not found.")

    res_json = res.json()
    thing_box = Box(res_json)
    logging.info(f"Successfully retrieved thing with id {thing_id}")

    return thing_box
def get_user_by_username(self, username: str = 'me') ‑> ThingiverseUser

Get user personal information by username

Parameters

username : str, default="me"
Username to fetch for.

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> user = thingy.get_user_by_username(username="me")
Expand source code
def get_user_by_username(self, username: Text = "me") -> ThingiverseUser:
    """Get user personal information by `username`

    Parameters
    ----------
    username : str, default="me"
        Username to fetch for.

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> user = thingy.get_user_by_username(username="me")
    """
    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get user by username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"User with username {username} not found.")

    res_json = res.json()
    user_box = Box(res_json)
    logging.info(f"Successfully retrieved user with username {username}")

    return user_box
def get_username_collected_things(self, username: str = None)

Gets a list of collected things by username

Parameters

username : str
username to search things for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_collected_things(username="m4t0n")
Expand source code
def get_username_collected_things(self, username: Text = None):
    """Gets a list of collected things by `username`

    Parameters
    ----------
    username: str
        username to search things for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_collected_things(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/all-collected-things"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get collected things for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    things_box = Box(res_json)

    logging.info(f"Successfully retrieved collected things for username {username}")

    return things_box
def get_username_collections(self, username: str = None, paginate: bool = True)

Gets a list of copies by username

Parameters

username : str
username to search copies for
paginate : bool, default=True
return a paginated response, if False, a full list will be returned

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_collections(username="m4t0n", paginate=False)
Expand source code
def get_username_collections(self, username: Text = None, paginate: bool = True):
    """Gets a list of copies by `username`

    Parameters
    ----------
    username: str
        username to search copies for

    paginate: bool, default=True
        return a paginated response, if `False`, a full list will be returned

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_collections(username="m4t0n", paginate=False)
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/collections"

    if paginate:
        path += "/all"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get collections for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # collections_box = Box(res_json)
    logging.info(f"Successfully retrieved collections for username {username}")

    return res_json
def get_username_copies(self, username: str = None)

Gets a list of copies by username

Parameters

username : str
username to search copies for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_copies(username="m4t0n")
Expand source code
def get_username_copies(self, username: Text = None):
    """Gets a list of copies by `username`

    Parameters
    ----------
    username: str
        username to search copies for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_copies(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/copies"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get copies for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # copies_box = Box(res_json)
    logging.info(f"Successfully retrieved copies for username {username}")

    return res_json
def get_username_downloads(self, username: str = None)

Gets a list of downloads by username

Parameters

username : str
username to search downloads for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_downloads(username="m4t0n")
Expand source code
def get_username_downloads(self, username: Text = None):
    """Gets a list of downloads by `username`

    Parameters
    ----------
    username: str
        username to search downloads for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_downloads(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/downloads"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get copies for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # downloads_box = Box(res_json)
    logging.info(f"Successfully retrieved copies for username {username}")

    return res_json
def get_username_favorites(self, username: str = None)

Gets a list of favorites by username

Parameters

username : str
username to search favorites for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_favorites(username="m4t0n")
Expand source code
def get_username_favorites(self, username: Text = None):
    """Gets a list of favorites by `username`

    Parameters
    ----------
    username: str
        username to search favorites for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_favorites(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/favorites"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get favorites for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # favorites_box = Box(res_json)
    logging.info(f"Successfully retrieved favorites for username {username}")

    return res_json
def get_username_likes(self, username: str = None)

Gets a list of likes by username

Parameters

username : str
username to search likes for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_likes(username="m4t0n")
Expand source code
def get_username_likes(self, username: Text = None):
    """Gets a list of likes by `username`

    Parameters
    ----------
    username: str
        username to search likes for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_likes(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/likes"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get likes for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # likes_box = Box(res_json)
    logging.info(f"Successfully retrieved likes for username {username}")

    return res_json
def get_username_things(self, username: str = None)

Gets a list of things by username

Parameters

username : str
username to search things for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_things_by_username(username="m4t0n")
Expand source code
def get_username_things(self, username: Text = None):
    """Gets a list of things by `username`

    Parameters
    ----------
    username: str
        username to search things for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_things_by_username(username="m4t0n")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/things"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get things for username: {username}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    # thing_box = Box(res_json)
    logging.info(f"Successfully retrieved things for username {username}")

    return res_json
def get_username_unread_message_count(self, username: str = None)

Gets unread message count

Parameters

username : str
username to search things for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thing = thingy.get_username_unread_message_count()
Expand source code
def get_username_unread_message_count(self, username: Text = None):
    """Gets unread message count

    Parameters
    ----------
    username: str
        username to search things for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thing = thingy.get_username_unread_message_count()
    """

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/unread-message-count"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get message count for username {username}")
    res = requests.get(url)

    error_msg = f"Something went wrong while fetching message count for username {username}."
    self.handle_response_error(res, error_msg)

    res_json = res.json()
    # message_count_box = Box(res_json)
    logging.info(f"Successfully retrieved message count for username {username}")
    print("Unread messages")
    print(res_json)
    return res_json
def get_users_data(self, username: str = None, term: str = None)

Get user things data by username

Parameters

username : str
Username to fetch for
term : str
The search query to perform

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> user = thingy.get_users_data(username="m4t0n", term="RPi")
Expand source code
def get_users_data(self, username: Text = None, term: Text = None):
    """Get user things data by `username`

    Parameters
    -----------
    username: str
        Username to fetch for
    term: str
        The search query to perform

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> user = thingy.get_users_data(username="m4t0n", term="RPi")
    """
    if not username:
        exception = UserException("'username' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/users/{username}/search"
    if term:
        path += f"/{term}"

    url = self.base_url + path + access_token_param
    logging.info(f"Making request to get username data: {username}; term: {term}")
    res = requests.get(url)

    self.handle_response_error(res, f"Username with username {username} not found.")

    res_json = res.json()
    thing_box = Box(res_json)
    logging.info(f"Successfully retrieved user data with username {username}")

    return thing_box
def handle_response_error(self, response: requests.models.Response, message: str)

Simply checks for invalid response and raises errors if any

Expand source code
def handle_response_error(self, response: requests.Response, message: Text):
    """Simply checks for invalid response and raises errors if any"""
    if response.status_code == 404:
        exception = ResourceNotFound(message)
        logging.exception(exception)
        raise exception
    elif response.status_code != 200:
        exception = ThingiverseException(f"Unknown error: {response.json()}")
        logging.error(f"Error requesting url:\n\t{response.url}")
        logging.exception(exception)
        raise exception
def search_tag(self, tag: str = None) ‑> SearchResponse

Searches for a tag on Thingiverse

Parameters

tag : str
Tag to search for

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thingy.search_tag(tag="Raspberry Pi")
Expand source code
def search_tag(self, tag: Text = None) -> SearchResponse:
    """Searches for a tag on Thingiverse

    Parameters
    ----------

    tag: str
        Tag to search for

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thingy.search_tag(tag="Raspberry Pi")
    """
    if not tag:
        exception = SearchException("'tag' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/search/{tag}/tag"

    url = self.base_url + path + access_token_param
    logging.info(f"Making search tag request to {url}")
    res = requests.get(url)
    res_json = res.json()
    search_box = Box(res_json)
    logging.info(f"Successfully retrieved search results for term {tag}")

    return search_box
def search_term(self, term: str = None) ‑> SearchResponse

Searches for a term on Thingiverse

Parameters

term : str
Term to search for
term_library : bool
Will be requesting libraries for term
autocomplete : bool
Will be requesting autocomplete endpoint

Usage:

>>> from thingiverse import Thingiverse
>>> thingy = Thingiverse(access_token="abc")
>>> thingy.search_term(term="Raspberry Pi",
                       term_library=False,
                       autocomplete=True)
Expand source code
def search_term(self,
                term: Text = None) -> SearchResponse:
    """Searches for a term on Thingiverse

    Parameters
    ----------
    term: str
        Term to search for

    term_library: bool
        Will be requesting libraries for term

    autocomplete: bool
        Will be requesting autocomplete endpoint

    Usage:
    >>> from thingiverse import Thingiverse
    >>> thingy = Thingiverse(access_token="abc")
    >>> thingy.search_term(term="Raspberry Pi",
                           term_library=False,
                           autocomplete=True)
    """
    if not term:
        exception = SearchException("'term' is required")
        logging.exception(exception)
        raise exception

    access_token_param = f"?access_token={self.access_token}"
    path = f"/search/{term}"

    url = self.base_url + path + access_token_param
    logging.info(f"Making search term request to {url}")
    res = requests.get(url)
    res_json = res.json()
    search_box = Box(res_json)
    logging.info(f"Successfully retrieved search results for term {term}")

    return search_box