Skip to content

Commit

Permalink
Merge pull request #270 from sparkmicro/dev
Browse files Browse the repository at this point in the history
1.2.0
  • Loading branch information
eeintech authored Dec 29, 2024
2 parents 345304e + 7413eba commit 070f29a
Show file tree
Hide file tree
Showing 21 changed files with 943 additions and 883 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test_deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

strategy:
matrix:
python-version: ['3.9', '3.10', '3.11']
python-version: ['3.9', '3.10', '3.11', '3.12']

steps:
- name: Checkout code
Expand Down Expand Up @@ -51,13 +51,16 @@ jobs:
TOKEN_DIGIKEY: ${{ secrets.TOKEN_DIGIKEY }}
DIGIKEY_CLIENT_ID: ${{ secrets.DIGIKEY_CLIENT_ID }}
DIGIKEY_CLIENT_SECRET: ${{ secrets.DIGIKEY_CLIENT_SECRET }}
DIGIKEY_LOCAL_SITE: US
DIGIKEY_LOCAL_LANGUAGE: en
DIGIKEY_LOCAL_CURRENCY: USD
TME_API_TOKEN: ${{ secrets.TME_API_TOKEN }}
TME_API_SECRET: ${{ secrets.TME_API_SECRET }}

continue-on-error: true
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11']
python-version: ['3.9', '3.10', '3.11', '3.12']

steps:
- name: Checkout code
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Ki-nTree works with:

