Skip to content

Commit

Permalink
Merge pull request #251 from sparkmicro/dev
Browse files Browse the repository at this point in the history
1.1.2
  • Loading branch information
eeintech authored Jul 12, 2024
2 parents 87bfafa + e61e2e6 commit e676d13
Show file tree
Hide file tree
Showing 15 changed files with 164 additions and 101 deletions.
2 changes: 1 addition & 1 deletion kintree/common/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,5 @@ def download_with_retry(url: str, full_path: str, silent=False, **kwargs) -> str
if not file:
return False

cprint('[INFO]\tSuccess: Part image downloaded', silent=silent)
cprint(f'[INFO]\tDownload success ({url=})', silent=silent)
return True
8 changes: 8 additions & 0 deletions kintree/config/config_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ def load_config(path):
user_settings = {**template_data, **user_data}
else:
user_settings = user_data
# Warn user about config data discrepancies with template data
template_vs_user = set(template_data) - set(user_data)
# user_vs_template = set(user_data) - set(template_data)
if template_vs_user:
print(f'[INFO]\tTEMPLATE "{filename}" configuration file contains the following keys which are NOT in your user settings: {template_vs_user}')
# if user_vs_template:
# cprint(f'[INFO]\tUSER SETTINGS {filename} configuration file contains the following keys which are NOT in the template: {user_vs_template}', silent=silent)

except (TypeError, AttributeError):
cprint(f'[INFO]\tCreating new {filename} configuration file', silent=silent)
# Config file does not exists
Expand Down
36 changes: 26 additions & 10 deletions kintree/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,34 @@ def load_suppliers():
global CONFIG_SUPPLIERS
global SUPPORTED_SUPPLIERS_API

update_supplier_config = {}
SUPPORTED_SUPPLIERS_API = []
for supplier, data in CONFIG_SUPPLIERS.items():
if data['enable']:
if data['name']:
supplier_name = data['name'].replace(' ', '')
SUPPORTED_SUPPLIERS_API.append(supplier_name)
else:
supplier_key = supplier.replace(' ', '')
SUPPORTED_SUPPLIERS_API.append(supplier_key)


load_suppliers()
try:
if data['enable']:
if data['name']:
supplier_name = data['name'].replace(' ', '')
SUPPORTED_SUPPLIERS_API.append(supplier_name)
else:
supplier_key = supplier.replace(' ', '')
SUPPORTED_SUPPLIERS_API.append(supplier_key)
except (TypeError, KeyError):
update_supplier_config[supplier] = {
'enable': True,
'name': supplier,
}

# Update supplier configuration file
if update_supplier_config:
config_interface.dump_file({**CONFIG_SUPPLIERS, **update_supplier_config}, CONFIG_SUPPLIERS_PATH)
CONFIG_SUPPLIERS = config_interface.load_file(CONFIG_SUPPLIERS_PATH)
return False
return True


if not load_suppliers():
# Re-load updated configuration file
load_suppliers()

# Generic API user configuration
CONFIG_SUPPLIER_PARAMETERS = os.path.join(CONFIG_USER_FILES, 'supplier_parameters.yaml')
Expand Down
9 changes: 5 additions & 4 deletions kintree/database/inventree_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ def create_category(parent: str, name: str):
return category_pk, is_new_category


def upload_part_image(image_url: str, part_id: int) -> bool:
def upload_part_image(image_url: str, part_id: int, silent=False) -> bool:
''' Upload InvenTree part thumbnail'''
global inventree_api

Expand All @@ -448,7 +448,7 @@ def upload_part_image(image_url: str, part_id: int) -> bool:
image_location = settings.search_images + image_name

# Download image (multiple attempts)
if not download_with_retry(image_url, image_location, filetype='Image'):
if not download_with_retry(image_url, image_location, filetype='Image', silent=silent):
return False

# Upload image to InvenTree
Expand All @@ -462,7 +462,7 @@ def upload_part_image(image_url: str, part_id: int) -> bool:
return False


def upload_part_datasheet(datasheet_url: str, part_ipn: int, part_pk: int) -> str:
def upload_part_datasheet(datasheet_url: str, part_ipn: int, part_pk: int, silent=False) -> str:
''' Upload InvenTree part attachment'''
global inventree_api

Expand All @@ -479,7 +479,8 @@ def upload_part_datasheet(datasheet_url: str, part_ipn: int, part_pk: int) -> st
datasheet_url,
datasheet_location,
filetype='PDF',
timeout=10
timeout=10,
silent=silent,
):
return ''

Expand Down
36 changes: 20 additions & 16 deletions kintree/database/inventree_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ def get_inventree_stock_location_id(stock_location_tree: list):
return inventree_api.get_inventree_stock_location_id(stock_location_tree)


