From 1e8326b24447447723a0f7de6f907aa8fc6adb08 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 27 Sep 2022 10:48:19 -0400 Subject: [PATCH 01/17] Base for upgrade to 0.6 --- README.md | 13 ++++ kintree/__init__.py | 2 +- .../kicad/templates/eeprom-sot23.kicad_sym | 59 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 kintree/kicad/templates/eeprom-sot23.kicad_sym diff --git a/README.md b/README.md index 1f9a1712..6e7fe81a 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,19 @@ Lastly, a new page will open with a "You may now close this window." message, pr

+#### Part Parameters + +Ki-nTree uses **supplier** parameters to populate **InvenTree** parameters. In order to match between supplier and InvenTree, user need to setup the config file `~/.config/kintree/user/supplier_parameters.yaml` with the following mapping for each category: +``` yaml +CATEGORY_NAME: + INVENTREE_PARAMETER_NAME: + - SUPPLIER_1_PARAMETER_NAME_1 + - SUPPLIER_1_PARAMETER_NAME_2 + - SUPPLIER_2_PARAMETER_NAME_1 +``` + +Refer to [this file](https://github.com/sparkmicro/Ki-nTree/blob/main/kintree/config/search/supplier_parameters.yaml) as a starting point / example. + #### Part Number Search Ki-nTree currently supports APIs for the following electronics suppliers: Digi-Key, Mouser and LCSC. diff --git a/kintree/__init__.py b/kintree/__init__.py index a1765cf7..bd89e732 100644 --- a/kintree/__init__.py +++ b/kintree/__init__.py @@ -4,7 +4,7 @@ # VERSION INFORMATION version_info = { 'MAJOR_REVISION': 0, - 'MINOR_REVISION': 5, + 'MINOR_REVISION': 6, 'RELEASE_STATUS': 99, # Dev = 99 } diff --git a/kintree/kicad/templates/eeprom-sot23.kicad_sym b/kintree/kicad/templates/eeprom-sot23.kicad_sym new file mode 100644 index 00000000..d7006f4e --- /dev/null +++ b/kintree/kicad/templates/eeprom-sot23.kicad_sym @@ -0,0 +1,59 @@ +(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor) + (symbol "IPN" (in_bom yes) (on_board yes) + (property "Reference" "U" (id 0) (at 0 8.89 0) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "IPN" (id 1) (at 0 -11.43 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "Footprint" (id 2) (at 0 -19.05 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "inventree_url" (id 3) (at 0 -21.59 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Manufacturer" "Manufacturer" (id 4) (at 0 -13.97 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Manufacturer Part Number" "MPN" (id 5) (at 0 -16.51 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Part Number" "Value" (id 6) (at 0 -8.89 0) + (effects (font (size 1.27 1.27))) + ) + (property "ki_keywords" "keywords" (id 7) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "description" (id 8) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "IPN_0_1" + (rectangle (start -5.08 7.62) (end 5.08 -7.62) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type background)) + ) + ) + (symbol "IPN_1_1" + (pin passive line (at -7.62 0 0) (length 2.54) + (name "SCL" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin power_in line (at 7.62 -5.08 180) (length 2.54) + (name "VSS" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at -7.62 -5.08 0) (length 2.54) + (name "SDA" (effects (font (size 1.27 1.27)))) + (number "3" (effects (font (size 1.27 1.27)))) + ) + (pin power_in line (at -7.62 5.08 0) (length 2.54) + (name "VCC" (effects (font (size 1.27 1.27)))) + (number "4" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 7.62 5.08 180) (length 2.54) + (name "WP" (effects (font (size 1.27 1.27)))) + (number "5" (effects (font (size 1.27 1.27)))) + ) + ) + ) +) From 92d7ea2116b86867395ffebaed322f630843b254 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 27 Sep 2022 12:59:48 -0400 Subject: [PATCH 02/17] Refactored how kicad/inventree flags are managed, added alternate flag --- README.md | 2 +- kintree/config/inventree/inventree_dev.yaml | 1 - kintree/config/inventree/inventree_prod.yaml | 1 - kintree/config/inventree/inventree_test.yaml | 6 -- kintree/config/settings.py | 74 ++++++++------------ kintree/config/settings/general.yaml | 6 +- kintree/kintree_gui.py | 7 +- run_tests.py | 6 +- 8 files changed, 44 insertions(+), 59 deletions(-) delete mode 100644 kintree/config/inventree/inventree_test.yaml diff --git a/README.md b/README.md index 6e7fe81a..571b59af 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ Lastly, a new page will open with a "You may now close this window." message, pr #### Part Parameters -Ki-nTree uses **supplier** parameters to populate **InvenTree** parameters. In order to match between supplier and InvenTree, user need to setup the config file `~/.config/kintree/user/supplier_parameters.yaml` with the following mapping for each category: +Ki-nTree uses **supplier** parameters to populate **InvenTree** parameters. In order to match between supplier and InvenTree, users need to setup the config file `~/.config/kintree/user/supplier_parameters.yaml` with the following mapping for each category: ``` yaml CATEGORY_NAME: INVENTREE_PARAMETER_NAME: diff --git a/kintree/config/inventree/inventree_dev.yaml b/kintree/config/inventree/inventree_dev.yaml index 27fbbc0c..3d665a61 100644 --- a/kintree/config/inventree/inventree_dev.yaml +++ b/kintree/config/inventree/inventree_dev.yaml @@ -2,5 +2,4 @@ PASSWORD: !!binary | '' SERVER_ADDRESS: '' USERNAME: '' -ENABLE: false INVENTREE_DEFAULT_REV: 'A' \ No newline at end of file diff --git a/kintree/config/inventree/inventree_prod.yaml b/kintree/config/inventree/inventree_prod.yaml index 27fbbc0c..3d665a61 100644 --- a/kintree/config/inventree/inventree_prod.yaml +++ b/kintree/config/inventree/inventree_prod.yaml @@ -2,5 +2,4 @@ PASSWORD: !!binary | '' SERVER_ADDRESS: '' USERNAME: '' -ENABLE: false INVENTREE_DEFAULT_REV: 'A' \ No newline at end of file diff --git a/kintree/config/inventree/inventree_test.yaml b/kintree/config/inventree/inventree_test.yaml deleted file mode 100644 index 27fbbc0c..00000000 --- a/kintree/config/inventree/inventree_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -PASSWORD: !!binary | - '' -SERVER_ADDRESS: '' -USERNAME: '' -ENABLE: false -INVENTREE_DEFAULT_REV: 'A' \ No newline at end of file diff --git a/kintree/config/settings.py b/kintree/config/settings.py index e8f9350f..18155356 100644 --- a/kintree/config/settings.py +++ b/kintree/config/settings.py @@ -112,6 +112,13 @@ def load_user_config(): AUTOMATIC_SUBCATEGORY_CREATE = CONFIG_GENERAL.get('AUTOMATIC_SUBCATEGORY_CREATE', False) AUTOMATIC_BROWSER_OPEN = CONFIG_GENERAL.get('AUTOMATIC_BROWSER_OPEN', False) DEFAULT_SUPPLIER = CONFIG_GENERAL.get('DEFAULT_SUPPLIER', 'Digi-Key') +# Load enable flags +try: + ENABLE_KICAD = CONFIG_GENERAL.get('ENABLE_KICAD', False) + ENABLE_INVENTREE = CONFIG_GENERAL.get('ENABLE_INVENTREE', False) + ENABLE_ALTERNATE = CONFIG_GENERAL.get('ENABLE_ALTERNATE', False) +except TypeError: + pass # Supported suppliers APIs SUPPORTED_SUPPLIERS_API = ['Digi-Key', 'Mouser', 'LCSC'] @@ -179,33 +186,18 @@ def load_kicad_settings(): global KICAD_SYMBOLS_PATH global KICAD_TEMPLATES_PATH global KICAD_FOOTPRINTS_PATH - global ENABLE_KICAD kicad_user_settings = config_interface.load_file(CONFIG_KICAD, silent=False) if kicad_user_settings: KICAD_SYMBOLS_PATH = kicad_user_settings.get('KICAD_SYMBOLS_PATH', None) KICAD_TEMPLATES_PATH = kicad_user_settings.get('KICAD_TEMPLATES_PATH', None) KICAD_FOOTPRINTS_PATH = kicad_user_settings.get('KICAD_FOOTPRINTS_PATH', None) - ENABLE_KICAD = kicad_user_settings.get('KICAD_ENABLE', None) # Load kicad settings load_kicad_settings() -# Enable flag -def set_kicad_enable_flag(value: bool, save=False): - global ENABLE_KICAD - ENABLE_KICAD = value - if save: - global CONFIG_KICAD - kicad_user_settings = config_interface.load_inventree_user_settings( - CONFIG_KICAD) - kicad_user_settings['KICAD_ENABLE'] = value - config_interface.dump_file(kicad_user_settings, CONFIG_KICAD) - return - - def set_default_supplier(value: str, save=False): global DEFAULT_SUPPLIER DEFAULT_SUPPLIER = value @@ -241,13 +233,11 @@ def set_default_supplier(value: str, save=False): # INVENTREE class Environment(Enum): ''' - Local Development/Testing: TESTING Server/Remote Development: DEVELOPMENT Server/Remote Production: PRODUCTION ''' - TESTING = 0 - DEVELOPMENT = 1 - PRODUCTION = 2 + DEVELOPMENT = 0 + PRODUCTION = 1 # Pick environment @@ -262,35 +252,12 @@ class Environment(Enum): # Load correct user file if environment == Environment.PRODUCTION.value: CONFIG_INVENTREE = os.path.join(CONFIG_USER_FILES, 'inventree_prod.yaml') -elif environment == Environment.DEVELOPMENT.value: - CONFIG_INVENTREE = os.path.join(CONFIG_USER_FILES, 'inventree_dev.yaml') else: - CONFIG_INVENTREE = os.path.join(CONFIG_USER_FILES, 'inventree_test.yaml') + CONFIG_INVENTREE = os.path.join(CONFIG_USER_FILES, 'inventree_dev.yaml') # Load user settings inventree_settings = config_interface.load_inventree_user_settings(CONFIG_INVENTREE) -# Enable flag -try: - ENABLE_INVENTREE = inventree_settings.get('ENABLE', False) -except TypeError: - pass - - -def set_inventree_enable_flag(value: bool, save=False): - global ENABLE_INVENTREE - ENABLE_INVENTREE = value - if save: - global CONFIG_INVENTREE - inventree_settings = config_interface.load_inventree_user_settings(CONFIG_INVENTREE) - inventree_settings['ENABLE'] = value - config_interface.save_inventree_user_settings(enable=inventree_settings['ENABLE'], - server=inventree_settings.get('SERVER_ADDRESS', None), - username=inventree_settings.get('USERNAME', None), - password=inventree_settings.get('PASSWORD', None), - user_config_path=CONFIG_INVENTREE) - return - # Server settings def load_inventree_settings(): @@ -333,3 +300,24 @@ def load_inventree_settings(): 'supplier_link': None, 'parameters': {}, } + + +# Enable flags +def set_enable_flags(values: list): + global CONFIG_GENERAL + global ENABLE_KICAD + global ENABLE_INVENTREE + global ENABLE_ALTERNATE + + ENABLE_KICAD = values[0] + ENABLE_INVENTREE = values[1] + ENABLE_ALTERNATE = values[2] + + # Save user settings + user_settings = CONFIG_GENERAL + user_settings['ENABLE_KICAD'] = ENABLE_KICAD + user_settings['ENABLE_INVENTREE'] = ENABLE_INVENTREE + user_settings['ENABLE_ALTERNATE'] = ENABLE_ALTERNATE + config_interface.dump_file(user_settings, os.path.join(CONFIG_USER_FILES, 'general.yaml')) + + return diff --git a/kintree/config/settings/general.yaml b/kintree/config/settings/general.yaml index c56b4e04..05140873 100644 --- a/kintree/config/settings/general.yaml +++ b/kintree/config/settings/general.yaml @@ -1,3 +1,7 @@ AUTOMATIC_SUBCATEGORY_CREATE: false AUTOMATIC_BROWSER_OPEN: true -INVENTREE_ENV: null \ No newline at end of file +INVENTREE_ENV: null +DEFAULT_SUPPLIER: Digi-Key +ENABLE_KICAD: false +ENABLE_INVENTREE: false +ENABLE_ALTERNATE: false \ No newline at end of file diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index 278297dd..16a9d2e6 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -942,6 +942,7 @@ def main(): [ sg.Checkbox('KiCad', enable_events=True, default=settings.ENABLE_KICAD, key='enable_kicad'), sg.Checkbox('InvenTree', enable_events=True, default=settings.ENABLE_INVENTREE, key='enable_inventree'), + sg.Checkbox('Alternate', enable_events=True, default=settings.ENABLE_ALTERNATE, key='enable_alternate'), ], [ sg.Button('CREATE', size=(58, 1)), @@ -976,8 +977,10 @@ def main(): elif event == 'KiCad': kicad_settings_window() elif 'enable' in event: - settings.set_inventree_enable_flag(values['enable_inventree'], save=True) - settings.set_kicad_enable_flag(values['enable_kicad'], save=True) + write_values = [values['enable_kicad'], + values['enable_inventree'], + values['enable_alternate'], ] + settings.set_enable_flags(write_values) elif event == 'Custom Part': CREATE_CUSTOM = True elif 'supplier' in event: diff --git a/run_tests.py b/run_tests.py index 43bcbcf2..ae045492 100644 --- a/run_tests.py +++ b/run_tests.py @@ -63,10 +63,8 @@ def check_result(status: str, new_part: bool) -> bool: # Enable test mode settings.enable_test_mode() -# Enable InvenTree -settings.set_inventree_enable_flag(True, save=True) -# Enable KiCad -settings.set_kicad_enable_flag(True, save=True) +# Enable InvenTree and KiCad +settings.set_enable_flags([True, True, False]) # Load user configuration files settings.load_user_config() # Set path to test libraries From eb58b97313cdbfd321930bd249f641e800abcbd6 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 27 Sep 2022 13:51:50 -0400 Subject: [PATCH 03/17] Tests fixes --- .github/workflows/test_deploy.yaml | 2 +- tests/files/{inventree_test.yaml => inventree_dev.yaml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/files/{inventree_test.yaml => inventree_dev.yaml} (100%) diff --git a/.github/workflows/test_deploy.yaml b/.github/workflows/test_deploy.yaml index 391a9d3e..e1464e49 100644 --- a/.github/workflows/test_deploy.yaml +++ b/.github/workflows/test_deploy.yaml @@ -74,7 +74,7 @@ jobs: run: | invoke install mkdir -p ~/.config/kintree/user/ && mkdir -p ~/.config/kintree/cache/search/ - cp tests/files/inventree_test.yaml ~/.config/kintree/user/ + cp tests/files/inventree_dev.yaml ~/.config/kintree/user/ cp tests/files/results.tgz ~/.config/kintree/cache/search/ cd ~/.config/kintree/cache/search/ && tar xvf results.tgz && cd - - name: Digi-Key API setup diff --git a/tests/files/inventree_test.yaml b/tests/files/inventree_dev.yaml similarity index 100% rename from tests/files/inventree_test.yaml rename to tests/files/inventree_dev.yaml From e348427f93d2c505779ec620181870674d1b7bbe Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 27 Sep 2022 15:44:55 -0400 Subject: [PATCH 04/17] Updated build task and dependencies --- README.md | 8 +- poetry.lock | 308 ++++++++++++++++++++++++++++++++++++------------- pyproject.toml | 6 +- tasks.py | 11 +- 4 files changed, 239 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 571b59af..fe969a7d 100644 --- a/README.md +++ b/README.md @@ -200,11 +200,11 @@ $ python -m kintree_gui 1. Make sure you followed the previous installation steps, then run: ``` bash $ poetry build -Building kintree (0.4.99) +Building kintree (0.6.99) - Building sdist - - Built kintree-0.4.99.tar.gz + - Built kintree-0.6.99.tar.gz - Building wheel - - Built kintree-0.4.99-py3-none-any.whl + - Built kintree-0.6.99-py3-none-any.whl ``` 2. Exit the virtual environment (`Ctrl + D` on Linux; you can also close the terminal and reopen it in the same folder). @@ -213,7 +213,7 @@ Building kintree (0.4.99) step. For example: ```bash -pip install dist/kintree-0.4.99-py3-none-any.whl +pip install dist/kintree-0.6.99-py3-none-any.whl ``` 3. You can now start Ki-nTree by typing `kintree` in the terminal, provided diff --git a/poetry.lock b/poetry.lock index 3b970b2c..67dd90b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -12,7 +12,7 @@ tldextract = "*" [[package]] name = "certifi" -version = "2022.6.15" +version = "2022.9.24" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -31,7 +31,7 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "2.1.0" +version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -61,7 +61,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.4.3" +version = "6.4.4" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -88,7 +88,7 @@ yaml = ["PyYAML (>=3.10)"] [[package]] name = "cryptography" -version = "37.0.4" +version = "38.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -99,11 +99,11 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] -sdist = ["setuptools_rust (>=0.11.4)"] +sdist = ["setuptools-rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] +test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"] [[package]] name = "decorator" @@ -172,7 +172,7 @@ speedup = ["python-levenshtein (>=0.12)"] [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -188,7 +188,7 @@ python-versions = ">=3.5" [[package]] name = "inventree" -version = "0.8.1" +version = "0.8.3" description = "Python interface for InvenTree inventory management system" category = "main" optional = false @@ -237,22 +237,22 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] -name = "pyopenssl" -version = "22.0.0" +name = "pyOpenSSL" +version = "22.1.0" description = "Python wrapper module around the OpenSSL library" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -cryptography = ">=35.0" +cryptography = ">=38.0.0,<39" [package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] +docs = ["sphinx (!=5.2.0,!=5.2.0.post0)", "sphinx-rtd-theme"] test = ["flaky", "pretend", "pytest (>=3.0.1)"] [[package]] -name = "pysimplegui" +name = "PySimpleGUI" version = "4.60.3" description = "Python GUIs for Humans. Launched in 2018. It's 2022 & PySimpleGUI is an ACTIVE & supported project. Super-simple to create custom GUI's. 325+ Demo programs & Cookbook for rapid start. Extensive documentation. Main docs at www.PySimpleGUI.org. Fun & your success are the focus. Examples using Machine Learning (GUI, OpenCV Integration), Rainmeter Style Desktop Widgets, Matplotlib + Pyplot, PIL support, add GUI to command line scripts, PDF & Image Viewers. Great for beginners & advanced GUI programmers." category = "main" @@ -260,15 +260,18 @@ optional = false python-versions = "*" [[package]] -name = "python-levenshtein" +name = "python-Levenshtein" version = "0.12.2" description = "Python extension for computing string edit distances and similarities." category = "main" optional = false python-versions = "*" +[package.dependencies] +setuptools = "*" + [[package]] -name = "pyyaml" +name = "PyYAML" version = "5.4.1" description = "YAML parser and emitter for Python" category = "main" @@ -316,6 +319,19 @@ python-versions = "*" [package.dependencies] six = ">=1.7.0" +[[package]] +name = "setuptools" +version = "65.4.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + [[package]] name = "six" version = "1.16.0" @@ -340,15 +356,15 @@ requests-file = ">=1.4" [[package]] name = "urllib3" -version = "1.26.11" +version = "1.26.12" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -363,7 +379,7 @@ python-versions = ">=3.4" decorator = ">=3.4.0" [package.extras] -test = ["pytest (>=2.2.3)", "flake8 (>=2.4.0)", "isort (>=4.2.2)"] +test = ["flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)"] [[package]] name = "wrapt" @@ -383,59 +399,172 @@ certauth = [ {file = "certauth-1.3.0-py2.py3-none-any.whl", hash = "sha256:f84b8c7075d0e445614d5ec4662056511453f19228cf4fcf8278cccae17b316b"}, {file = "certauth-1.3.0.tar.gz", hash = "sha256:7862d5deff0b33d2fb28d36861ba63d91c82d700bfdfc4bd848a8711ca72b8fb"}, ] -certifi = [] -cffi = [] -charset-normalizer = [] +certifi = [ + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, +] +cffi = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] -colorama = [] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] coverage = [ - {file = "coverage-6.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f50d3a822947572496ea922ee7825becd8e3ae6fbd2400cd8236b7d64b17f285"}, - {file = "coverage-6.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5191d53afbe5b6059895fa7f58223d3751c42b8101fb3ce767e1a0b1a1d8f87"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04010af3c06ce2bfeb3b1e4e05d136f88d88c25f76cd4faff5d1fd84d11581ea"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6630d8d943644ea62132789940ca97d05fac83f73186eaf0930ffa715fbdab6b"}, - {file = "coverage-6.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05de0762c1caed4a162b3e305f36cf20a548ff4da0be6766ad5c870704be3660"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e3a41aad5919613483aad9ebd53336905cab1bd6788afd3995c2a972d89d795"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a2738ba1ee544d6f294278cfb6de2dc1f9a737a780469b5366e662a218f806c3"}, - {file = "coverage-6.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a0d2df4227f645a879010461df2cea6b7e3fb5a97d7eafa210f7fb60345af9e8"}, - {file = "coverage-6.4.3-cp310-cp310-win32.whl", hash = "sha256:73a10939dc345460ca0655356a470dd3de9759919186a82383c87b6eb315faf2"}, - {file = "coverage-6.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:53c8edd3b83a4ddba3d8c506f1359401e7770b30f2188f15c17a338adf5a14db"}, - {file = "coverage-6.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1eda5cae434282712e40b42aaf590b773382afc3642786ac3ed39053973f61f"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59fc88bc13e30f25167e807b8cad3c41b7218ef4473a20c86fd98a7968733083"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75314b00825d70e1e34b07396e23f47ed1d4feedc0122748f9f6bd31a544840"}, - {file = "coverage-6.4.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52f8b9fcf3c5e427d51bbab1fb92b575a9a9235d516f175b24712bcd4b5be917"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5a559aab40c716de80c7212295d0dc96bc1b6c719371c20dd18c5187c3155518"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:306788fd019bb90e9cbb83d3f3c6becad1c048dd432af24f8320cf38ac085684"}, - {file = "coverage-6.4.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:920a734fe3d311ca01883b4a19aa386c97b82b69fbc023458899cff0a0d621b9"}, - {file = "coverage-6.4.3-cp37-cp37m-win32.whl", hash = "sha256:ab9ef0187d6c62b09dec83a84a3b94f71f9690784c84fd762fb3cf2d2b44c914"}, - {file = "coverage-6.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:39ebd8e120cb77a06ee3d5fc26f9732670d1c397d7cd3acf02f6f62693b89b80"}, - {file = "coverage-6.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc698580216050b5f4a34d2cdd2838b429c53314f1c4835fab7338200a8396f2"}, - {file = "coverage-6.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:877ee5478fd78e100362aed56db47ccc5f23f6e7bb035a8896855f4c3e49bc9b"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:555a498999c44f5287cc95500486cd0d4f021af9162982cbe504d4cb388f73b5"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff095a5aac7011fdb51a2c82a8fae9ec5211577f4b764e1e59cfa27ceeb1b59"}, - {file = "coverage-6.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5de1e9335e2569974e20df0ce31493d315a830d7987e71a24a2a335a8d8459d3"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7856ea39059d75f822ff0df3a51ea6d76307c897048bdec3aad1377e4e9dca20"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:411fdd9f4203afd93b056c0868c8f9e5e16813e765de962f27e4e5798356a052"}, - {file = "coverage-6.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cdf7b83f04a313a21afb1f8730fe4dd09577fefc53bbdfececf78b2006f4268e"}, - {file = "coverage-6.4.3-cp38-cp38-win32.whl", hash = "sha256:ab2b1a89d2bc7647622e9eaf06128a5b5451dccf7c242deaa31420b055716481"}, - {file = "coverage-6.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:0e34247274bde982bbc613894d33f9e36358179db2ed231dd101c48dd298e7b0"}, - {file = "coverage-6.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b104b6b1827d6a22483c469e3983a204bcf9c6bf7544bf90362c4654ebc2edf3"}, - {file = "coverage-6.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adf1a0d272633b21d645dd6e02e3293429c1141c7d65a58e4cbcd592d53b8e01"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff9832434a9193fbd716fbe05f9276484e18d26cc4cf850853594bb322807ac3"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:923f9084d7e1d31b5f74c92396b05b18921ed01ee5350402b561a79dce3ea48d"}, - {file = "coverage-6.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d64304acf79766e650f7acb81d263a3ea6e2d0d04c5172b7189180ff2c023c"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fc294de50941d3da66a09dca06e206297709332050973eca17040278cb0918ff"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a42eaaae772f14a5194f181740a67bfd48e8806394b8c67aa4399e09d0d6b5db"}, - {file = "coverage-6.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4822327b35cb032ff16af3bec27f73985448f08e874146b5b101e0e558b613dd"}, - {file = "coverage-6.4.3-cp39-cp39-win32.whl", hash = "sha256:f217850ac0e046ede611312703423767ca032a7b952b5257efac963942c055de"}, - {file = "coverage-6.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0a84376e4fd13cebce2c0ef8c2f037929c8307fb94af1e5dbe50272a1c651b5d"}, - {file = "coverage-6.4.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:068d6f2a893af838291b8809c876973d885543411ea460f3e6886ac0ee941732"}, - {file = "coverage-6.4.3.tar.gz", hash = "sha256:ec2ae1f398e5aca655b7084392d23e80efb31f7a660d2eecf569fb9f79b3fb94"}, -] -coveralls = [] -cryptography = [] + {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, + {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, + {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, + {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, + {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, + {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, + {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, + {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, + {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, + {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, + {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, + {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, + {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, + {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, + {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, + {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, +] +coveralls = [ + {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"}, + {file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"}, +] +cryptography = [ + {file = "cryptography-38.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f"}, + {file = "cryptography-38.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd"}, + {file = "cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6"}, + {file = "cryptography-38.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a"}, + {file = "cryptography-38.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294"}, + {file = "cryptography-38.0.1-cp36-abi3-win32.whl", hash = "sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0"}, + {file = "cryptography-38.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a"}, + {file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d"}, + {file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9"}, + {file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d"}, + {file = "cryptography-38.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818"}, + {file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6"}, + {file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750"}, + {file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013"}, + {file = "cryptography-38.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5"}, + {file = "cryptography-38.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61"}, + {file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac"}, + {file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb"}, + {file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a"}, + {file = "cryptography-38.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b"}, + {file = "cryptography-38.0.1.tar.gz", hash = "sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7"}, +] decorator = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, @@ -460,14 +589,17 @@ fuzzywuzzy = [ {file = "fuzzywuzzy-0.18.0.tar.gz", hash = "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8"}, ] idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, ] -inventree = [] +inventree = [ + {file = "inventree-0.8.3-py2.py3-none-any.whl", hash = "sha256:ebfff738e877e3dae125f1d2f4f25b667be9a6d173abb77764e23b5d99c67b6e"}, + {file = "inventree-0.8.3.tar.gz", hash = "sha256:424ad53658267e497f26b39a02a9566b285ba7aa2cc27c18b8cfcac9ba8714f5"}, +] invoke = [ {file = "invoke-1.7.1-py3-none-any.whl", hash = "sha256:2dc975b4f92be0c0a174ad2d063010c8a1fdb5e9389d69871001118b4fcac4fb"}, {file = "invoke-1.7.1.tar.gz", hash = "sha256:7b6deaf585eee0a848205d0b8c0014b9bf6f287a8eb798818a642dff1df14b19"}, @@ -503,15 +635,18 @@ pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -pyopenssl = [ - {file = "pyOpenSSL-22.0.0-py2.py3-none-any.whl", hash = "sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0"}, - {file = "pyOpenSSL-22.0.0.tar.gz", hash = "sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf"}, +pyOpenSSL = [ + {file = "pyOpenSSL-22.1.0-py3-none-any.whl", hash = "sha256:b28437c9773bb6c6958628cf9c3bebe585de661dba6f63df17111966363dd15e"}, + {file = "pyOpenSSL-22.1.0.tar.gz", hash = "sha256:7a83b7b272dd595222d672f5ce29aa030f1fb837630ef229f62e72e395ce8968"}, ] -pysimplegui = [] -python-levenshtein = [ +PySimpleGUI = [ + {file = "PySimpleGUI-4.60.3-py3-none-any.whl", hash = "sha256:dc62d5722c0a46d709bc8706590b5d47593bd2ed8c1d306ecfee6c05fb6711f5"}, + {file = "PySimpleGUI-4.60.3.tar.gz", hash = "sha256:75ec46694dc975c0e46be8c57a774e038433b53095821d67be3b221aca3fd68d"}, +] +python-Levenshtein = [ {file = "python-Levenshtein-0.12.2.tar.gz", hash = "sha256:dc2395fbd148a1ab31090dd113c366695934b9e85fe5a4b2a032745efd0346f6"}, ] -pyyaml = [ +PyYAML = [ {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, @@ -542,7 +677,10 @@ pyyaml = [ {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, ] -requests = [] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] requests-file = [ {file = "requests-file-1.5.1.tar.gz", hash = "sha256:07d74208d3389d01c38ab89ef403af0cfec63957d53a0081d8eca738d0247d8e"}, {file = "requests_file-1.5.1-py2.py3-none-any.whl", hash = "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953"}, @@ -550,12 +688,22 @@ requests-file = [ retrying = [ {file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"}, ] +setuptools = [ + {file = "setuptools-65.4.0-py3-none-any.whl", hash = "sha256:c2d2709550f15aab6c9110196ea312f468f41cd546bceb24127a1be6fdcaeeb1"}, + {file = "setuptools-65.4.0.tar.gz", hash = "sha256:a8f6e213b4b0661f590ccf40de95d28a177cd747d098624ad3f69c40287297e9"}, +] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -tldextract = [] -urllib3 = [] +tldextract = [ + {file = "tldextract-3.3.1-py3-none-any.whl", hash = "sha256:35a0260570e214d8d3cfeeb403992fe9e2b686925f63c9b03c5933408ac2aa5a"}, + {file = "tldextract-3.3.1.tar.gz", hash = "sha256:fe15ac3205e5a25b61689369f98cb45c7778a8f2af113d7c11559ece5195f2d6"}, +] +urllib3 = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] validators = [ {file = "validators-0.19.0.tar.gz", hash = "sha256:dec45f4381f042f1e705cfa74949505b77f1e27e8b05409096fee8152c839cbe"}, ] diff --git a/pyproject.toml b/pyproject.toml index 33205ada..020ca2dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "kintree" -version = "0.5.99" # placeholder +version = "0.6.99" # placeholder description = "Fast part creation in KiCad and InvenTree" authors = ["eeintech "] maintainers = ["eeintech ", "randrej "] @@ -14,10 +14,10 @@ keywords = ["inventree", "kicad", "component", "part", "create"] python = ">=3.8,<3.11" digikey-api = "^1.0.0" fuzzywuzzy = "^0.18.0" -inventree = "^0.8.1" +inventree = "^0.8.3" multiprocess = "^0.70.13" mouser = "^0.1.1" -PySimpleGUI = "^4.60.1" +PySimpleGUI = "^4.60.3" PyYAML = "^5.4.1" validators = "^0.19.0" wrapt = "^1.14.1" diff --git a/tasks.py b/tasks.py index cb6fdbdb..5fe7ec3c 100644 --- a/tasks.py +++ b/tasks.py @@ -63,19 +63,16 @@ def clean(c): @task(pre=[clean]) def build(c): """ - Build Ki-nTree into executable file + Build Ki-nTree into dist/wheel """ try: - c.run('pip show pyinstaller', hide=True) + c.run('pip show poetry', hide=True) except UnexpectedExit: - c.run('pip install -U pyinstaller', hide=True) + c.run('pip install -U poetry', hide=True) - # Uninstall typing - c.run('pip uninstall typing -y', hide=True) - cprint('[MAIN]\tBuilding Ki-nTree GUI into "dist" directory') - c.run('pyinstaller --clean --onefile -p kintree/kicad kintree_gui.py', hide=True) + c.run('poetry build', hide=True) @task From 0a5d6683deedd0c04896389bbb3731c69c231e9c Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 27 Sep 2022 17:40:34 -0400 Subject: [PATCH 05/17] Started alternate flow implementation --- kintree/config/settings.py | 2 +- kintree/kintree_gui.py | 59 ++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/kintree/config/settings.py b/kintree/config/settings.py index 18155356..b638412b 100644 --- a/kintree/config/settings.py +++ b/kintree/config/settings.py @@ -247,7 +247,7 @@ class Environment(Enum): try: environment = int(environment) except TypeError: - environment = Environment.TESTING.value + environment = 0 # Load correct user file if environment == Environment.PRODUCTION.value: diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index 16a9d2e6..fb6872b6 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -320,6 +320,41 @@ def kicad_settings_window(): return +def alternate_window() -> dict: + ''' Alternate supplier window ''' + + alternate_layout = [ + [ + sg.Text('InvenTree IPN', size=gui_global['label_size']), + sg.InputText('', key='original_part_ipn'), + sg.Text('InvenTree ID', size=gui_global['label_size']), + sg.InputText('', key='original_part_id'), + ], + [ + sg.Button('Continue', size=(15, 1)), + ], + ] + alternate_window = sg.Window( + 'Create alternate of...', + alternate_layout, + font=gui_global['font'], + location=gui_global['location'], + ) + + while True: + event, values = alternate_window.read() + + if event == sg.WIN_CLOSED: + alternate_window.close() + return + else: + alternate_window.close() + return { + values['original_part_ipn'], + values['original_part_id'], + } + + def snapeda_window(part_number: str): ''' Display SnapEDA API results ''' @@ -420,7 +455,7 @@ def snapeda_window(part_number: str): snapeda_window.close() -def part_user_form(part_data: dict, custom=False) -> dict: +def part_user_form(part_data: dict, alternate=False, custom=False) -> dict: ''' User part data form ''' user_values = {} @@ -428,6 +463,10 @@ def part_user_form(part_data: dict, custom=False) -> dict: input_keys = [] for key, value in part_data.items(): + if alternate: + if key in ['name', 'description', 'revision', 'keywords', 'image']: + continue + label = key.replace('_', ' ').title() part_user_form_layout.append([ @@ -435,7 +474,7 @@ def part_user_form(part_data: dict, custom=False) -> dict: sg.InputText(value, size=(45, 1), key=key), ]) input_keys.append(key) - + if custom: part_user_form_layout.append([sg.Button('CREATE', size=(64, 1)), ]) window_title = 'Add Custom Part' @@ -942,7 +981,7 @@ def main(): [ sg.Checkbox('KiCad', enable_events=True, default=settings.ENABLE_KICAD, key='enable_kicad'), sg.Checkbox('InvenTree', enable_events=True, default=settings.ENABLE_INVENTREE, key='enable_inventree'), - sg.Checkbox('Alternate', enable_events=True, default=settings.ENABLE_ALTERNATE, key='enable_alternate'), + sg.Checkbox('Alternate', enable_events=True, default=settings.ENABLE_ALTERNATE, key='enable_alternate', disabled=not(settings.ENABLE_INVENTREE)), ], [ sg.Button('CREATE', size=(58, 1)), @@ -979,7 +1018,11 @@ def main(): elif 'enable' in event: write_values = [values['enable_kicad'], values['enable_inventree'], - values['enable_alternate'], ] + values['enable_alternate'] if values['enable_inventree'] and not values['enable_kicad'] else False, ] + if values['enable_inventree'] and not values['enable_kicad']: + window.find_element('enable_alternate').Update(disabled=False) + else: + window.find_element('enable_alternate').Update(disabled=True) settings.set_enable_flags(write_values) elif event == 'Custom Part': CREATE_CUSTOM = True @@ -1077,10 +1120,16 @@ def main(): font=gui_global['font'], location=gui_global['location']) + + if settings.ENABLE_ALTERNATE: + cprint('Warning: Alternate') + # Do we have form data? if part_supplier_form: # Open part form - part_user_info = part_user_form(part_data=part_supplier_form, custom=CREATE_CUSTOM) + part_user_info = part_user_form(part_data=part_supplier_form, + alternate=settings.ENABLE_ALTERNATE, + custom=CREATE_CUSTOM) # Stitch back categories and parameters try: From c71c27f725286bf32832a4649989bc3e34bd90a8 Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 31 Oct 2022 13:38:42 -0400 Subject: [PATCH 06/17] Added database check for original part --- kintree/database/inventree_api.py | 40 +++++++++ kintree/database/inventree_interface.py | 9 ++ kintree/kintree_gui.py | 113 ++++++++++++++---------- 3 files changed, 115 insertions(+), 47 deletions(-) diff --git a/kintree/database/inventree_api.py b/kintree/database/inventree_api.py index 8ca0a378..0a52297f 100644 --- a/kintree/database/inventree_api.py +++ b/kintree/database/inventree_api.py @@ -109,6 +109,46 @@ def set_part_number(part_id: int, ipn: str) -> bool: return False +def get_part_id_from_ipn(part_ipn='') -> int: + ''' Get Part ID from Part IPN ''' + global inventree_api + + parts = Part.list(inventree_api) + + for part in parts: + if part.IPN == part_ipn: + return part.pk + + # No part found + return 0 + + +def fetch_part_id(part_id='', part_ipn='') -> int: + ''' Fetch part information from database ''' + from requests.exceptions import HTTPError + global inventree_api + + part = 0 + if part_id: + try: + part = Part(inventree_api, part_id) + except TypeError: + # Part ID is invalid (eg. decimal value) + cprint('[TREE] Error: Part ID type is invalid') + except ValueError: + # Part ID is not a positive integer + cprint('[TREE] Error: Part ID must be positive') + except HTTPError: + # Part ID does not exist + cprint('[TREE] Error: Part ID does not exist in database') + elif part_ipn: + part = get_part_id_from_ipn(part_ipn) + else: + pass + + return part + + def is_new_part(category_id: int, part_info: dict) -> int: ''' Check if part exists based on parameters (or description) ''' global inventree_api diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index f4ae0014..9af6c149 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -556,3 +556,12 @@ def inventree_create(part_info: dict, categories: list, kicad=False, symbol=None pass return new_part, part_pk, inventree_part + + +def inventree_create_alternate(part_info: dict, part_id='', part_ipn=''): + part_pk = inventree_api.fetch_part_id(part_id, part_ipn) + + if part_pk: + cprint(f'[INFO] Success: Found original part in database (part ID = {part_pk})') + else: + cprint('[INFO] Error: Original part was not found in database') diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index fb6872b6..27aeb0ff 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -325,13 +325,15 @@ def alternate_window() -> dict: alternate_layout = [ [ - sg.Text('InvenTree IPN', size=gui_global['label_size']), - sg.InputText('', key='original_part_ipn'), - sg.Text('InvenTree ID', size=gui_global['label_size']), - sg.InputText('', key='original_part_id'), + sg.Text('Original Part ID', size=gui_global['label_size']), + sg.InputText('', key='part_id'), ], [ - sg.Button('Continue', size=(15, 1)), + sg.Text('Original Part IPN', size=gui_global['label_size']), + sg.InputText('', key='part_ipn'), + ], + [ + sg.Button('Submit', size=(15, 1)), ], ] alternate_window = sg.Window( @@ -348,11 +350,16 @@ def alternate_window() -> dict: alternate_window.close() return else: - alternate_window.close() - return { - values['original_part_ipn'], - values['original_part_id'], - } + if values['part_ipn'] or values['part_id']: + break + else: + sg.popup_ok('Missing original part "IPN" or "ID"', + title='Error', + font=gui_global['font'], + location=gui_global['location']) + + alternate_window.close() + return values def snapeda_window(part_number: str): @@ -498,23 +505,26 @@ def part_user_form(part_data: dict, alternate=False, custom=False) -> dict: for key in input_keys: user_values[key] = form_values[key] - if not form_values['name'] and not form_values['description']: - sg.popup_ok('Missing "Name" and "Description"', - title='Error', - font=gui_global['font'], - location=gui_global['location']) - elif not form_values['name']: - sg.popup_ok('Missing "Name"', - title='Error', - font=gui_global['font'], - location=gui_global['location']) - elif not form_values['description']: - sg.popup_ok('Missing "Description"', - title='Error', - font=gui_global['font'], - location=gui_global['location']) - else: + if alternate: break + else: + if not form_values['name'] and not form_values['description']: + sg.popup_ok('Missing "Name" and "Description"', + title='Error', + font=gui_global['font'], + location=gui_global['location']) + elif not form_values['name']: + sg.popup_ok('Missing "Name"', + title='Error', + font=gui_global['font'], + location=gui_global['location']) + elif not form_values['description']: + sg.popup_ok('Missing "Description"', + title='Error', + font=gui_global['font'], + location=gui_global['location']) + else: + break part_user_form_window.close() return user_values @@ -941,6 +951,8 @@ def main(): init() CREATE_CUSTOM = False + # Default alternate checkbox state + alt_checkbox_disable = True if not settings.ENABLE_INVENTREE or settings.ENABLE_KICAD else False # Select PySimpleGUI theme # sg.theme_previewer() # Show all @@ -981,7 +993,7 @@ def main(): [ sg.Checkbox('KiCad', enable_events=True, default=settings.ENABLE_KICAD, key='enable_kicad'), sg.Checkbox('InvenTree', enable_events=True, default=settings.ENABLE_INVENTREE, key='enable_inventree'), - sg.Checkbox('Alternate', enable_events=True, default=settings.ENABLE_ALTERNATE, key='enable_alternate', disabled=not(settings.ENABLE_INVENTREE)), + sg.Checkbox('Alternate', enable_events=True, default=settings.ENABLE_ALTERNATE, key='enable_alternate', disabled=alt_checkbox_disable), ], [ sg.Button('CREATE', size=(58, 1)), @@ -1016,13 +1028,13 @@ def main(): elif event == 'KiCad': kicad_settings_window() elif 'enable' in event: + # Update alternate checkbox state + alt_checkbox_disable = True if not values['enable_inventree'] or values['enable_kicad'] else False write_values = [values['enable_kicad'], values['enable_inventree'], - values['enable_alternate'] if values['enable_inventree'] and not values['enable_kicad'] else False, ] - if values['enable_inventree'] and not values['enable_kicad']: - window.find_element('enable_alternate').Update(disabled=False) - else: - window.find_element('enable_alternate').Update(disabled=True) + values['enable_alternate'] if not alt_checkbox_disable else False, ] + # Update alternate checkbox + window.find_element('enable_alternate').Update(disabled=alt_checkbox_disable) settings.set_enable_flags(write_values) elif event == 'Custom Part': CREATE_CUSTOM = True @@ -1044,6 +1056,8 @@ def main(): progressbar = False actions_complete = False inventree_connect = False + # Get alternate enable state + CREATE_ALTERNATE = values['enable_alternate'] if values['enable_inventree'] and not values['enable_kicad'] else False # Check supplier selection (can be overwritten) if values['supplier'] not in settings.SUPPORTED_SUPPLIERS_API: @@ -1120,27 +1134,32 @@ def main(): font=gui_global['font'], location=gui_global['location']) - - if settings.ENABLE_ALTERNATE: - cprint('Warning: Alternate') - # Do we have form data? if part_supplier_form: # Open part form part_user_info = part_user_form(part_data=part_supplier_form, - alternate=settings.ENABLE_ALTERNATE, + alternate=CREATE_ALTERNATE, custom=CREATE_CUSTOM) + + if not CREATE_ALTERNATE: + # Stitch back categories and parameters + try: + part_user_info.update({ + 'category': part_supplier_info['category'], + 'subcategory': part_supplier_info['subcategory'], + 'parameters': part_supplier_info['parameters'], + }) + except (KeyError, AttributeError): + pass + + if CREATE_ALTERNATE: + # cprint(part_user_info) + original_part = alternate_window() + # cprint(original_part) + + # Create alternate + inventree_interface.inventree_create_alternate(part_user_info, original_part['part_id'], original_part['part_ipn']) - # Stitch back categories and parameters - try: - part_user_info.update({ - 'category': part_supplier_info['category'], - 'subcategory': part_supplier_info['subcategory'], - 'parameters': part_supplier_info['parameters'], - }) - except (KeyError, AttributeError): - pass - # Check that name and description are present in user form (else the form is empty) try: if part_user_info['name'] and part_user_info['description']: From 7dd846b9717be82ba8631643d3a1d0acd428c6cd Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 31 Oct 2022 15:36:49 -0400 Subject: [PATCH 07/17] Fix tests --- .github/workflows/test_deploy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_deploy.yaml b/.github/workflows/test_deploy.yaml index e1464e49..0abbe665 100644 --- a/.github/workflows/test_deploy.yaml +++ b/.github/workflows/test_deploy.yaml @@ -45,6 +45,7 @@ jobs: INVENTREE_DB_NAME: ${{ github.workspace }}/InvenTree/inventree_default_db.sqlite3 INVENTREE_MEDIA_ROOT: ${{ github.workspace }}/InvenTree INVENTREE_STATIC_ROOT: ${{ github.workspace }}/InvenTree/static + INVENTREE_BACKUP_DIR: ${{ github.workspace }}/InvenTree/backup INVENTREE_ENV: 0 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TOKEN_DIGIKEY: ${{ secrets.TOKEN_DIGIKEY }} From 61d1e5ea20f8544ec4f3411a9305301940723322 Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 31 Oct 2022 16:20:06 -0400 Subject: [PATCH 08/17] Updated minimum python version to match InvenTree codebase requirements --- .github/workflows/test_deploy.yaml | 4 +- README.md | 2 +- images/python_versions.svg | 2 +- poetry.lock | 195 ++++++++++++++--------------- pyproject.toml | 4 +- tasks.py | 2 +- 6 files changed, 101 insertions(+), 108 deletions(-) diff --git a/.github/workflows/test_deploy.yaml b/.github/workflows/test_deploy.yaml index 0abbe665..973b4890 100644 --- a/.github/workflows/test_deploy.yaml +++ b/.github/workflows/test_deploy.yaml @@ -20,7 +20,7 @@ jobs: strategy: matrix: - python-version: ['3.8', '3.10'] + python-version: ['3.9', '3.11'] steps: - name: Checkout code @@ -52,7 +52,7 @@ jobs: strategy: matrix: - python-version: ['3.8', '3.10'] + python-version: ['3.9', '3.11'] steps: - name: Checkout code diff --git a/README.md b/README.md index fe969a7d..eeb692ca 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Ki-nTree was developped by [@eeintech](https://github.com/eeintech) for [SPARK M ### Requirements -* Ki-nTree is currently tested for Python 3.8 to 3.10 versions. +* Ki-nTree is currently tested for Python 3.9 to 3.11 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" diff --git a/images/python_versions.svg b/images/python_versions.svg index ca9fdb36..9cc6b481 100644 --- a/images/python_versions.svg +++ b/images/python_versions.svg @@ -1 +1 @@ -pythonpython3.8 - 3.103.8 - 3.10 \ No newline at end of file +pythonpython3.9 - 3.113.9 - 3.11 \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 67dd90b7..f95065d0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -53,15 +53,15 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "coverage" -version = "6.4.4" +version = "6.5.0" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -130,11 +130,11 @@ urllib3 = ">=1.25.3" [[package]] name = "dill" -version = "0.3.5.1" +version = "0.3.6" description = "serialize all of python" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +python-versions = ">=3.7" [package.extras] graph = ["objgraph (>=1.7.2)"] @@ -188,7 +188,7 @@ python-versions = ">=3.5" [[package]] name = "inventree" -version = "0.8.3" +version = "0.9.0" description = "Python interface for InvenTree inventory management system" category = "main" optional = false @@ -199,7 +199,7 @@ requests = ">=2.27.0" [[package]] name = "invoke" -version = "1.7.1" +version = "1.7.3" description = "Pythonic task execution" category = "dev" optional = false @@ -219,14 +219,14 @@ requests = ">=2.26,<3.0" [[package]] name = "multiprocess" -version = "0.70.13" +version = "0.70.14" description = "better multiprocessing and multithreading in python" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +python-versions = ">=3.7" [package.dependencies] -dill = ">=0.3.5.1" +dill = ">=0.3.6" [[package]] name = "pycparser" @@ -253,7 +253,7 @@ test = ["flaky", "pretend", "pytest (>=3.0.1)"] [[package]] name = "PySimpleGUI" -version = "4.60.3" +version = "4.60.4" description = "Python GUIs for Humans. Launched in 2018. It's 2022 & PySimpleGUI is an ACTIVE & supported project. Super-simple to create custom GUI's. 325+ Demo programs & Cookbook for rapid start. Extensive documentation. Main docs at www.PySimpleGUI.org. Fun & your success are the focus. Examples using Machine Learning (GUI, OpenCV Integration), Rainmeter Style Desktop Widgets, Matplotlib + Pyplot, PIL support, add GUI to command line scripts, PDF & Image Viewers. Great for beginners & advanced GUI programmers." category = "main" optional = false @@ -321,14 +321,14 @@ six = ">=1.7.0" [[package]] name = "setuptools" -version = "65.4.0" +version = "65.5.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -342,7 +342,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tldextract" -version = "3.3.1" +version = "3.4.0" description = "Accurately separates a URL's subdomain, domain, and public suffix, using the Public Suffix List (PSL). By default, this includes the public ICANN TLDs and their exceptions. You can optionally support the Public Suffix List's private domains as well." category = "main" optional = false @@ -391,8 +391,8 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [metadata] lock-version = "1.1" -python-versions = ">=3.8,<3.11" -content-hash = "f6bba7b39da8ba6be11d40b5dca4343bfdbfda3a18bd0cf361f75ac73a01bbc9" +python-versions = ">=3.9,<3.12" +content-hash = "3223a36328af587f9286bc1e36e85ce356c70ca053c6075a7c048a553b574de1" [metadata.files] certauth = [ @@ -478,60 +478,60 @@ click = [ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] coverage = [ - {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, - {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, - {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, - {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, - {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, - {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, - {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, - {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, - {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, - {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, - {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, - {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, - {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, - {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, - {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, - {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, + {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, + {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, + {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, + {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, + {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, + {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, + {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, + {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, + {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, + {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, + {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, + {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, + {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, + {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, ] coveralls = [ {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"}, @@ -574,8 +574,8 @@ digikey-api = [ {file = "digikey_api-1.0.0-py3-none-any.whl", hash = "sha256:3e5c825aa17a61b1c79df0d3ec7162bbd298f0b655f478cd4b0534bf0a68138a"}, ] dill = [ - {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, - {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, + {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, + {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, ] docopt = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, @@ -597,39 +597,32 @@ inflection = [ {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, ] inventree = [ - {file = "inventree-0.8.3-py2.py3-none-any.whl", hash = "sha256:ebfff738e877e3dae125f1d2f4f25b667be9a6d173abb77764e23b5d99c67b6e"}, - {file = "inventree-0.8.3.tar.gz", hash = "sha256:424ad53658267e497f26b39a02a9566b285ba7aa2cc27c18b8cfcac9ba8714f5"}, + {file = "inventree-0.9.0-py2.py3-none-any.whl", hash = "sha256:e9d22dda0fc78502ad7d5862e98f170808ab0a5f3169040c61880f4da3c6dc04"}, + {file = "inventree-0.9.0.tar.gz", hash = "sha256:90590901bd484742f1778a24bb54e612aecb0d69b20eff70f8f7dc204a70adfa"}, ] invoke = [ - {file = "invoke-1.7.1-py3-none-any.whl", hash = "sha256:2dc975b4f92be0c0a174ad2d063010c8a1fdb5e9389d69871001118b4fcac4fb"}, - {file = "invoke-1.7.1.tar.gz", hash = "sha256:7b6deaf585eee0a848205d0b8c0014b9bf6f287a8eb798818a642dff1df14b19"}, + {file = "invoke-1.7.3-py3-none-any.whl", hash = "sha256:d9694a865764dd3fd91f25f7e9a97fb41666e822bbb00e670091e3f43933574d"}, + {file = "invoke-1.7.3.tar.gz", hash = "sha256:41b428342d466a82135d5ab37119685a989713742be46e42a3a399d685579314"}, ] mouser = [ {file = "mouser-0.1.1-py3-none-any.whl", hash = "sha256:1c0f1f5d317754b55be7b9a30ab40b446ced9ccb2891486bff8d1aa974b29d12"}, {file = "mouser-0.1.1.tar.gz", hash = "sha256:f2b09352b0ecbb3eb5f057ac39adcb619bd266b1f19143bf2c1b6686461abbb3"}, ] multiprocess = [ - {file = "multiprocess-0.70.13-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:b9a3be43ecee6776a9e7223af96914a0164f306affcf4624b213885172236b77"}, - {file = "multiprocess-0.70.13-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:7e6a689da3490412caa7b3e27c3385d8aaa49135f3a353ace94ca47e4c926d37"}, - {file = "multiprocess-0.70.13-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:17cb4229aa43e6973679d67c66a454cbf8b6b0d038425cba3220ea5a06d61b58"}, - {file = "multiprocess-0.70.13-cp27-cp27m-win32.whl", hash = "sha256:99bb68dd0d5b3d30fe104721bee26e4637667112d5951b51feb81479fd560876"}, - {file = "multiprocess-0.70.13-cp27-cp27m-win_amd64.whl", hash = "sha256:6cdde49defcb933062df382ebc9b5299beebcd157a98b3a65291c1c94a2edc41"}, - {file = "multiprocess-0.70.13-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:92003c247436f8699b7692e95346a238446710f078500eb364bc23bb0503dd4f"}, - {file = "multiprocess-0.70.13-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:3ec1c8015e19182bfa01b5887a9c25805c48df3c71863f48fe83803147cde5d6"}, - {file = "multiprocess-0.70.13-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b7415f61bddfffdade73396904551be8124a4a363322aa9c72d42e349c5fca39"}, - {file = "multiprocess-0.70.13-pp37-pypy37_pp73-manylinux_2_24_i686.whl", hash = "sha256:5436d1cd9f901f7ddc4f20b6fd0b462c87dcc00d941cc13eeb2401fc5bd00e42"}, - {file = "multiprocess-0.70.13-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:34e9703bd5b9fee5455c93a74e44dbabe55481c214d03be1e65f037be9d0c520"}, - {file = "multiprocess-0.70.13-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af0a48440aa8f793d8bb100f20102c12f192de5a608638819a998f2cc59e1fcd"}, - {file = "multiprocess-0.70.13-pp38-pypy38_pp73-manylinux_2_24_i686.whl", hash = "sha256:c4a97216e8319039c69a266252cc68a392b96f9e67e3ed02ad88be9e6f2d2969"}, - {file = "multiprocess-0.70.13-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:48315eefe02c35dd7560da3fa8af66d9f4a61b9dc8f7c40801c5f972ab4604b1"}, - {file = "multiprocess-0.70.13-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5a6dca5f29f0224c855d0d5cad963476175cfc8de112d3eebe85914cb735f130"}, - {file = "multiprocess-0.70.13-pp39-pypy39_pp73-manylinux_2_24_i686.whl", hash = "sha256:5974bdad390ba466cc130288d2ef1048fdafedd01cf4641fc024f6088af70bfe"}, - {file = "multiprocess-0.70.13-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:01c1137d2f18d0cd262d0fdb7294b1fe9fc3e8dc8b126e506085434ae8eb3677"}, - {file = "multiprocess-0.70.13-py310-none-any.whl", hash = "sha256:0f4faf4811019efdb2f91db09240f893ee40cbfcb06978f3b8ed8c248e73babe"}, - {file = "multiprocess-0.70.13-py37-none-any.whl", hash = "sha256:62e556a0c31ec7176e28aa331663ac26c276ee3536b5e9bb5e850681e7a00f11"}, - {file = "multiprocess-0.70.13-py38-none-any.whl", hash = "sha256:7be9e320a41d2d0d0eddacfe693cfb07b4cb9c0d3d10007f4304255c15215778"}, - {file = "multiprocess-0.70.13-py39-none-any.whl", hash = "sha256:00ef48461d43d1e30f8f4b2e1b287ecaaffec325a37053beb5503e0d69e5a3cd"}, - {file = "multiprocess-0.70.13.tar.gz", hash = "sha256:2e096dd618a84d15aa369a9cf6695815e5539f853dc8fa4f4b9153b11b1d0b32"}, + {file = "multiprocess-0.70.14-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:560a27540daef4ce8b24ed3cc2496a3c670df66c96d02461a4da67473685adf3"}, + {file = "multiprocess-0.70.14-pp37-pypy37_pp73-manylinux_2_24_i686.whl", hash = "sha256:bfbbfa36f400b81d1978c940616bc77776424e5e34cb0c94974b178d727cfcd5"}, + {file = "multiprocess-0.70.14-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:89fed99553a04ec4f9067031f83a886d7fdec5952005551a896a4b6a59575bb9"}, + {file = "multiprocess-0.70.14-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:40a5e3685462079e5fdee7c6789e3ef270595e1755199f0d50685e72523e1d2a"}, + {file = "multiprocess-0.70.14-pp38-pypy38_pp73-manylinux_2_24_i686.whl", hash = "sha256:44936b2978d3f2648727b3eaeab6d7fa0bedf072dc5207bf35a96d5ee7c004cf"}, + {file = "multiprocess-0.70.14-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:e628503187b5d494bf29ffc52d3e1e57bb770ce7ce05d67c4bbdb3a0c7d3b05f"}, + {file = "multiprocess-0.70.14-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d5da0fc84aacb0e4bd69c41b31edbf71b39fe2fb32a54eaedcaea241050855c"}, + {file = "multiprocess-0.70.14-pp39-pypy39_pp73-manylinux_2_24_i686.whl", hash = "sha256:6a7b03a5b98e911a7785b9116805bd782815c5e2bd6c91c6a320f26fd3e7b7ad"}, + {file = "multiprocess-0.70.14-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:cea5bdedd10aace3c660fedeac8b087136b4366d4ee49a30f1ebf7409bce00ae"}, + {file = "multiprocess-0.70.14-py310-none-any.whl", hash = "sha256:7dc1f2f6a1d34894c8a9a013fbc807971e336e7cc3f3ff233e61b9dc679b3b5c"}, + {file = "multiprocess-0.70.14-py37-none-any.whl", hash = "sha256:93a8208ca0926d05cdbb5b9250a604c401bed677579e96c14da3090beb798193"}, + {file = "multiprocess-0.70.14-py38-none-any.whl", hash = "sha256:6725bc79666bbd29a73ca148a0fb5f4ea22eed4a8f22fce58296492a02d18a7b"}, + {file = "multiprocess-0.70.14-py39-none-any.whl", hash = "sha256:63cee628b74a2c0631ef15da5534c8aedbc10c38910b9c8b18dcd327528d1ec7"}, + {file = "multiprocess-0.70.14.tar.gz", hash = "sha256:3eddafc12f2260d27ae03fe6069b12570ab4764ab59a75e81624fac453fbf46a"}, ] pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, @@ -640,8 +633,8 @@ pyOpenSSL = [ {file = "pyOpenSSL-22.1.0.tar.gz", hash = "sha256:7a83b7b272dd595222d672f5ce29aa030f1fb837630ef229f62e72e395ce8968"}, ] PySimpleGUI = [ - {file = "PySimpleGUI-4.60.3-py3-none-any.whl", hash = "sha256:dc62d5722c0a46d709bc8706590b5d47593bd2ed8c1d306ecfee6c05fb6711f5"}, - {file = "PySimpleGUI-4.60.3.tar.gz", hash = "sha256:75ec46694dc975c0e46be8c57a774e038433b53095821d67be3b221aca3fd68d"}, + {file = "PySimpleGUI-4.60.4-py3-none-any.whl", hash = "sha256:e133fbd21779f0f125cebbc2a4e1f5a931a383738661013ff33ad525d5611eda"}, + {file = "PySimpleGUI-4.60.4.tar.gz", hash = "sha256:f88c82c301a51aea35be605dc060bcceb0dcb6682e16280544884701ab4b23ba"}, ] python-Levenshtein = [ {file = "python-Levenshtein-0.12.2.tar.gz", hash = "sha256:dc2395fbd148a1ab31090dd113c366695934b9e85fe5a4b2a032745efd0346f6"}, @@ -689,16 +682,16 @@ retrying = [ {file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"}, ] setuptools = [ - {file = "setuptools-65.4.0-py3-none-any.whl", hash = "sha256:c2d2709550f15aab6c9110196ea312f468f41cd546bceb24127a1be6fdcaeeb1"}, - {file = "setuptools-65.4.0.tar.gz", hash = "sha256:a8f6e213b4b0661f590ccf40de95d28a177cd747d098624ad3f69c40287297e9"}, + {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, + {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] tldextract = [ - {file = "tldextract-3.3.1-py3-none-any.whl", hash = "sha256:35a0260570e214d8d3cfeeb403992fe9e2b686925f63c9b03c5933408ac2aa5a"}, - {file = "tldextract-3.3.1.tar.gz", hash = "sha256:fe15ac3205e5a25b61689369f98cb45c7778a8f2af113d7c11559ece5195f2d6"}, + {file = "tldextract-3.4.0-py3-none-any.whl", hash = "sha256:47aa4d8f1a4da79a44529c9a2ddc518663b25d371b805194ec5ce2a5f615ccd2"}, + {file = "tldextract-3.4.0.tar.gz", hash = "sha256:78aef13ac1459d519b457a03f1f74c1bf1c2808122a6bcc0e6840f81ba55ad73"}, ] urllib3 = [ {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, diff --git a/pyproject.toml b/pyproject.toml index 020ca2dd..6dea1e70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,10 +11,10 @@ repository = "https://github.com/sparkmicro/Ki-nTree" keywords = ["inventree", "kicad", "component", "part", "create"] [tool.poetry.dependencies] -python = ">=3.8,<3.11" +python = ">=3.9,<3.12" digikey-api = "^1.0.0" fuzzywuzzy = "^0.18.0" -inventree = "^0.8.3" +inventree = "^0.9.0" multiprocess = "^0.70.13" mouser = "^0.1.1" PySimpleGUI = "^4.60.3" diff --git a/tasks.py b/tasks.py index 5fe7ec3c..2b80f65a 100644 --- a/tasks.py +++ b/tasks.py @@ -129,7 +129,7 @@ def python_badge(c): cprint('[MAIN]\tInstall pybadges') c.run('pip install pybadges pip-autoremove', hide=True) cprint('[MAIN]\tCreate badge') - c.run('python -m pybadges --left-text="python" --right-text="3.8 - 3.10" ' + c.run('python -m pybadges --left-text="python" --right-text="3.9 - 3.11" ' '--whole-link="https://www.python.org/" --browser --embed-logo ' '--logo="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/python.svg"') cprint('[MAIN]\tUninstall pybadges') From 8e886810909dbed48555e7b6c7f02855383f4039 Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 31 Oct 2022 16:28:29 -0400 Subject: [PATCH 09/17] invoke does not support 3.11 yet so rolling back latest version to 3.10 --- .github/workflows/test_deploy.yaml | 4 ++-- README.md | 2 +- images/python_versions.svg | 2 +- poetry.lock | 4 ++-- pyproject.toml | 2 +- tasks.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_deploy.yaml b/.github/workflows/test_deploy.yaml index 973b4890..d67572be 100644 --- a/.github/workflows/test_deploy.yaml +++ b/.github/workflows/test_deploy.yaml @@ -20,7 +20,7 @@ jobs: strategy: matrix: - python-version: ['3.9', '3.11'] + python-version: ['3.9', '3.10'] steps: - name: Checkout code @@ -52,7 +52,7 @@ jobs: strategy: matrix: - python-version: ['3.9', '3.11'] + python-version: ['3.9', '3.10'] steps: - name: Checkout code diff --git a/README.md b/README.md index eeb692ca..c346f483 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Ki-nTree was developped by [@eeintech](https://github.com/eeintech) for [SPARK M ### 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.10 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" diff --git a/images/python_versions.svg b/images/python_versions.svg index 9cc6b481..aa94e4fb 100644 --- a/images/python_versions.svg +++ b/images/python_versions.svg @@ -1 +1 @@ -pythonpython3.9 - 3.113.9 - 3.11 \ No newline at end of file +pythonpython3.9 - 3.103.9 - 3.10 \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index f95065d0..74aaf88f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -391,8 +391,8 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [metadata] lock-version = "1.1" -python-versions = ">=3.9,<3.12" -content-hash = "3223a36328af587f9286bc1e36e85ce356c70ca053c6075a7c048a553b574de1" +python-versions = ">=3.9,<3.11" +content-hash = "fcf8c5508aaa6d03b600efaa6d16b4a77d8cf92c0664f62067ecb8e05f650337" [metadata.files] certauth = [ diff --git a/pyproject.toml b/pyproject.toml index 6dea1e70..5520b9e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ repository = "https://github.com/sparkmicro/Ki-nTree" keywords = ["inventree", "kicad", "component", "part", "create"] [tool.poetry.dependencies] -python = ">=3.9,<3.12" +python = ">=3.9,<3.11" digikey-api = "^1.0.0" fuzzywuzzy = "^0.18.0" inventree = "^0.9.0" diff --git a/tasks.py b/tasks.py index 2b80f65a..78e490bd 100644 --- a/tasks.py +++ b/tasks.py @@ -129,7 +129,7 @@ def python_badge(c): cprint('[MAIN]\tInstall pybadges') c.run('pip install pybadges pip-autoremove', hide=True) cprint('[MAIN]\tCreate badge') - c.run('python -m pybadges --left-text="python" --right-text="3.9 - 3.11" ' + c.run('python -m pybadges --left-text="python" --right-text="3.9 - 3.10" ' '--whole-link="https://www.python.org/" --browser --embed-logo ' '--logo="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/python.svg"') cprint('[MAIN]\tUninstall pybadges') From 904ad00ecfae0848ad81d805b6dcbd9a2c49b40d Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 31 Oct 2022 17:11:08 -0400 Subject: [PATCH 10/17] Adding alternate is now working! Still need to add test --- kintree/database/inventree_api.py | 14 ++--- kintree/database/inventree_interface.py | 73 +++++++++++++++++++++++-- kintree/kintree_gui.py | 8 ++- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/kintree/database/inventree_api.py b/kintree/database/inventree_api.py index 0a52297f..c2d1ddc9 100644 --- a/kintree/database/inventree_api.py +++ b/kintree/database/inventree_api.py @@ -109,7 +109,7 @@ def set_part_number(part_id: int, ipn: str) -> bool: return False -def get_part_id_from_ipn(part_ipn='') -> int: +def get_part_from_ipn(part_ipn='') -> int: ''' Get Part ID from Part IPN ''' global inventree_api @@ -117,18 +117,18 @@ def get_part_id_from_ipn(part_ipn='') -> int: for part in parts: if part.IPN == part_ipn: - return part.pk + return part # No part found - return 0 + return None -def fetch_part_id(part_id='', part_ipn='') -> int: - ''' Fetch part information from database ''' +def fetch_part(part_id='', part_ipn='') -> int: + ''' Fetch part from database using either ID or IPN ''' from requests.exceptions import HTTPError global inventree_api - part = 0 + part = None if part_id: try: part = Part(inventree_api, part_id) @@ -142,7 +142,7 @@ def fetch_part_id(part_id='', part_ipn='') -> int: # Part ID does not exist cprint('[TREE] Error: Part ID does not exist in database') elif part_ipn: - part = get_part_id_from_ipn(part_ipn) + part = get_part_from_ipn(part_ipn) else: pass diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index 9af6c149..22a91bb9 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -558,10 +558,73 @@ def inventree_create(part_info: dict, categories: list, kicad=False, symbol=None return new_part, part_pk, inventree_part -def inventree_create_alternate(part_info: dict, part_id='', part_ipn=''): - part_pk = inventree_api.fetch_part_id(part_id, part_ipn) +def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_progress=True): + ''' Create alternate manufacturer and supplier entries for an existing InvenTree part ''' - if part_pk: - cprint(f'[INFO] Success: Found original part in database (part ID = {part_pk})') + cprint('\n[MAIN]\tSearching for original part in database', silent=settings.SILENT) + part = inventree_api.fetch_part(part_id, part_ipn) + + # Progress Update + if show_progress and not progress.update_progress_bar_window(3): + return + + if part: + part_pk = part.pk + part_description = part.description + cprint(f'[INFO] Success: Found original part in database (ID = {part_pk} | Description = "{part_description}")', silent=settings.SILENT) else: - cprint('[INFO] Error: Original part was not found in database') + cprint('[INFO] Error: Original part was not found in database', silent=settings.SILENT) + + manufacturer_name = part_info.get('manufacturer_name', '') + manufacturer_mpn = part_info.get('manufacturer_part_number', '') + datasheet = part_info.get('datasheet', '') + + # Create manufacturer part + if manufacturer_mpn: + cprint('\n[MAIN]\tCreating manufacturer part', silent=settings.SILENT) + manufacturer_part = inventree_api.is_new_manufacturer_part(manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn) + + if manufacturer_part: + cprint('[INFO]\tManufacturer part already exists, skipping.', silent=settings.SILENT) + else: + # Create a new manufacturer part + is_manufacturer_part_created = inventree_api.create_manufacturer_part(part_id=part_pk, + manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn, + datasheet=datasheet, + description=part_description) + + if is_manufacturer_part_created: + cprint('[INFO]\tSuccess: Added new manufacturer part', silent=settings.SILENT) + + # Progress Update + if show_progress and not progress.update_progress_bar_window(3): + return + + supplier_name = part_info.get('supplier_name', '') + supplier_sku = part_info.get('supplier_part_number', '') + supplier_link = part_info.get('supplier_link', '') + + # Add supplier alternate + if supplier_sku: + cprint('\n[MAIN]\tCreating supplier part', silent=settings.SILENT) + is_new_supplier_part = inventree_api.is_new_supplier_part(supplier_name=supplier_name, + supplier_sku=supplier_sku) + + if not is_new_supplier_part: + cprint('[INFO]\tSupplier part already exists, skipping.', silent=settings.SILENT) + else: + # Create a new supplier part + is_supplier_part_created = inventree_api.create_supplier_part(part_id=part_pk, + manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn, + supplier_name=supplier_name, + supplier_sku=supplier_sku, + description=part_description, + link=supplier_link) + + if is_supplier_part_created: + cprint('[INFO]\tSuccess: Added new supplier part', silent=settings.SILENT) + + return diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index 27aeb0ff..ef37ef7c 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -1157,8 +1157,14 @@ def main(): original_part = alternate_window() # cprint(original_part) + # Create progress bar window + progressbar = progress.create_progress_bar_window(font=gui_global['font'], location=gui_global['location']) + # Create alternate - inventree_interface.inventree_create_alternate(part_user_info, original_part['part_id'], original_part['part_ipn']) + inventree_interface.inventree_create_alternate(part_info=part_user_info, + part_id=original_part['part_id'], + part_ipn=original_part['part_ipn'], + show_progress=progressbar) # Check that name and description are present in user form (else the form is empty) try: From 40184108926915fe0c014e38f394c27809ee9fe1 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 1 Nov 2022 16:29:25 -0400 Subject: [PATCH 11/17] Added alternate tests --- kintree/database/inventree_interface.py | 7 +- kintree/kintree_gui.py | 23 ++--- run_tests.py | 118 ++++++++++++++--------- tests/files/inventree_default_db.sqlite3 | Bin 983040 -> 1314816 bytes 4 files changed, 88 insertions(+), 60 deletions(-) diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index 22a91bb9..c0bf53aa 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -558,9 +558,10 @@ def inventree_create(part_info: dict, categories: list, kicad=False, symbol=None return new_part, part_pk, inventree_part -def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_progress=True): +def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_progress=True) -> bool: ''' Create alternate manufacturer and supplier entries for an existing InvenTree part ''' + result = False cprint('\n[MAIN]\tSearching for original part in database', silent=settings.SILENT) part = inventree_api.fetch_part(part_id, part_ipn) @@ -597,6 +598,7 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr if is_manufacturer_part_created: cprint('[INFO]\tSuccess: Added new manufacturer part', silent=settings.SILENT) + result = True # Progress Update if show_progress and not progress.update_progress_bar_window(3): @@ -626,5 +628,6 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr if is_supplier_part_created: cprint('[INFO]\tSuccess: Added new supplier part', silent=settings.SILENT) + result = True - return + return result diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index ef37ef7c..5372324d 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -1153,18 +1153,19 @@ def main(): pass if CREATE_ALTERNATE: - # cprint(part_user_info) + # Alternate window original_part = alternate_window() - # cprint(original_part) - - # Create progress bar window - progressbar = progress.create_progress_bar_window(font=gui_global['font'], location=gui_global['location']) - - # Create alternate - inventree_interface.inventree_create_alternate(part_info=part_user_info, - part_id=original_part['part_id'], - part_ipn=original_part['part_ipn'], - show_progress=progressbar) + + # Check if original_part is empty + if original_part: + # Create progress bar window + progressbar = progress.create_progress_bar_window(font=gui_global['font'], location=gui_global['location']) + + # Create alternate + inventree_interface.inventree_create_alternate(part_info=part_user_info, + part_id=original_part['part_id'], + part_ipn=original_part['part_ipn'], + show_progress=progressbar) # Check that name and description are present in user form (else the form is empty) try: diff --git a/run_tests.py b/run_tests.py index ae045492..84ff79ae 100644 --- a/run_tests.py +++ b/run_tests.py @@ -232,52 +232,6 @@ def check_result(status: str, new_part: bool) -> bool: # cprint(f'\nInvenTree Results\n-----', silent=not(settings.ENABLE_TEST)) # cprint(inventree_results, silent=not(settings.ENABLE_TEST)) - if ENABLE_DELETE: - if kicad_results or inventree_results: - if not AUTO_DELETE: - input('\nPress "Enter" to delete parts...') - else: - cprint('') - - # NOT YET SUPPORTED - REMOVE? - # if ENABLE_KICAD: - # error = 0 - - # pretty_test_print('[MAIN]\tDeleting KiCad test parts') - # # Delete all KiCad test parts - # for number, result in kicad_results.items(): - # try: - # kicad_interface.delete_part(part_number=number, - # library_path=test_library_path) - # except: - # error += 1 - # cprint(f'[KCAD]\tWarning: "{number}" could not be deleted') - - # if error > 0: - # cprint('[ FAIL ]') - # exit_code = -1 - # else: - # cprint('[ PASS ]') - - if ENABLE_INVENTREE: - error = 0 - - pretty_test_print('[MAIN]\tDeleting InvenTree test parts') - # Delete all InvenTree test parts - for number, result in inventree_results.items(): - if result[2]: - try: - if not inventree_api.delete_part(part_id=result[0]): - error += 1 - except: - error += 1 - - if error > 0: - cprint('[ FAIL ]') - exit_code = -1 - else: - cprint('[ PASS ]') - if ENABLE_TEST_METHODS: methods = [ 'Fuzzy category matching', @@ -290,6 +244,8 @@ def check_result(status: str, new_part: bool) -> bool: 'Sync InvenTree and Supplier categories', 'SnapEDA API methods', 'Download image method', + 'Add valid alternate supplier part using part ID', + 'Add invalid alternate supplier part using part IPN', ] method_success = True # Line return @@ -397,13 +353,81 @@ def check_result(status: str, new_part: bool) -> bool: if inventree_api.get_category_parameters(1): method_success = False + elif method_idx == 11: + # Test manufacturer and supplier alternates using Part ID + part_info = { + "datasheet": "https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM155R71C104KA88-01.pdf", + "manufacturer_name": "Murata Electronics", + "manufacturer_part_number": "GRM155R71C104KA88D", + "supplier_link": "https://www.digikey.com/en/products/detail/murata-electronics/GRM155R71C104KA88D/675947", + "supplier_name": "Digi-Key", + "supplier_part_number": "490-3261-1-ND" + } + if not inventree_interface.inventree_create_alternate(part_info=part_info, + part_id='1', + show_progress=False, ): + method_success = False + + elif method_idx == 12: + # Test manufacturer and supplier alternates using Part IPN + if inventree_interface.inventree_create_alternate(part_info=part_info, + part_ipn='CAP-000001-00', + show_progress=False, ): + method_success = False + if method_success: cprint('[ PASS ]') else: cprint('[ FAIL ]') exit_code = -1 break - + + if ENABLE_DELETE: + if kicad_results or inventree_results: + if not AUTO_DELETE: + input('\nPress "Enter" to delete parts...') + else: + cprint('') + + # NOT YET SUPPORTED - REMOVE? + # if ENABLE_KICAD: + # error = 0 + + # pretty_test_print('[MAIN]\tDeleting KiCad test parts') + # # Delete all KiCad test parts + # for number, result in kicad_results.items(): + # try: + # kicad_interface.delete_part(part_number=number, + # library_path=test_library_path) + # except: + # error += 1 + # cprint(f'[KCAD]\tWarning: "{number}" could not be deleted') + + # if error > 0: + # cprint('[ FAIL ]') + # exit_code = -1 + # else: + # cprint('[ PASS ]') + + if ENABLE_INVENTREE: + error = 0 + + pretty_test_print('[MAIN]\tDeleting InvenTree test parts') + # Delete all InvenTree test parts + for number, result in inventree_results.items(): + if result[2]: + try: + if not inventree_api.delete_part(part_id=result[0]): + error += 1 + except: + error += 1 + + if error > 0: + cprint('[ FAIL ]') + exit_code = -1 + else: + cprint('[ PASS ]') + # Line return cprint('') diff --git a/tests/files/inventree_default_db.sqlite3 b/tests/files/inventree_default_db.sqlite3 index 89637220a82efea0db6c255e5e3d57fd75ba24a3..552e151b76c87cd81dec58b009e7c8564411be9c 100644 GIT binary patch delta 37773 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 From a4159a4a23966dd7d573eee78ba2db49cb81a886 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 1 Nov 2022 16:30:50 -0400 Subject: [PATCH 12/17] Fixed style --- kintree/kintree_gui.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index 5372324d..75dd30eb 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -1155,7 +1155,7 @@ def main(): if CREATE_ALTERNATE: # Alternate window original_part = alternate_window() - + # Check if original_part is empty if original_part: # Create progress bar window @@ -1163,9 +1163,9 @@ def main(): # Create alternate inventree_interface.inventree_create_alternate(part_info=part_user_info, - part_id=original_part['part_id'], - part_ipn=original_part['part_ipn'], - show_progress=progressbar) + part_id=original_part['part_id'], + part_ipn=original_part['part_ipn'], + show_progress=progressbar) # Check that name and description are present in user form (else the form is empty) try: From ce1191566d0f9ab50c4bdd970dc9ed7f124a1f9d Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 1 Nov 2022 16:57:06 -0400 Subject: [PATCH 13/17] Fixed number of test methods --- kintree/database/inventree_interface.py | 1 + run_tests.py | 1 + 2 files changed, 2 insertions(+) diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index c0bf53aa..85261ae4 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -575,6 +575,7 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr cprint(f'[INFO] Success: Found original part in database (ID = {part_pk} | Description = "{part_description}")', silent=settings.SILENT) else: cprint('[INFO] Error: Original part was not found in database', silent=settings.SILENT) + return result manufacturer_name = part_info.get('manufacturer_name', '') manufacturer_mpn = part_info.get('manufacturer_part_number', '') diff --git a/run_tests.py b/run_tests.py index 84ff79ae..70d6bc1b 100644 --- a/run_tests.py +++ b/run_tests.py @@ -244,6 +244,7 @@ def check_result(status: str, new_part: bool) -> bool: 'Sync InvenTree and Supplier categories', 'SnapEDA API methods', 'Download image method', + 'Get category parameters', 'Add valid alternate supplier part using part ID', 'Add invalid alternate supplier part using part IPN', ] From 622d32c65d383a6c928ba3ccdbe9e5f5821de8eb Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 2 Nov 2022 10:48:15 -0400 Subject: [PATCH 14/17] Add 'smart' way to check for existing companies in database, found Digikey search bug --- kintree/database/inventree_api.py | 13 +++-- kintree/database/inventree_interface.py | 66 ++++++++++++++++++------- kintree/kintree_gui.py | 18 +++++-- 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/kintree/database/inventree_api.py b/kintree/database/inventree_api.py index c2d1ddc9..a0a9e571 100644 --- a/kintree/database/inventree_api.py +++ b/kintree/database/inventree_api.py @@ -349,16 +349,23 @@ def create_company(company_name: str, manufacturer=False, supplier=False) -> boo return company -def get_company_id(company_name: str) -> int: - ''' Get company (supplier/manufacturer) primary key (ID) ''' +def get_all_companies() -> dict: + ''' Get all existing companies (supplier/manufacturer) from database ''' global inventree_api company_list = Company.list(inventree_api) companies = {} for company in company_list: companies[company.name] = company.pk + + return companies + + +def get_company_id(company_name: str) -> int: + ''' Get company (supplier/manufacturer) primary key (ID) ''' + try: - return companies[company_name] + return get_all_companies()[company_name] except: return 0 diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index 85261ae4..1cd7cfa3 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -334,7 +334,7 @@ def supplier_search(supplier: str, part_number: str, test_mode=False) -> dict: part_info = mouser_api.fetch_part_info(part_number) elif supplier == 'LCSC': part_info = lcsc_api.fetch_part_info(part_number) - + cprint(part_info) # Check supplier data exist if not part_info: cprint(f'[INFO]\tError: Failed to fetch data for "{part_number}"', silent=settings.SILENT) @@ -346,6 +346,45 @@ def supplier_search(supplier: str, part_number: str, test_mode=False) -> dict: return part_info +def inventree_fuzzy_company_match(name: str) -> str: + ''' Fuzzy match company name to exisiting companies ''' + inventree_companies = inventree_api.get_all_companies() + + for company_name in inventree_companies.keys(): + if fuzz.partial_ratio(name.lower(), company_name.lower()) == 100: + return company_name + + return name + + +def inventree_create_manufacturer_part(part_id: int, manufacturer_name: str, manufacturer_mpn: str, datasheet: str, description: str) -> bool: + ''' Create manufacturer part ''' + + cprint('\n[MAIN]\tCreating manufacturer part', silent=settings.SILENT) + manufacturer_part = inventree_api.is_new_manufacturer_part(manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn) + + if manufacturer_part: + cprint('[INFO]\tManufacturer part already exists, skipping.', silent=settings.SILENT) + else: + # Create a new manufacturer part + is_manufacturer_part_created = inventree_api.create_manufacturer_part(part_id=part_id, + manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn, + datasheet=datasheet, + description=description) + + if is_manufacturer_part_created: + cprint('[INFO]\tSuccess: Added new manufacturer part', silent=settings.SILENT) + return True + + return False + + +def inventree_create_supplier_part(part) -> bool: + return + + def inventree_create(part_info: dict, categories: list, kicad=False, symbol=None, footprint=None, show_progress=True, is_custom=False): ''' Create InvenTree part from supplier part data and categories ''' @@ -577,29 +616,18 @@ def inventree_create_alternate(part_info: dict, part_id='', part_ipn='', show_pr cprint('[INFO] Error: Original part was not found in database', silent=settings.SILENT) return result - manufacturer_name = part_info.get('manufacturer_name', '') + # Overwrite manufacturer with matching one from database + manufacturer_name = inventree_fuzzy_company_match(part_info.get('manufacturer_name', '')) manufacturer_mpn = part_info.get('manufacturer_part_number', '') datasheet = part_info.get('datasheet', '') # Create manufacturer part if manufacturer_mpn: - cprint('\n[MAIN]\tCreating manufacturer part', silent=settings.SILENT) - manufacturer_part = inventree_api.is_new_manufacturer_part(manufacturer_name=manufacturer_name, - manufacturer_mpn=manufacturer_mpn) - - if manufacturer_part: - cprint('[INFO]\tManufacturer part already exists, skipping.', silent=settings.SILENT) - else: - # Create a new manufacturer part - is_manufacturer_part_created = inventree_api.create_manufacturer_part(part_id=part_pk, - manufacturer_name=manufacturer_name, - manufacturer_mpn=manufacturer_mpn, - datasheet=datasheet, - description=part_description) - - if is_manufacturer_part_created: - cprint('[INFO]\tSuccess: Added new manufacturer part', silent=settings.SILENT) - result = True + inventree_create_manufacturer_part(part_id=part_pk, + manufacturer_name=manufacturer_name, + manufacturer_mpn=manufacturer_mpn, + datasheet=datasheet, + description=part_description) # Progress Update if show_progress and not progress.update_progress_bar_window(3): diff --git a/kintree/kintree_gui.py b/kintree/kintree_gui.py index 75dd30eb..fcb9e53c 100644 --- a/kintree/kintree_gui.py +++ b/kintree/kintree_gui.py @@ -1152,7 +1152,7 @@ def main(): except (KeyError, AttributeError): pass - if CREATE_ALTERNATE: + if CREATE_ALTERNATE and part_user_info: # Alternate window original_part = alternate_window() @@ -1162,10 +1162,18 @@ def main(): progressbar = progress.create_progress_bar_window(font=gui_global['font'], location=gui_global['location']) # Create alternate - inventree_interface.inventree_create_alternate(part_info=part_user_info, - part_id=original_part['part_id'], - part_ipn=original_part['part_ipn'], - show_progress=progressbar) + alt_result = inventree_interface.inventree_create_alternate(part_info=part_user_info, + part_id=original_part['part_id'], + part_ipn=original_part['part_ipn'], + show_progress=progressbar) + + # Alternate creation failed + if not alt_result: + progress.close_progress_bar_window() + sg.popup_ok('Failed to create alternate part', + title='Alternate', + font=gui_global['font'], + location=gui_global['location'], ) # Check that name and description are present in user form (else the form is empty) try: From ac8932e33995cb65960e1b0ac45c46801c4a04a3 Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 2 Nov 2022 12:36:15 -0400 Subject: [PATCH 15/17] New Digi-key search method, needs more testing! --- kintree/database/inventree_interface.py | 2 +- kintree/search/digikey_api.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/kintree/database/inventree_interface.py b/kintree/database/inventree_interface.py index 1cd7cfa3..08635ad5 100644 --- a/kintree/database/inventree_interface.py +++ b/kintree/database/inventree_interface.py @@ -334,7 +334,7 @@ def supplier_search(supplier: str, part_number: str, test_mode=False) -> dict: part_info = mouser_api.fetch_part_info(part_number) elif supplier == 'LCSC': part_info = lcsc_api.fetch_part_info(part_number) - cprint(part_info) + # Check supplier data exist if not part_info: cprint(f'[INFO]\tError: Failed to fetch data for "{part_number}"', silent=settings.SILENT) diff --git a/kintree/search/digikey_api.py b/kintree/search/digikey_api.py index 4d091613..dbefa093 100644 --- a/kintree/search/digikey_api.py +++ b/kintree/search/digikey_api.py @@ -80,14 +80,29 @@ def find_categories(part_details: str): def fetch_part_info(part_number: str) -> dict: ''' Fetch part data from API ''' from ..wrapt_timeout_decorator import timeout + from digikey.v3.productinformation.models.manufacturer_product_details_request import ManufacturerProductDetailsRequest part_info = {} if not setup_environment(): return part_info + # OLD METHOD OF SEARCHING DIGI-KEY + # THIS METHOD WOULD SOMETIMES RETURN INCORRECT MATCH + # @timeout(dec_timeout=20) + # def digikey_search_timeout(): + # return digikey.product_details(part_number).to_dict() + @timeout(dec_timeout=20) def digikey_search_timeout(): - return digikey.product_details(part_number).to_dict() + # Create search request body + search_request = ManufacturerProductDetailsRequest(manufacturer_product=part_number, record_count=1) + # Run search + manufacturer_product_details = digikey.manufacturer_product_details(body=search_request).to_dict() + if type(manufacturer_product_details.get('product_details', None)) == list: + # Return the first item only + return manufacturer_product_details.get('product_details', None)[0] + else: + return {} # Query part number try: From 55b756eb69aa34353be731e724da9a162c71e22b Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 2 Nov 2022 12:43:28 -0400 Subject: [PATCH 16/17] Fixed Digi-key api test --- kintree/search/digikey_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kintree/search/digikey_api.py b/kintree/search/digikey_api.py index dbefa093..c4bab0d9 100644 --- a/kintree/search/digikey_api.py +++ b/kintree/search/digikey_api.py @@ -150,7 +150,7 @@ def test_api_connect(check_content=False) -> bool: test_success = True expected = { 'product_description': 'RES 10K OHM 5% 1/16W 0402', - 'digi_key_part_number': 'RMCF0402JT10K0CT-ND', + 'digi_key_part_number': 'RMCF0402JT10K0TR-ND', 'manufacturer': 'Stackpole Electronics Inc', 'manufacturer_part_number': 'RMCF0402JT10K0', 'product_url': 'https://www.digikey.com/en/products/detail/stackpole-electronics-inc/RMCF0402JT10K0/1758206', From 6568c05e85cce9255d2fa8c16f37fdfa0707a866 Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 2 Nov 2022 13:24:40 -0400 Subject: [PATCH 17/17] Need to figure out how filter works with new method --- kintree/search/digikey_api.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kintree/search/digikey_api.py b/kintree/search/digikey_api.py index c4bab0d9..36aa54bb 100644 --- a/kintree/search/digikey_api.py +++ b/kintree/search/digikey_api.py @@ -94,8 +94,14 @@ def fetch_part_info(part_number: str) -> dict: @timeout(dec_timeout=20) def digikey_search_timeout(): + # Set parametric filter for Cut Tape + parametric_filters = { + "ParameterId": 7, + "ValueId": "2", + } # Create search request body - search_request = ManufacturerProductDetailsRequest(manufacturer_product=part_number, record_count=1) + # TODO: record_count and filters parameter do not work + search_request = ManufacturerProductDetailsRequest(manufacturer_product=part_number, record_count=1, filters=parametric_filters) # Run search manufacturer_product_details = digikey.manufacturer_product_details(body=search_request).to_dict() if type(manufacturer_product_details.get('product_details', None)) == list: