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
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)
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)
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')
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
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')
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')
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')
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)