def part(
        self,
        partnr: str,
        include_associated: bool = False,
        include_for_use_with: bool = False,
        use_cache: bool = True,
    ) -> dict:
        """
        Query part by unique ID
        Args:
            partnr (str): Part number. Works best with Digi-Key part numbers.
            include_associated (bool): The option to include all Associated products
            include_for_use_with (bool): The option to include all For Use With product
            use_cache (bool): Use cache to limit requests made to API
        Kwargs:
        Returns:
            dict. See `models.Part` for exact fields.
        """
        part_cache = self._cache_path.joinpath(
            'part', '{}.json'.format(partnr.replace('/', '_')))
        if use_cache and part_cache.exists():
            cache = json.load(open(part_cache))
            cache_datetime = datetime.fromisoformat(cache['timestamp'])
            if cache_datetime + self._cache_max_age > datetime.now():
                if len(cache.keys()) == 1:
                    raise DigikeyError(
                        "[CACHE] No results found for {}".format(partnr))
                return cache
            part_cache.unlink()

        data = {
            'part': partnr,
            'include_all_associated_products': include_associated,
            'include_all_for_use_with_products': include_for_use_with
        }

        if not models.PartDetailPostRequest.is_valid(data):
            errors = models.PartDetailPostRequest.errors(data)
            raise DigikeyError('Query is malformed: %s' % errors)

        # Convert `query` to format that Octopart accepts.
        params = models.PartDetailPostRequest.camelize(
            models.PartDetailPostRequest(data).to_primitive())

        try:
            result = self._request('/partdetails', data=params)
        except DigikeyError as e:
            json.dump({'timestamp': datetime.now().isoformat()},
                      open(part_cache, 'w'))
            raise e

        result_cache = dict(result)
        result_cache['timestamp'] = datetime.now().isoformat()
        json.dump(result_cache, open(part_cache, 'w'))

        return result
Example #2
0
    def part(
        self,
        partnr: str,
        include_associated: bool = False,
        include_for_use_with: bool = False,
    ) -> dict:
        """
        Query part by unique ID
        Args:
            partnr (str): Part number. Works best with Digi-Key part numbers.
            include_associated (bool): The option to include all Associated products
            include_for_use_with (bool): The option to include all For Use With product
        Kwargs:
        Returns:
            dict. See `models.Part` for exact fields.
        """
        data = {
            'part': partnr,
            'include_all_associated_products': include_associated,
            'include_all_for_use_with_products': include_for_use_with
        }

        if not models.PartDetailPostRequest.is_valid(data):
            errors = models.PartDetailPostRequest.errors(data)
            raise DigikeyError('Query is malformed: %s' % errors)

        # Convert `query` to format that Octopart accepts.
        params = models.PartDetailPostRequest.camelize(
            models.PartDetailPostRequest(data).to_primitive())

        return self._request('/partdetails', data=params)
Example #3
0
    def search(self,
               query: str,  # maps to "keyword" parameter in Digikey API
               start: int = 0,
               limit: int = 10,
               ) -> dict:
        """
        Search for parts, using more fields and filter options than 'match'.
        This calls the /parts/search endpoint of the Octopart API:
        https://octopart.com/api/docs/v3/rest-api#endpoints-parts-search
        Args:
            query (str): free-form keyword query
            start (int): ordinal position of first result
            limit (int): maximum number of results to return
        Kwargs:
        Returns:
            dict. See `models.PartsSearchResponse` for exact fields.
        """
        data = {
            'keywords': query,
            'search_options': None,
            'record_count': limit,
            'record_start_pos': start,
            'filters': None,
            'sort': None,
            'requested_quantity': 1
        }

        if not models.KeywordSearchRequest.is_valid(data):
            errors = models.KeywordSearchRequest.errors(data)
            raise DigikeyError('Query is malformed: %s' % errors)

        # Convert `query` to format that Octopart accepts.
        params = models.KeywordSearchRequest.camelize(models.KeywordSearchRequest(data).to_primitive())

        return self._request('/keywordsearch', data=params)
Example #4
0
def manufacturer_product_details(*args, **kwargs) -> KeywordSearchResponse:
    client = DigikeyApiWrapper('manufacturer_product_details_with_http_info', digikey.v3.productinformation)

    if 'body' in kwargs and type(kwargs['body']) == ManufacturerProductDetailsRequest:
        logger.info(f'Search for: {kwargs["body"].manufacturer_product}')
        return client.call_api_function(*args, **kwargs)
    else:
        raise DigikeyError('Please provide a valid ManufacturerProductDetailsRequest argument')