def inventree_create(part_info: dict, stock=None, kicad=False, symbol=None, footprint=None, show_progress=True, is_custom=False):
def inventree_create(part_info: dict, stock=None, kicad=False, symbol=None, footprint=None, show_progress=True, is_custom=False, enable_upload=False):
''' Create InvenTree part from supplier part data and categories '''

part_pk = 0
Expand Down Expand Up @@ -659,21 +659,24 @@ def inventree_create(part_info: dict, stock=None, kicad=False, symbol=None, foot
part_pk,
data={'existing_image': inventree_part['existing_image']})
elif inventree_part['image']:
# Add image
image_result = inventree_api.upload_part_image(inventree_part['image'], part_pk)
if not image_result:
cprint('[TREE]\tWarning: Failed to upload part image', silent=settings.SILENT)
if enable_upload:
# Add image
image_result = inventree_api.upload_part_image(inventree_part['image'], part_pk, silent=settings.SILENT)
if not image_result:
cprint('[TREE]\tWarning: Failed to upload part image', silent=settings.SILENT)
if inventree_part['datasheet'] and settings.DATASHEET_UPLOAD:
# Upload datasheet
datasheet_link = inventree_api.upload_part_datasheet(
datasheet_url=inventree_part['datasheet'],
part_ipn=inventree_part['IPN'],
part_pk=part_pk,
)
if not datasheet_link:
cprint('[TREE]\tWarning: Failed to upload part datasheet', silent=settings.SILENT)
else:
cprint('[TREE]\tSuccess: Uploaded part datasheet', silent=settings.SILENT)
if enable_upload:
# Upload datasheet
datasheet_link = inventree_api.upload_part_datasheet(
datasheet_url=inventree_part['datasheet'],
part_ipn=inventree_part['IPN'],
part_pk=part_pk,
silent=settings.SILENT,
)
if not datasheet_link:
cprint('[TREE]\tWarning: Failed to upload part datasheet', silent=settings.SILENT)
else:
cprint('[TREE]\tSuccess: Uploaded part datasheet', silent=settings.SILENT)

if kicad:
try:
Expand Down Expand Up @@ -845,7 +848,7 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr
inventree_api.update_part(pk=part_pk,
data={'existing_image': existing_image})
elif image:
inventree_api.upload_part_image(image_url=image, part_id=part_pk)
inventree_api.upload_part_image(image_url=image, part_id=part_pk, silent=settings.SILENT)

# create or update parameters
if inventree_part.get('parameters', {}):
Expand All @@ -866,6 +869,7 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr
datasheet_url=datasheet,
part_ipn=part_ipn,
part_pk=part_id,
silent=settings.SILENT,
)
if not part_info['datasheet']:
cprint('[TREE]\tWarning: Failed to upload part datasheet', silent=settings.SILENT)
Expand Down
8 changes: 0 additions & 8 deletions kintree/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ def init_gui(page: ft.Page):
# to show the user that the app is busy doing something
page.splash = ft.ProgressBar(visible=False)

# Init dialogs
page.snack_bar = ft.SnackBar(
content=None,
open=False,
)
page.banner = ft.Banner()
page.dialog = ft.AlertDialog()

# Update
page.update()

Expand Down
6 changes: 4 additions & 2 deletions kintree/gui/views/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,10 @@ def show_dialog(
self._page.banner = self.dialog
self._page.banner.open = open
elif isinstance(self.dialog, ft.AlertDialog):
self._page.dialog = self.dialog
self._page.dialog.open = open
if open:
self._page.open(self.dialog)
else:
self._page.close(self.dialog)
self._page.update()


Expand Down
8 changes: 4 additions & 4 deletions kintree/search/automationdirect_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def find_categories(part_details: str):
return None, None


def fetch_part_info(part_number: str) -> dict:
def fetch_part_info(part_number: str, silent=False) -> dict:
''' Fetch part data from API '''

# Load Automation Direct settingss
Expand All @@ -81,7 +81,7 @@ def search_timeout(timeout=10):
part = part['solrResult']['response'] # extract the data for parts returned
if part['numFound'] > 0:
if part['numFound'] == 1:
cprint(f'[INFO]\tFound exactly one result for "{part_number}"', silent=False)
cprint(f'[INFO]\tFound exactly one result for "{part_number}"', silent=True)
else:
cprint(f'[INFO]\tFound {part["numFound"]} results for "{part_number}", selecting first result', silent=False)
part = part['docs'][0] # choose the first part in the returned returned list
Expand Down Expand Up @@ -212,7 +212,7 @@ def search_timeout(timeout=10):

except KeyError as e:
from ..common.tools import cprint
cprint(f'[INFO]\tNo pricing attribute "{e.args[0]}" found for "{part_number}"')
cprint(f'[INFO]\tNo pricing attribute "{e.args[0]}" found for "{part_number}"', silent=silent)
part_info['pricing']['1'] = price_per_unit

part_info['currency'] = 'USD'
Expand Down Expand Up @@ -255,7 +255,7 @@ def test_api() -> bool:
}
}

