From a821496a57d7cf9e328c05978e3a90bae85603c3 Mon Sep 17 00:00:00 2001 From: Serj Zavadsky Date: Tue, 12 Apr 2022 12:44:50 +0200 Subject: [PATCH] chore: docs updated --- README.md | 36 ++++- docs/api/base.html | 50 ++++--- docs/api/common.html | 47 ++++--- docs/api/my_profile.html | 94 ++++++------- docs/api/user_panel.html | 205 +++++++++++++++++++++++----- docs/exceptions.html | 38 +++++- docs/index.html | 24 +--- docs/main.html | 62 ++++++++- docs/types.html | 67 ++++++++- push_to_3yourmind/__init__.py | 11 -- push_to_3yourmind/api/base.py | 19 +-- push_to_3yourmind/api/common.py | 10 +- push_to_3yourmind/api/my_profile.py | 18 +-- push_to_3yourmind/api/user_panel.py | 47 +++++-- push_to_3yourmind/exceptions.py | 8 +- push_to_3yourmind/main.py | 17 +++ push_to_3yourmind/types.py | 27 +++- 17 files changed, 568 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index 0080a19..c90bfdc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # push-to-3yourmind + A Python SDK library to work with 3YOURMIND's platform API. It enables you to manage user profile information, push 3D Files, manipulate baskets, lines, get pricing information, place Orders and Catalog Items. @@ -19,13 +20,19 @@ Open `/admin/auth/user/`, and click "Create token" in the user list. ## Usage +### First, initialize API class + ```python from push_to_3yourmind import PushTo3YourmindAPI client = PushTo3YourmindAPI( access_token="QWERTY123456789", base_url="http://", ) +``` +### Get or set current user's info + +```python profile_info = client.my_profile.get_profile() my_preferences = client.my_profile.get_preferences() client.my_profile.set_preferences(currency="USD", language="de") @@ -33,17 +40,44 @@ client.my_profile.set_preferences(currency="USD", language="de") client.my_profile.set_preferences(language="en") # or client.my_profile.set_preferences(unit="inch") +``` + +### Explore User Panel's API +```python # get current user's basket list baskets = client.user_panel.get_baskets() # or basket = client.user_panel.get_basket(basket_id=6) +``` +### Do more with a single API call + +```python +client.user_panel.create_line_with_cad_file_and_product( + basket_id=4, + cad_file="/path/to/the/cad_file.stl", + product_id=3, + quantity=1, +) ``` # Usage Guide -[link](https://3yourmind.github.io/push-to-3yourmind/) +[Creating a basket, placing an order](https://3yourmind.github.io/push-to-3yourmind/api/user_panel.html) + +[User profile management](https://3yourmind.github.io/push-to-3yourmind/api/my_profile.html) + +[Common API](https://3yourmind.github.io/push-to-3yourmind/api/common.html) + +[there is more](https://3yourmind.github.io/push-to-3yourmind/) + + +# Documentation generation + + poetry install + poetry shell + make documentation # @ diff --git a/docs/api/base.html b/docs/api/base.html index 535863a..13c5a1d 100644 --- a/docs/api/base.html +++ b/docs/api/base.html @@ -41,14 +41,15 @@

Module push_to_3yourmind.api.base

class BaseAPI: """ - Base class for all namespaced API methods. + Base class for all namespaced API methods. Not to be instantiated directly. """ def __init__(self, access_token: str, base_url: str): """ - - :param access_token: - :param base_url: + Args: + access_token: to create a token, open `/admin/auth/user/`, and click + "Create token" in the user list. + base_url: application URL, ex. https://app.3yourmind.com """ self._api_prefix = "api/v2.0" self._access_token = access_token @@ -109,12 +110,14 @@

Module push_to_3yourmind.api.base

else: response_payload = "" - if response.status_code == 404: - raise exceptions.ObjectNotFound(response_payload) + if response.status_code == 400: + raise exceptions.BadRequest(response_payload) elif response.status_code == 401: raise exceptions.Unauthorized(response_payload) - elif response.status_code == 400: - raise exceptions.BadRequest(response_payload) + elif response.status_code == 403: + raise exceptions.AccessDenied(response_payload) + elif response.status_code == 404: + raise exceptions.ObjectNotFound(response_payload) elif response.status_code == 405: raise exceptions.MethodNotAllowed(response_payload) return response_payload @@ -142,23 +145,30 @@

Classes

(access_token: str, base_url: str)
-

Base class for all namespaced API methods.

-

:param access_token: -:param base_url:

+

Base class for all namespaced API methods. Not to be instantiated directly.

+

Args

+
+
access_token
+
to create a token, open /admin/auth/user/, and click +"Create token" in the user list.
+
base_url
+
application URL, ex. https://app.3yourmind.com
+
Expand source code
class BaseAPI:
     """
-    Base class for all namespaced API methods.
+    Base class for all namespaced API methods. Not to be instantiated directly.
     """
 
     def __init__(self, access_token: str, base_url: str):
         """
-
-        :param access_token:
-        :param base_url:
+        Args:
+            access_token: to create a token, open `/admin/auth/user/`, and click
+                "Create token" in the user list.
+            base_url: application URL, ex. https://app.3yourmind.com
         """
         self._api_prefix = "api/v2.0"
         self._access_token = access_token
@@ -219,12 +229,14 @@ 

Classes