Example #5
0
    def __init__(self, wrapped_function, module):
        self.sandbox = False

        apinames = {
            digikey.v3.productinformation: 'Search',
            digikey.v3.ordersupport: 'OrderDetails',
            digikey.v3.batchproductdetails: 'BatchSearch'
        }

        apiclasses = {
            digikey.v3.productinformation:
            digikey.v3.productinformation.PartSearchApi,
            digikey.v3.ordersupport:
            digikey.v3.ordersupport.OrderDetailsApi,
            digikey.v3.batchproductdetails:
            digikey.v3.batchproductdetails.BatchSearchApi
        }

        apiname = apinames[module]
        apiclass = apiclasses[module]

        # Configure API key authorization: apiKeySecurity
        configuration = module.Configuration()
        configuration.api_key['X-DIGIKEY-Client-Id'] = os.getenv(
            'DIGIKEY_CLIENT_ID')

        # Return quietly if no clientid has been set to prevent errors when importing the module
        if os.getenv('DIGIKEY_CLIENT_ID') is None or os.getenv(
                'DIGIKEY_CLIENT_SECRET') is None:
            raise DigikeyError(
                'Please provide a valid DIGIKEY_CLIENT_ID and DIGIKEY_CLIENT_SECRET in your env setup'
            )

        # Use normal API by default, if DIGIKEY_CLIENT_SANDBOX is True use sandbox API
        configuration.host = 'https://api.digikey.com/' + apiname + '/v3'
        try:
            if bool(strtobool(os.getenv('DIGIKEY_CLIENT_SANDBOX'))):
                configuration.host = 'https://sandbox-api.digikey.com/' + apiname + '/v3'
                self.sandbox = True
        except (ValueError, AttributeError):
            pass

        # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
        # configuration.api_key_prefix['X-DIGIKEY-Client-Id'] = 'Bearer'

        # Configure OAuth2 access token for authorization: oauth2AccessCodeSecurity
        self._digikeyApiToken = digikey.oauth.oauth2.TokenHandler(
            version=3, sandbox=self.sandbox).get_access_token()
        configuration.access_token = self._digikeyApiToken.access_token

        # create an instance of the API class
        self._api_instance = apiclass(module.ApiClient(configuration))

        # Populate reused ids
        self.authorization = self._digikeyApiToken.get_authorization()
        self.x_digikey_client_id = os.getenv('DIGIKEY_CLIENT_ID')

        self.wrapped_function = wrapped_function
Example #6
0
def keyword_search(*args, **kwargs) -> KeywordSearchResponse:
    client = DigikeyApiWrapper('keyword_search_with_http_info', digikey.v3.productinformation)

    if 'body' in kwargs and type(kwargs['body']) == KeywordSearchRequest:
        logger.info(f'Search for: {kwargs["body"].keywords}')
        logger.debug('CALL -> keyword_search')
        return client.call_api_function(*args, **kwargs)
    else:
        raise DigikeyError('Please provide a valid KeywordSearchRequest argument')
Example #7
0
def batch_product_details(*args, **kwargs) -> BatchProductDetailsResponse:
    client = DigikeyApiWrapper('batch_product_details_with_http_info', digikey.v3.batchproductdetails)

    if 'body' in kwargs and type(kwargs['body']) == BatchProductDetailsRequest:
        logger.info(f'Batch product search: {kwargs["body"].products}')
        logger.debug('CALL -> batch_product_details')
        return client.call_api_function(*args, **kwargs)
    else:
        raise DigikeyError('Please provide a valid BatchProductDetailsRequest argument')
Example #8
0
def salesorder_history(*args, **kwargs) -> [SalesOrderHistoryItem]:
    client = DigikeyApiWrapper('history_get_with_http_info', digikey.v3.ordersupport)

    if 'start_date' in kwargs and type(kwargs['start_date']) == str \
            and 'end_date' in kwargs and type(kwargs['end_date']) == str:
        logger.info(f'Searching for orders in date range ' + kwargs['start_date'] + ' to ' + kwargs['end_date'])
        return client.call_api_function(*args, **kwargs)
    else:
        raise DigikeyError('Please provide valid start_date and end_date strings')
Example #9
0
    def part(
        self,
        partnr: str,
        include_associated: bool = False,
        include_for_use_with: bool = False,
    ) -> dict:
        """
        Query part by unique ID
        Args:
            partnr (str): Part number. Works best with Digi-Key part numbers.
            include_associated (bool): The option to include all Associated products
            include_for_use_with (bool): The option to include all For Use With product
        Kwargs:
        Returns:
            dict. See `models.Part` for exact fields.
        """
        #TODO: (also in Model) How to best keep these fields include_all_associated_products, include_all_for_use_with_products from PartDetailPostRequest
        # data = {
        #     'part': partnr,
        #     'include_all_associated_products': include_associated,
        #     'include_all_for_use_with_products': include_for_use_with
        # }

        data = {
            'part': partnr,
            # 'includes': "DigiKeyPartNumber,ManufacturerPartNumber,QuantityAvailable,AssociatedProducts[2]"
        }

        if not models.ProductDetailGetRequest.is_valid(data):
            errors = models.ProductDetailGetRequest.errors(data)
            raise DigikeyError('Query is malformed: %s' % errors)

        # Convert `query` to format that Digikey accepts.
        params = models.ProductDetailGetRequest.camelize(
            models.ProductDetailGetRequest(data).to_primitive())

        del params['Part']
        return self._request_get('/Search/v3/Products/{}'.format(partnr),
                                 data=params)