test_part = fetch_part_info('BX-16ND3')
test_part = fetch_part_info('BX-16ND3', silent=True)
if not test_part:
test_success = False

Expand Down
12 changes: 6 additions & 6 deletions kintree/search/element14_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,14 @@ def get_default_store_url(supplier: str) -> str:
return STORES[supplier][default_store]


def build_api_url(part_number: str, supplier: str, store_url=None) -> str:
def build_api_url(part_number: str, supplier: str, store_url=None, silent=False) -> str:
''' Build API URL based on user settings '''

user_settings = config_interface.load_file(settings.CONFIG_ELEMENT14_API)
api_key = user_settings.get('ELEMENT14_PRODUCT_SEARCH_API_KEY', '')
if not api_key:
from ..common.tools import cprint
cprint('[INFO]\tWarning: ELEMENT14_PRODUCT_SEARCH_API_KEY user value not configured', silent=False)
cprint('[INFO]\tWarning: ELEMENT14_PRODUCT_SEARCH_API_KEY user value not configured', silent=silent)

import os
api_key = os.environ.get('ELEMENT14_PART_API_KEY', None)
Expand Down Expand Up @@ -213,13 +213,13 @@ def build_image_url(image_data: dict, supplier: str, store_url=None) -> str:
return image_url


def fetch_part_info(part_number: str, supplier: str, store_url=None) -> dict:
def fetch_part_info(part_number: str, supplier: str, store_url=None, silent=False) -> dict:
''' Fetch part data from API '''

part_info = {}

def search_timeout(timeout=10):
url = build_api_url(part_number, supplier, store_url)
url = build_api_url(part_number, supplier, store_url, silent)
response = download(url, timeout=timeout)
return response

Expand Down Expand Up @@ -349,15 +349,15 @@ def test_api(store_url=None) -> bool:
if store_url:
# If store URL is specified, only check data is returned (eg. avoid discrepancies between stores)
part_number = '1N4148'
test_part = fetch_part_info(part_number, '', store_url)
test_part = fetch_part_info(part_number, '', store_url, True)
if not test_part:
test_success = False
else:
for item in search_queries:
if not test_success:
break

test_part = fetch_part_info(item['part_number'], '', item['store_url'])
test_part = fetch_part_info(item['part_number'], '', item['store_url'], True)

if not test_part:
test_success = False
Expand Down
2 changes: 1 addition & 1 deletion kintree/search/mouser_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_api() -> bool:

test_success = True
expected = {
'Description': 'MOSFET P-channel 1.25W',
'Description': 'MOSFETs P-channel 1.25W',
'MouserPartNumber': '621-DMP2066LSN-7',
'Manufacturer': 'Diodes Incorporated',
'ManufacturerPartNumber': 'DMP2066LSN-7',
Expand Down
18 changes: 14 additions & 4 deletions kintree/search/snapeda_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def parse_snapeda_response(response: dict) -> dict:
return data


def download_snapeda_images(snapeda_data: dict) -> dict:
def download_snapeda_images(snapeda_data: dict, silent=False) -> dict:
''' Download symbol and footprint images from SnapEDA's server '''

images = {
Expand All @@ -83,7 +83,12 @@ def download_snapeda_images(snapeda_data: dict) -> dict:
image_location = settings.search_images + image_name

# Download symbol image
symbol = download_with_retry(snapeda_data['symbol_image'], image_location, filetype='Image')
symbol = download_with_retry(
url=snapeda_data['symbol_image'],
full_path=image_location,
filetype='Image',
silent=silent,
)
if symbol:
images['symbol'] = image_location
except KeyError:
Expand All @@ -96,7 +101,12 @@ def download_snapeda_images(snapeda_data: dict) -> dict:
image_location = settings.search_images + image_name

# Download symbol image
footprint = download_with_retry(snapeda_data['footprint_image'], image_location, filetype='Image')
footprint = download_with_retry(
url=snapeda_data['footprint_image'],
full_path=image_location,
filetype='Image',
silent=silent,
)
if footprint:
images['footprint'] = image_location
except KeyError:
Expand All @@ -113,7 +123,7 @@ def test_snapeda_api() -> bool:
# Test single result
response = fetch_snapeda_part_info('NTR06B2001CTRF')
data = parse_snapeda_response(response)
images = download_snapeda_images(data)
images = download_snapeda_images(data, silent=True)

if data['part_number'] and data['has_symbol'] and images['symbol']:
result = True
Expand Down
Loading

0 comments on commit e676d13

Please sign in to comment.