else: response_payload = "" - if response.status_code == 404: - raise exceptions.ObjectNotFound(response_payload) + if response.status_code == 400: + raise exceptions.BadRequest(response_payload) elif response.status_code == 401: raise exceptions.Unauthorized(response_payload) - elif response.status_code == 400: - raise exceptions.BadRequest(response_payload) + elif response.status_code == 403: + raise exceptions.AccessDenied(response_payload) + elif response.status_code == 404: + raise exceptions.ObjectNotFound(response_payload) elif response.status_code == 405: raise exceptions.MethodNotAllowed(response_payload) return response_payload diff --git a/docs/api/common.html b/docs/api/common.html index 66acc76..35846c3 100644 --- a/docs/api/common.html +++ b/docs/api/common.html @@ -36,6 +36,13 @@

Module push_to_3yourmind.api.common

class CommonAPI(BaseAPI): + """ + API methods common to all panels. + + Accessible via namespace `common`, for example: + >>> response = client.common.get_colors() + """ + def get_colors(self) -> t.List[types.ResponseDict]: return self._request("GET", "colors/") @@ -43,21 +50,18 @@

Module push_to_3yourmind.api.common

""" Get list of units of measure available on the platform. Currently, "mm" and "inch". - :return: """ return self._request("GET", "units/") def get_countries(self) -> t.List[types.ResponseDict]: """ Get list of countries with codes and full names - :return: """ return self._request("GET", "countries/") def get_currencies(self) -> t.List[str]: """ Get list of currencies available on the platform - :return: """ return self._request("GET", "currencies/") @@ -82,14 +86,30 @@

Classes

(access_token: str, base_url: str)
-

Base class for all namespaced API methods.

-

:param access_token: -:param base_url:

+

API methods common to all panels.

+

Accessible via namespace common, for example:

+
>>> response = client.common.get_colors()
+
+

Args

+
+
access_token
+
to create a token, open /admin/auth/user/, and click +"Create token" in the user list.
+
base_url
+
application URL, ex. https://app.3yourmind.com
+
Expand source code
class CommonAPI(BaseAPI):
+    """
+    API methods common to all panels.
+
+    Accessible via namespace `common`, for example:
+    >>> response = client.common.get_colors()
+    """
+
     def get_colors(self) -> t.List[types.ResponseDict]:
         return self._request("GET", "colors/")
 
@@ -97,21 +117,18 @@ 

Classes

""" Get list of units of measure available on the platform. Currently, "mm" and "inch". - :return: """ return self._request("GET", "units/") def get_countries(self) -> t.List[types.ResponseDict]: """ Get list of countries with codes and full names - :return: """ return self._request("GET", "countries/") def get_currencies(self) -> t.List[str]: """ Get list of currencies available on the platform - :return: """ return self._request("GET", "currencies/") @@ -145,8 +162,7 @@

Methods

Get list of units of measure available on the platform. -Currently, "mm" and "inch". -:return:

+Currently, "mm" and "inch".

Expand source code @@ -155,7 +171,6 @@

Methods

""" Get list of units of measure available on the platform. Currently, "mm" and "inch". - :return: """ return self._request("GET", "units/")
@@ -164,8 +179,7 @@

Methods

def get_countries(self) ‑> List[Dict[str, Any]]
-

Get list of countries with codes and full names -:return:

+

Get list of countries with codes and full names

Expand source code @@ -173,7 +187,6 @@

Methods

def get_countries(self) -> t.List[types.ResponseDict]:
     """
     Get list of countries with codes and full names
-    :return:
     """
     return self._request("GET", "countries/")
@@ -182,8 +195,7 @@

Methods

def get_currencies(self) ‑> List[str]
-

Get list of currencies available on the platform -:return:

+

Get list of currencies available on the platform

Expand source code @@ -191,7 +203,6 @@

Methods

def get_currencies(self) -> t.List[str]:
     """
     Get list of currencies available on the platform
-    :return:
     """
     return self._request("GET", "currencies/")
diff --git a/docs/api/my_profile.html b/docs/api/my_profile.html index e4056a8..11d2259 100644 --- a/docs/api/my_profile.html +++ b/docs/api/my_profile.html @@ -39,8 +39,6 @@

Module push_to_3yourmind.api.my_profile

def get_preferences(self) -> types.ResponseDict: """ Get preferences of the current user: country, currency, language, unit - - :return: """ return self._request("GET", "my-profile/preferences/") @@ -57,11 +55,11 @@

Module push_to_3yourmind.api.my_profile

Update profile of the current user. All arguments are optional, only passed values will be saved to the profile. - :param country: 2-letter country code, ex. US, FR, GB - :param currency: 3-letter currency code, ex. USD, EUR - :param language: 2-letter language code, ex. en, de, fr, es - :param unit: mm or inch - :return: + Args: + country: 2-letter country code, ex. US, FR, GB + currency: 3-letter currency code, ex. USD, EUR + language: 2-letter language code, ex. en, de, fr, es + unit: mm or inch """ json = self._get_parameters( @@ -72,8 +70,6 @@

Module push_to_3yourmind.api.my_profile

def get_profile(self) -> types.ResponseDict: """ Get profile of the current user: name, default address, access roles etc. - - :return: """ return self._request("GET", "my-profile/profile/") @@ -81,8 +77,6 @@

Module push_to_3yourmind.api.my_profile

def get_addresses(self) -> t.List[types.ResponseDict]: """ Get a list of current user's addresses - - :return: """ return self._request("GET", "my-profile/addresses/") @@ -90,8 +84,6 @@