> :warning: **Important Note**
>
> Ki-nTree version `1.2.x` and forward support Digi-Key API version **4 only**.
>
> Ki-nTree version `1.0.x` and forward support KiCad versions **6 and up**.
>
> Ki-nTree versions `0.5.x` and `0.6.x` only support KiCad version **6** (`pip install kintree==0.6.6`).
Expand All @@ -40,11 +42,16 @@ Ki-nTree was developed by [@eeintech](https://github.com/eeintech) for [SPARK Mi

### Requirements

* Ki-nTree is currently tested for Python 3.9 to 3.11 versions.
* Ki-nTree is currently tested for Python 3.9 to 3.12 versions.
* Ki-nTree requires a Digi-Key **production** API instance. To create one, go to https://developer.digikey.com/. Create an account, an organization and add a **production** API to your organization. Save both Client ID and Secret keys.
> [Here is a video](https://youtu.be/OI1EGEc0Ju0) to help with the different steps
* Ki-nTree requires a Mouser Search API key. To request one, head over to https://www.mouser.ca/api-search/ and click on "Sign Up for Search API"
* Ki-nTree requires an Element14 Product Search API key to fetch part information for the following suppliers: Farnell (Europe), Newark (North America) and Element14 (Asia-Pacific). To request one, head over to https://partner.element14.com/ and click on "Register"
* on rolling release distributions like Arch Linux some Flet dependencies need to be repaired manually:
```
sudo pacman -S mpv
sudo ln -s /usr/lib/libmpv.so /usr/lib/libmpv.so.1
```

### Installation (system wide)

Expand Down
2 changes: 1 addition & 1 deletion images/python_versions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion kintree/common/part_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def clean_parameter_value(category: str, name: str, value: str) -> str:

# Remove parenthesis section
if '(' in value:
parenthesis = re.findall('\(.*\)', value)
parenthesis = re.findall(r'\(.*\)', value)

if parenthesis:
for item in parenthesis:
Expand Down
2 changes: 1 addition & 1 deletion kintree/common/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_image_with_retries(url, headers, retries=3, wait=5, silent=False):
scraper = cloudscraper.create_scraper()
for attempt in range(retries):
try:
response = scraper.get(url, headers=headers)
response = scraper.get(url, headers=headers, timeout=wait)
if response.status_code == 200:
return response
else:
Expand Down
10 changes: 2 additions & 8 deletions kintree/database/inventree_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,19 +751,12 @@ def create_supplier_part(part_id: int, manufacturer_name: str, manufacturer_mpn:
return False, False


def sanitize_price(price_in):
price = re.findall('\d+.\d+', price_in)[0]
price = price.replace(',', '.')
price = price.replace('\xa0', '')
return price


def update_price_breaks(supplier_part,
price_breaks: dict,
currency='USD') -> bool:
''' Update the Price Breaks associated with a supplier part '''
def sanitize_price(price_in):
price = re.findall('\d+.\d+', price_in)[0]
price = re.findall(r'\d+.\d+', price_in)[0]
price = price.replace(',', '.')
price = price.replace('\xa0', '')
return price
Expand Down Expand Up @@ -838,6 +831,7 @@ def create_parameter_template(name: str, units: str) -> int:
})
except:
cprint(f'[TREE]\tError: Failed to create parameter template "{name}".', silent=settings.SILENT)
return 0

if parameter_template:
return parameter_template.pk
Expand Down
61 changes: 0 additions & 61 deletions kintree/gui/views/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from enum import Enum
from math import pi
from typing import Optional, List

import flet as ft
Expand Down Expand Up @@ -394,66 +393,6 @@ def done_search(self, e=None):
self.options = self._options
self.dropdown.update()


class Collapsible(ft.Column):
def __init__(
self,
title: str,
content: ft.Control,
icon: Optional[ft.Control] = None,
spacing: float = 3,
radio: Optional[ft.Radio] = None,
scale: ft.types.ScaleValue = 1,
):
super().__init__()
self.icon = icon
self.title = title
self.scale = scale
self.shevron = ft.Icon(
ft.icons.KEYBOARD_ARROW_RIGHT_ROUNDED,
animate_rotation=100,
rotate=0,
scale=self.scale,
)
self.content = ft.Column(
[ft.Container(height=spacing), content],
height=0,
spacing=0,
animate_size=100,
opacity=0,
animate_opacity=100,
scale=self.scale,
)
self.spacing = 0
self.radio = radio
self.radio.scale = self.scale

def header_click(self, e):
self.content.height = None if self.content.height == 0 else 0
self.content.opacity = 0 if self.content.height == 0 else 1
self.shevron.rotate = pi / 2 if self.shevron.rotate == 0 else 0
self.update()

def build(self):
title_row = ft.Row()
if self.icon is not None:
title_row.controls.append(self.icon)
if self.radio:
title_row.controls.append(self.radio)
else:
title_row.controls.append(ft.Text(self.title))
self.controls = [
ft.Container(
ft.Row([title_row, self.shevron], alignment="spaceBetween"),
padding=ft.padding.only(left=8, right=8),
height=38,
border_radius=4,
ink=True,
on_click=self.header_click,
),
self.content,
]


class MenuButton(ft.Container):
def __init__(
Expand Down
5 changes: 3 additions & 2 deletions kintree/gui/views/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
maximizable=True,
),
leading_width=40,
title=ft.WindowDragArea(ft.Text(f'Ki-nTree | {__version__}'), maximizable=True),
title=ft.WindowDragArea(ft.Container(ft.Text(f'Ki-nTree | {__version__}'),
width=10000), maximizable=True),
center_title=False,
bgcolor=ft.colors.SURFACE_VARIANT,
actions=[],
Expand Down Expand Up @@ -313,7 +314,7 @@ def run_search(self, e):
self.reset_view(e, ignore=['part_number', 'supplier'])
self.switch_view()
# Validate form
if bool(self.fields['part_number'].value) != bool(self.fields['supplier'].value):
if bool(self.fields['part_number'].value) != bool(self.fields['supplier'].value) or not self.fields['part_number'].value and not self.fields['supplier'].value:
if not self.fields['part_number'].value:
error_msg = 'Missing Part Number'
else:
Expand Down
30 changes: 29 additions & 1 deletion kintree/gui/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@
ft.TextField(),
None,
]
supplier_settings[supplier]['Local Site'] = [
digikey_api_settings.get('DIGIKEY_LOCAL_SITE', 'US'),
ft.TextField(),
None,
]
supplier_settings[supplier]['Language'] = [
digikey_api_settings.get('DIGIKEY_LOCAL_LANGUAGE', 'en'),
ft.TextField(),
None,
]
supplier_settings[supplier]['Currency'] = [
digikey_api_settings.get('DIGIKEY_LOCAL_CURRENCY', 'USD'),
ft.TextField(),
None,
]
elif supplier == 'Mouser':
mouser_api_settings = config_interface.load_file(global_settings.CONFIG_MOUSER_API)
supplier_settings[supplier]['Part API Key'] = [
Expand Down Expand Up @@ -291,7 +306,8 @@

# Settings AppBar
settings_appbar = ft.AppBar(
title=ft.Text('Ki-nTree Settings'),
title=ft.WindowDragArea(ft.Container(ft.Text('Ki-nTree Settings'),
width=10000), maximizable=True),
bgcolor=ft.colors.SURFACE_VARIANT
)

Expand Down Expand Up @@ -359,6 +375,15 @@ def __init__(self, page: ft.Page):

# Init view
super().__init__(page=page, appbar=settings_appbar, navigation_rail=settings_navrail)
if not self.appbar.actions:
self.appbar.actions.extend(
[
ft.IconButton(
ft.icons.CLOSE,
on_click=lambda _: page.window.close(),
),
]
)

# Update navigation rail
self.navigation_rail.on_change = self.nav_rail_redirect
Expand Down Expand Up @@ -673,6 +698,9 @@ def save_s(self, e: ft.ControlEvent, supplier: str, show_dialog=True):
updated_settings = {
'DIGIKEY_CLIENT_ID': SETTINGS[self.title][supplier]['Client ID'][1].value,
'DIGIKEY_CLIENT_SECRET': SETTINGS[self.title][supplier]['Client Secret'][1].value,
'DIGIKEY_LOCAL_SITE': SETTINGS[self.title][supplier]['Local Site'][1].value,
'DIGIKEY_LOCAL_LANGUAGE': SETTINGS[self.title][supplier]['Language'][1].value,
'DIGIKEY_LOCAL_CURRENCY': SETTINGS[self.title][supplier]['Currency'][1].value,
}
digikey_settings = {**settings_from_file, **updated_settings}
config_interface.dump_file(digikey_settings, global_settings.CONFIG_DIGIKEY_API)
Expand Down
10 changes: 6 additions & 4 deletions kintree/search/automationdirect_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def search_timeout(timeout=10):
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
else:
part = None
except Exception as e:
cprint(f'[INFO]\tError: fetch_part_info(): {repr(e)}')
part = None
Expand Down Expand Up @@ -146,7 +148,7 @@ def search_timeout(timeout=10):
parameter_name = parameter_name.replace('/', '')
parameter_value = attribute_list[1]
try:
html_li_list = re.split("</?\s*[a-z-][^>]*\s*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);)", parameter_value)
html_li_list = re.split(r"</?\s*[a-z-][^>]*\s*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);)", parameter_value)
cleaned_html_li_list = list(filter(None, html_li_list))
parameter_value = ', '.join(cleaned_html_li_list)
except Exception as e:
Expand All @@ -156,7 +158,7 @@ def search_timeout(timeout=10):
# Nominal Input Voltage gives range min-max, parse it out to put in min/max params
if parameter_name == "Nominal Input Voltage":
if parameter_value.count('-') == 1:
parameter_value = re.sub('[^\d-]+', '', parameter_value)
parameter_value = re.sub(r'[^\d-]+', '', parameter_value)
values_list = parameter_value.split('-')
min_value = min(values_list)
max_value = max(values_list)
Expand All @@ -169,7 +171,7 @@ def search_timeout(timeout=10):
# Nominal Output Voltage gives range min-max, parse it out to put in min/max params
if parameter_name == "Nominal Output Voltage":
if parameter_value.count('-') == 1:
parameter_value = re.sub('[^\d-]+', '', parameter_value)
parameter_value = re.sub(r'[^\d-]+', '', parameter_value)
values_list = parameter_value.split('-')
min_value = min(values_list)
max_value = max(values_list)
Expand All @@ -189,7 +191,7 @@ def search_timeout(timeout=10):

# Parse out ordering attributes
pricing_attributes = {}
price_per_unit = part[price_key]
price_per_unit = part.get(price_key, '0')
try:
for attribute in part[ordering_attributes]:
attribute = attribute.split(':')
Expand Down
Loading

0 comments on commit 070f29a

Please sign in to comment.