Module push_to_3yourmind.api.my_profile

def get_address(self, *, address_id: int) -> types.ResponseDict: """ Get specific address of the current user - - :return: """ return self._request("GET", f"my-profile/addresses/{address_id}/")
@@ -111,9 +103,15 @@

Classes

(access_token: str, base_url: str)
-

Base class for all namespaced API methods.

-

:param access_token: -:param base_url:

+

Base class for all namespaced API methods. Not to be instantiated directly.

+

Args

+
+
access_token
+
to create a token, open /admin/auth/user/, and click +"Create token" in the user list.
+
base_url
+
application URL, ex. https://app.3yourmind.com
+
Expand source code @@ -122,8 +120,6 @@

Classes

def get_preferences(self) -> types.ResponseDict: """ Get preferences of the current user: country, currency, language, unit - - :return: """ return self._request("GET", "my-profile/preferences/") @@ -140,11 +136,11 @@

Classes

Update profile of the current user. All arguments are optional, only passed values will be saved to the profile. - :param country: 2-letter country code, ex. US, FR, GB - :param currency: 3-letter currency code, ex. USD, EUR - :param language: 2-letter language code, ex. en, de, fr, es - :param unit: mm or inch - :return: + Args: + country: 2-letter country code, ex. US, FR, GB + currency: 3-letter currency code, ex. USD, EUR + language: 2-letter language code, ex. en, de, fr, es + unit: mm or inch """ json = self._get_parameters( @@ -155,8 +151,6 @@

Classes

def get_profile(self) -> types.ResponseDict: """ Get profile of the current user: name, default address, access roles etc. - - :return: """ return self._request("GET", "my-profile/profile/") @@ -164,8 +158,6 @@

Classes

def get_addresses(self) -> t.List[types.ResponseDict]: """ Get a list of current user's addresses - - :return: """ return self._request("GET", "my-profile/addresses/") @@ -173,8 +165,6 @@

Classes

def get_address(self, *, address_id: int) -> types.ResponseDict: """ Get specific address of the current user - - :return: """ return self._request("GET", f"my-profile/addresses/{address_id}/") @@ -189,8 +179,7 @@

Methods

def get_preferences(self) ‑> Dict[str, Any]
-

Get preferences of the current user: country, currency, language, unit

-

:return:

+

Get preferences of the current user: country, currency, language, unit

Expand source code @@ -198,8 +187,6 @@

Methods

def get_preferences(self) -> types.ResponseDict:
     """
     Get preferences of the current user: country, currency, language, unit
-
-    :return:
     """
 
     return self._request("GET", "my-profile/preferences/")
@@ -211,11 +198,17 @@

Methods

Update profile of the current user. All arguments are optional, only passed values will be saved to the profile.

-

:param country: 2-letter country code, ex. US, FR, GB -:param currency: 3-letter currency code, ex. USD, EUR -:param language: 2-letter language code, ex. en, de, fr, es -:param unit: mm or inch -:return:

+

Args

+
+
country
+
2-letter country code, ex. US, FR, GB
+
currency
+
3-letter currency code, ex. USD, EUR
+
language
+
2-letter language code, ex. en, de, fr, es
+
unit
+
mm or inch
+
Expand source code @@ -232,11 +225,11 @@

Methods

Update profile of the current user. All arguments are optional, only passed values will be saved to the profile. - :param country: 2-letter country code, ex. US, FR, GB - :param currency: 3-letter currency code, ex. USD, EUR - :param language: 2-letter language code, ex. en, de, fr, es - :param unit: mm or inch - :return: + Args: + country: 2-letter country code, ex. US, FR, GB + currency: 3-letter currency code, ex. USD, EUR + language: 2-letter language code, ex. en, de, fr, es + unit: mm or inch """ json = self._get_parameters( @@ -249,8 +242,7 @@

Methods

def get_profile(self) ‑> Dict[str, Any]
-

Get profile of the current user: name, default address, access roles etc.

-

:return:

+

Get profile of the current user: name, default address, access roles etc.

Expand source code @@ -258,8 +250,6 @@

Methods

def get_profile(self) -> types.ResponseDict:
     """
     Get profile of the current user: name, default address, access roles etc.
-
-    :return:
     """
 
     return self._request("GET", "my-profile/profile/")
@@ -269,8 +259,7 @@

Methods

def get_addresses(self) ‑> List[Dict[str, Any]]
-

Get a list of current user's addresses

-

:return:

+

Get a list of current user's addresses

Expand source code @@ -278,8 +267,6 @@

Methods

def get_addresses(self) -> t.List[types.ResponseDict]:
     """
     Get a list of current user's addresses
-
-    :return:
     """
 
     return self._request("GET", "my-profile/addresses/")
@@ -289,8 +276,7 @@

Methods

def get_address(self, *, address_id: int) ‑> Dict[str, Any]
-

Get specific address of the current user

-

:return:

+

Get specific address of the current user

Expand source code @@ -298,8 +284,6 @@

Methods

def get_address(self, *, address_id: int) -> types.ResponseDict:
     """
     Get specific address of the current user
-
-    :return:
     """
 
     return self._request("GET", f"my-profile/addresses/{address_id}/")
diff --git a/docs/api/user_panel.html b/docs/api/user_panel.html index 8587e1c..310e077 100644 --- a/docs/api/user_panel.html +++ b/docs/api/user_panel.html @@ -47,6 +47,13 @@

Module push_to_3yourmind.api.user_panel

""" Groups API functionality from the User Panel, such as creating/updating baskets, placing orders, making requests for quotes, ordering quotes etc. + + Accessible via namespace `user_panel`, for example: + >>> response = client.user_panel.get_baskets() + + Attributes: + CHECK_FILE_STATUS_MAX_ATTEMPTS: How many times to check for the uploaded CAD file analysis status + CHECK_FILE_STATUS_DELAY: Delay between status check requests, in seconds """ CHECK_FILE_STATUS_MAX_ATTEMPTS = 60 @@ -61,20 +68,30 @@

Module push_to_3yourmind.api.user_panel

""" Get all baskets of the current user. Returns paginated list. - :param page: int, optional - :param page_size: int, optional - :return: dictionary with the following keys: - count: total number of baskets - currentPage: - totalPages: - pageSize: baskets per page - results: list of basket details + Args: + page: int, optional + page_size: int, optional + Returns: + dictionary with the following keys: + + - count: total number of baskets, int + - currentPage: page number, int + - totalPages: total number of pages, int + - pageSize: baskets per page, int + - results: list of basket details """ query = self._get_parameters(page=page, pageSize=page_size) return self._request("GET", "user-panel/baskets/", params=query) def get_basket(self, *, basket_id: int) -> types.ResponseDict: + """ + Args: + basket_id: int + + Returns: + Basket details dict + """ return self._request("GET", f"user-panel/baskets/{basket_id}/") def get_basket_price( @@ -87,6 +104,20 @@

Module push_to_3yourmind.api.user_panel

shipping_method_id: types.OptionalNumber = types.NoValue, voucher_code: types.OptionalString = types.NoValue, ) -> types.ResponseDict: + """ + Calculate basket's price, given additional optional shipping, billing information + + Args: + basket_id: int + currency: str + shipping_address_id: int, optional + billing_address_id: int, optional + shipping_method_id: int, optional + voucher_code: str, optional + + Returns: + Dict containing basket prices + """ query = self._get_parameters( currency=currency, shippingAddressId=shipping_address_id, @@ -420,8 +451,24 @@

Classes

Groups API functionality from the User Panel, such as creating/updating baskets, placing orders, making requests for quotes, ordering quotes etc.

-

:param access_token: -:param base_url:

+

Accessible via namespace user_panel, for example:

+
>>> response = client.user_panel.get_baskets()
+
+

Attributes

+
+
CHECK_FILE_STATUS_MAX_ATTEMPTS
+
How many times to check for the uploaded CAD file analysis status
+
CHECK_FILE_STATUS_DELAY
+
Delay between status check requests, in seconds
+
+

Args

+
+
access_token
+
to create a token, open /admin/auth/user/, and click +"Create token" in the user list.
+
base_url
+
application URL, ex. https://app.3yourmind.com
+
Expand source code @@ -430,6 +477,13 @@

Classes

""" Groups API functionality from the User Panel, such as creating/updating baskets, placing orders, making requests for quotes, ordering quotes etc. + + Accessible via namespace `user_panel`, for example: + >>> response = client.user_panel.get_baskets() + + Attributes: + CHECK_FILE_STATUS_MAX_ATTEMPTS: How many times to check for the uploaded CAD file analysis status + CHECK_FILE_STATUS_DELAY: Delay between status check requests, in seconds """ CHECK_FILE_STATUS_MAX_ATTEMPTS = 60 @@ -444,20 +498,30 @@

Classes

""" Get all baskets of the current user. Returns paginated list. - :param page: int, optional - :param page_size: int, optional - :return: dictionary with the following keys: - count: total number of baskets - currentPage: - totalPages: - pageSize: baskets per page - results: list of basket details + Args: + page: int, optional + page_size: int, optional + Returns: + dictionary with the following keys: + + - count: total number of baskets, int + - currentPage: page number, int + - totalPages: total number of pages, int + - pageSize: baskets per page, int + - results: list of basket details """ query = self._get_parameters(page=page, pageSize=page_size) return self._request("GET", "user-panel/baskets/", params=query) def get_basket(self, *, basket_id: int) -> types.ResponseDict: + """ + Args: + basket_id: int + + Returns: + Basket details dict + """ return self._request("GET", f"user-panel/baskets/{basket_id}/") def get_basket_price( @@ -470,6 +534,20 @@

Classes

shipping_method_id: types.OptionalNumber = types.NoValue, voucher_code: types.OptionalString = types.NoValue, ) -> types.ResponseDict: + """ + Calculate basket's price, given additional optional shipping, billing information + + Args: + basket_id: int + currency: str + shipping_address_id: int, optional + billing_address_id: int, optional + shipping_method_id: int, optional + voucher_code: str, optional + + Returns: + Dict containing basket prices + """ query = self._get_parameters( currency=currency, shippingAddressId=shipping_address_id, @@ -808,14 +886,22 @@

Methods

Get all baskets of the current user. Returns paginated list.

-

:param page: int, optional -:param page_size: int, optional -:return: dictionary with the following keys: -count: total number of baskets -currentPage: -totalPages: -pageSize: baskets per page -results: list of basket details

+

Args

+
+
page
+
int, optional
+
page_size
+
int, optional
+
+

Returns

+

dictionary with the following keys:

+
    +
  • count: total number of baskets, int
  • +
  • currentPage: page number, int
  • +
  • totalPages: total number of pages, int
  • +
  • pageSize: baskets per page, int
  • +
  • results: list of basket details
  • +
Expand source code @@ -829,14 +915,17 @@

Methods

""" Get all baskets of the current user. Returns paginated list. - :param page: int, optional - :param page_size: int, optional - :return: dictionary with the following keys: - count: total number of baskets - currentPage: - totalPages: - pageSize: baskets per page - results: list of basket details + Args: + page: int, optional + page_size: int, optional + Returns: + dictionary with the following keys: + + - count: total number of baskets, int + - currentPage: page number, int + - totalPages: total number of pages, int + - pageSize: baskets per page, int + - results: list of basket details """ query = self._get_parameters(page=page, pageSize=page_size) @@ -847,12 +936,25 @@

Methods

def get_basket(self, *, basket_id: int) ‑> Dict[str, Any]
-
+

Args

+
+
basket_id
+
int
+
+

Returns

+

Basket details dict

Expand source code
def get_basket(self, *, basket_id: int) -> types.ResponseDict:
+    """
+    Args:
+        basket_id: int
+
+    Returns:
+        Basket details dict
+    """
     return self._request("GET", f"user-panel/baskets/{basket_id}/")
@@ -860,7 +962,24 @@

Methods

def get_basket_price(self, *, basket_id: int, currency: str, shipping_address_id: Union[int, float, decimal.Decimal, Type[NoValue]] = push_to_3yourmind.types.NoValue, billing_address_id: Union[int, float, decimal.Decimal, Type[NoValue]] = push_to_3yourmind.types.NoValue, shipping_method_id: Union[int, float, decimal.Decimal, Type[NoValue]] = push_to_3yourmind.types.NoValue, voucher_code: Union[str, bytes, Type[NoValue]] = push_to_3yourmind.types.NoValue) ‑> Dict[str, Any]
-
+

Calculate basket's price, given additional optional shipping, billing information

+

Args

+
+
basket_id
+
int
+
currency
+
str
+
shipping_address_id
+
int, optional
+
billing_address_id
+
int, optional
+
shipping_method_id
+
int, optional
+
voucher_code
+
str, optional
+
+

Returns

+

Dict containing basket prices

Expand source code @@ -875,6 +994,20 @@

Methods

shipping_method_id: types.OptionalNumber = types.NoValue, voucher_code: types.OptionalString = types.NoValue, ) -> types.ResponseDict: + """ + Calculate basket's price, given additional optional shipping, billing information + + Args: + basket_id: int + currency: str + shipping_address_id: int, optional + billing_address_id: int, optional + shipping_method_id: int, optional + voucher_code: str, optional + + Returns: + Dict containing basket prices + """ query = self._get_parameters( currency=currency, shippingAddressId=shipping_address_id, diff --git a/docs/exceptions.html b/docs/exceptions.html index d2cc337..1a92e12 100644 --- a/docs/exceptions.html +++ b/docs/exceptions.html @@ -33,15 +33,17 @@

Module push_to_3yourmind.exceptions

class ObjectNotFound(BasePushTo3YourmindAPIException): - """ - Is raised when an API endpoint response is 404 - Object Not Found - """ + pass class Unauthorized(BasePushTo3YourmindAPIException): pass +class AccessDenied(BasePushTo3YourmindAPIException): + pass + + class BadRequest(BasePushTo3YourmindAPIException): pass @@ -109,6 +111,7 @@

Ancestors

Subclasses

    +
  • AccessDenied
  • BadArgument
  • BadRequest
  • CADFileNotFoundError
  • @@ -127,15 +130,13 @@

    Subclasses

    (*args, **kwargs)
    -

    Is raised when an API endpoint response is 404 - Object Not Found

    +

    Base exception class for all exceptions raised by push_to_3yourmind

    Expand source code
    class ObjectNotFound(BasePushTo3YourmindAPIException):
    -    """
    -    Is raised when an API endpoint response is 404 - Object Not Found
    -    """
    + pass

    Ancestors

      @@ -164,6 +165,26 @@

      Ancestors

    • builtins.BaseException
    +
    +class AccessDenied +(*args, **kwargs) +
    +
    +

    Base exception class for all exceptions raised by push_to_3yourmind

    +
    + +Expand source code + +
    class AccessDenied(BasePushTo3YourmindAPIException):
    +    pass
    +
    +

    Ancestors

    + +
    class BadRequest (*args, **kwargs) @@ -370,6 +391,9 @@

    Unauthorized

  • +

    AccessDenied

    +
  • +
  • BadRequest

  • diff --git a/docs/index.html b/docs/index.html index fda2366..62c86f2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,8 +5,7 @@ push_to_3yourmind API documentation - + @@ -23,28 +22,11 @@

    Package push_to_3yourmind

    -

    Structurally client API is a class that is initialized with user's API token and the -base URL.

    -
    from push_to_3yourmind import PushTo3YourmindAPI
    -client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://<domain-name>")
    -
    -

    Functionality is divided into namespaces, for example my_profile, user_panel etc.

    Expand source code -
    """
    -Structurally client API is a class that is initialized with user's API token and the
    -base URL.
    -
    -```python
    -from push_to_3yourmind import PushTo3YourmindAPI
    -client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://<domain-name>")
    -```
    -
    -Functionality is divided into namespaces, for example `my_profile`, `user_panel` etc.
    -"""
    -from .main import PushTo3YourmindAPI
    +
    from .main import PushTo3YourmindAPI
    @@ -68,7 +50,7 @@

    Sub-modules

push_to_3yourmind.types
-
+

This module contains NoValue class and type aliases for type annotations

diff --git a/docs/main.html b/docs/main.html index d643d0c..0bb8e7c 100644 --- a/docs/main.html +++ b/docs/main.html @@ -36,6 +36,23 @@

Module push_to_3yourmind.main

class PushTo3YourmindAPI(BaseAPI): + """ + The main class and the entrypoint for API + + >>> from push_to_3yourmind import PushTo3YourmindAPI + >>> client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://<domain-name>") + + Functionality is divided into namespaces, for example `my_profile`, `user_panel` etc. Some + API endpoints require proper user permissions, in case when an API can't be reached, an exception + AccessDenied is raised. + + Attributes: + user_panel: order management-related API: create/update basket lines, + upload CAD files, pricing + common: common API: country, unit, material lists + my_profile: API to manage user's preferences, profile, address list etc + """ + def __init__(self, access_token: str, base_url: str): super().__init__(access_token, base_url) self.user_panel = UserPanelAPI(access_token, base_url) @@ -57,14 +74,53 @@

Classes

(access_token: str, base_url: str)
-

Base class for all namespaced API methods.

-

:param access_token: -:param base_url:

+

The main class and the entrypoint for API

+
>>> from push_to_3yourmind import PushTo3YourmindAPI
+>>> client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://<domain-name>")
+
+

Functionality is divided into namespaces, for example my_profile, user_panel etc. Some +API endpoints require proper user permissions, in case when an API can't be reached, an exception +AccessDenied is raised.

+

Attributes

+
+
user_panel
+
order management-related API: create/update basket lines, +upload CAD files, pricing
+
common
+
common API: country, unit, material lists
+
my_profile
+
API to manage user's preferences, profile, address list etc
+
+

Args

+
+
access_token
+
to create a token, open /admin/auth/user/, and click +"Create token" in the user list.
+
base_url
+
application URL, ex. https://app.3yourmind.com
+
Expand source code
class PushTo3YourmindAPI(BaseAPI):
+    """
+    The main class and the entrypoint for API
+
+    >>> from push_to_3yourmind import PushTo3YourmindAPI
+    >>> client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://<domain-name>")
+
+    Functionality is divided into namespaces, for example `my_profile`, `user_panel` etc. Some
+    API endpoints require proper user permissions, in case when an API can't be reached, an exception
+    AccessDenied is raised.
+
+    Attributes:
+        user_panel: order management-related API: create/update basket lines,
+            upload CAD files, pricing
+        common: common API: country, unit, material lists
+        my_profile: API to manage user's preferences, profile, address list etc
+    """
+
     def __init__(self, access_token: str, base_url: str):
         super().__init__(access_token, base_url)
         self.user_panel = UserPanelAPI(access_token, base_url)
diff --git a/docs/types.html b/docs/types.html
index 29eb125..86a1e16 100644
--- a/docs/types.html
+++ b/docs/types.html
@@ -5,7 +5,7 @@
 
 
 push_to_3yourmind.types API documentation
-
+
 
 
 
@@ -22,17 +22,43 @@
 

Module push_to_3yourmind.types

+

This module contains NoValue class and type aliases for type annotations

Expand source code -
import datetime
+
"""
+This module contains NoValue class and type aliases for type annotations
+"""
+
+import datetime
 import decimal
 import typing as t
 
 
+__all__ = ["NoValue"]
+
+
 class NoValue:
-    pass
+    """
+    Some class methods accept arguments that are optional. Skipping them means
+    "no data changed" and will lead to not sending them to the 3YD API. To skip such an
+    argument give it a `NoValue` value.
+
+    For example, `client.my_profile.set_preferences` can accept 4 arguments:
+    country, currency, language, unit. If you need to update user's unit but leave other
+    settings unchanged:
+
+    >>> client.my_profile.set_preferences(unit="inch", country=NoValue, currency=NoValue, language=NoValue)
+    # or shorter
+    >>> client.my_profile.set_preferences(unit="inch")
+
+    The following:
+
+    >>> client.my_profile.set_preferences(unit="inch", country=None, currency=None, language=None)
+
+    ... it will mean that you want to set user's country, currency and language setting to NULL.
+    """
 
 
 ResponseDict = t.Dict[str, t.Any]
@@ -61,13 +87,44 @@ 

Classes

class NoValue
-
+

Some class methods accept arguments that are optional. Skipping them means +"no data changed" and will lead to not sending them to the 3YD API. To skip such an +argument give it a NoValue value.

+

For example, client.my_profile.set_preferences can accept 4 arguments: +country, currency, language, unit. If you need to update user's unit but leave other +settings unchanged:

+
>>> client.my_profile.set_preferences(unit="inch", country=NoValue, currency=NoValue, language=NoValue)
+# or shorter
+>>> client.my_profile.set_preferences(unit="inch")
+
+

The following:

+
>>> client.my_profile.set_preferences(unit="inch", country=None, currency=None, language=None)
+
+

… it will mean that you want to set user's country, currency and language setting to NULL.

Expand source code
class NoValue:
-    pass
+ """ + Some class methods accept arguments that are optional. Skipping them means + "no data changed" and will lead to not sending them to the 3YD API. To skip such an + argument give it a `NoValue` value. + + For example, `client.my_profile.set_preferences` can accept 4 arguments: + country, currency, language, unit. If you need to update user's unit but leave other + settings unchanged: + + >>> client.my_profile.set_preferences(unit="inch", country=NoValue, currency=NoValue, language=NoValue) + # or shorter + >>> client.my_profile.set_preferences(unit="inch") + + The following: + + >>> client.my_profile.set_preferences(unit="inch", country=None, currency=None, language=None) + + ... it will mean that you want to set user's country, currency and language setting to NULL. + """
diff --git a/push_to_3yourmind/__init__.py b/push_to_3yourmind/__init__.py index fd5d9d9..bdc4712 100644 --- a/push_to_3yourmind/__init__.py +++ b/push_to_3yourmind/__init__.py @@ -1,12 +1 @@ -""" -Structurally client API is a class that is initialized with user's API token and the -base URL. - -```python -from push_to_3yourmind import PushTo3YourmindAPI -client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://") -``` - -Functionality is divided into namespaces, for example `my_profile`, `user_panel` etc. -""" from .main import PushTo3YourmindAPI diff --git a/push_to_3yourmind/api/base.py b/push_to_3yourmind/api/base.py index 080cbd5..974709d 100644 --- a/push_to_3yourmind/api/base.py +++ b/push_to_3yourmind/api/base.py @@ -13,14 +13,15 @@ class BaseAPI: """ - Base class for all namespaced API methods. + Base class for all namespaced API methods. Not to be instantiated directly. """ def __init__(self, access_token: str, base_url: str): """ - - :param access_token: - :param base_url: + Args: + access_token: to create a token, open `/admin/auth/user/`, and click + "Create token" in the user list. + base_url: application URL, ex. https://app.3yourmind.com """ self._api_prefix = "api/v2.0" self._access_token = access_token @@ -81,12 +82,14 @@ def _request( else: response_payload = "" - if response.status_code == 404: - raise exceptions.ObjectNotFound(response_payload) + if response.status_code == 400: + raise exceptions.BadRequest(response_payload) elif response.status_code == 401: raise exceptions.Unauthorized(response_payload) - elif response.status_code == 400: - raise exceptions.BadRequest(response_payload) + elif response.status_code == 403: + raise exceptions.AccessDenied(response_payload) + elif response.status_code == 404: + raise exceptions.ObjectNotFound(response_payload) elif response.status_code == 405: raise exceptions.MethodNotAllowed(response_payload) return response_payload diff --git a/push_to_3yourmind/api/common.py b/push_to_3yourmind/api/common.py index 677c80c..46c2f76 100644 --- a/push_to_3yourmind/api/common.py +++ b/push_to_3yourmind/api/common.py @@ -8,6 +8,13 @@ class CommonAPI(BaseAPI): + """ + API methods common to all panels. + + Accessible via namespace `common`, for example: + >>> response = client.common.get_colors() + """ + def get_colors(self) -> t.List[types.ResponseDict]: return self._request("GET", "colors/") @@ -15,21 +22,18 @@ def get_units(self) -> t.List[types.ResponseDict]: """ Get list of units of measure available on the platform. Currently, "mm" and "inch". - :return: """ return self._request("GET", "units/") def get_countries(self) -> t.List[types.ResponseDict]: """ Get list of countries with codes and full names - :return: """ return self._request("GET", "countries/") def get_currencies(self) -> t.List[str]: """ Get list of currencies available on the platform - :return: """ return self._request("GET", "currencies/") diff --git a/push_to_3yourmind/api/my_profile.py b/push_to_3yourmind/api/my_profile.py index cce2c11..bcaad7e 100644 --- a/push_to_3yourmind/api/my_profile.py +++ b/push_to_3yourmind/api/my_profile.py @@ -11,8 +11,6 @@ class MyProfileAPI(BaseAPI): def get_preferences(self) -> types.ResponseDict: """ Get preferences of the current user: country, currency, language, unit - - :return: """ return self._request("GET", "my-profile/preferences/") @@ -29,11 +27,11 @@ def set_preferences( Update profile of the current user. All arguments are optional, only passed values will be saved to the profile. - :param country: 2-letter country code, ex. US, FR, GB - :param currency: 3-letter currency code, ex. USD, EUR - :param language: 2-letter language code, ex. en, de, fr, es - :param unit: mm or inch - :return: + Args: + country: 2-letter country code, ex. US, FR, GB + currency: 3-letter currency code, ex. USD, EUR + language: 2-letter language code, ex. en, de, fr, es + unit: mm or inch """ json = self._get_parameters( @@ -44,8 +42,6 @@ def set_preferences( def get_profile(self) -> types.ResponseDict: """ Get profile of the current user: name, default address, access roles etc. - - :return: """ return self._request("GET", "my-profile/profile/") @@ -53,8 +49,6 @@ def get_profile(self) -> types.ResponseDict: def get_addresses(self) -> t.List[types.ResponseDict]: """ Get a list of current user's addresses - - :return: """ return self._request("GET", "my-profile/addresses/") @@ -62,8 +56,6 @@ def get_addresses(self) -> t.List[types.ResponseDict]: def get_address(self, *, address_id: int) -> types.ResponseDict: """ Get specific address of the current user - - :return: """ return self._request("GET", f"my-profile/addresses/{address_id}/") diff --git a/push_to_3yourmind/api/user_panel.py b/push_to_3yourmind/api/user_panel.py index e81dcfa..7176147 100644 --- a/push_to_3yourmind/api/user_panel.py +++ b/push_to_3yourmind/api/user_panel.py @@ -19,6 +19,13 @@ class UserPanelAPI(BaseAPI): """ Groups API functionality from the User Panel, such as creating/updating baskets, placing orders, making requests for quotes, ordering quotes etc. + + Accessible via namespace `user_panel`, for example: + >>> response = client.user_panel.get_baskets() + + Attributes: + CHECK_FILE_STATUS_MAX_ATTEMPTS: How many times to check for the uploaded CAD file analysis status + CHECK_FILE_STATUS_DELAY: Delay between status check requests, in seconds """ CHECK_FILE_STATUS_MAX_ATTEMPTS = 60 @@ -33,20 +40,30 @@ def get_baskets( """ Get all baskets of the current user. Returns paginated list. - :param page: int, optional - :param page_size: int, optional - :return: dictionary with the following keys: - count: total number of baskets - currentPage: - totalPages: - pageSize: baskets per page - results: list of basket details + Args: + page: int, optional + page_size: int, optional + Returns: + dictionary with the following keys: + + - count: total number of baskets, int + - currentPage: page number, int + - totalPages: total number of pages, int + - pageSize: baskets per page, int + - results: list of basket details """ query = self._get_parameters(page=page, pageSize=page_size) return self._request("GET", "user-panel/baskets/", params=query) def get_basket(self, *, basket_id: int) -> types.ResponseDict: + """ + Args: + basket_id: int + + Returns: + Basket details dict + """ return self._request("GET", f"user-panel/baskets/{basket_id}/") def get_basket_price( @@ -59,6 +76,20 @@ def get_basket_price( shipping_method_id: types.OptionalNumber = types.NoValue, voucher_code: types.OptionalString = types.NoValue, ) -> types.ResponseDict: + """ + Calculate basket's price, given additional optional shipping, billing information + + Args: + basket_id: int + currency: str + shipping_address_id: int, optional + billing_address_id: int, optional + shipping_method_id: int, optional + voucher_code: str, optional + + Returns: + Dict containing basket prices + """ query = self._get_parameters( currency=currency, shippingAddressId=shipping_address_id, diff --git a/push_to_3yourmind/exceptions.py b/push_to_3yourmind/exceptions.py index 3322a7f..23d1cba 100644 --- a/push_to_3yourmind/exceptions.py +++ b/push_to_3yourmind/exceptions.py @@ -5,15 +5,17 @@ class BasePushTo3YourmindAPIException(Exception): class ObjectNotFound(BasePushTo3YourmindAPIException): - """ - Is raised when an API endpoint response is 404 - Object Not Found - """ + pass class Unauthorized(BasePushTo3YourmindAPIException): pass +class AccessDenied(BasePushTo3YourmindAPIException): + pass + + class BadRequest(BasePushTo3YourmindAPIException): pass diff --git a/push_to_3yourmind/main.py b/push_to_3yourmind/main.py index 7dcb3e5..36f4839 100644 --- a/push_to_3yourmind/main.py +++ b/push_to_3yourmind/main.py @@ -8,6 +8,23 @@ class PushTo3YourmindAPI(BaseAPI): + """ + The main class and the entrypoint for API + + >>> from push_to_3yourmind import PushTo3YourmindAPI + >>> client = PushTo3YourmindAPI(access_token="QWERTY123456789", base_url="http://") + + Functionality is divided into namespaces, for example `my_profile`, `user_panel` etc. Some + API endpoints require proper user permissions, in case when an API can't be reached, an exception + AccessDenied is raised. + + Attributes: + user_panel: order management-related API: create/update basket lines, + upload CAD files, pricing + common: common API: country, unit, material lists + my_profile: API to manage user's preferences, profile, address list etc + """ + def __init__(self, access_token: str, base_url: str): super().__init__(access_token, base_url) self.user_panel = UserPanelAPI(access_token, base_url) diff --git a/push_to_3yourmind/types.py b/push_to_3yourmind/types.py index 4abae6b..a4099e5 100644 --- a/push_to_3yourmind/types.py +++ b/push_to_3yourmind/types.py @@ -1,10 +1,35 @@ +""" +This module contains NoValue class and type aliases for type annotations +""" + import datetime import decimal import typing as t +__all__ = ["NoValue"] + + class NoValue: - pass + """ + Some class methods accept arguments that are optional. Skipping them means + "no data changed" and will lead to not sending them to the 3YD API. To skip such an + argument give it a `NoValue` value. + + For example, `client.my_profile.set_preferences` can accept 4 arguments: + country, currency, language, unit. If you need to update user's unit but leave other + settings unchanged: + + >>> client.my_profile.set_preferences(unit="inch", country=NoValue, currency=NoValue, language=NoValue) + # or shorter + >>> client.my_profile.set_preferences(unit="inch") + + The following: + + >>> client.my_profile.set_preferences(unit="inch", country=None, currency=None, language=None) + + ... it will mean that you want to set user's country, currency and language setting to NULL. + """ ResponseDict = t.Dict[str, t.Any]