From e72fc56888ae4623058d70eb7c584fa0ff3db91d Mon Sep 17 00:00:00 2001 From: trung_ho Date: Wed, 26 Apr 2023 11:44:11 +0700 Subject: [PATCH] initial commit --- .gitignore | 20 ++ LICENSE.md | 21 ++ README.md | 100 +++++++ images/parts-pushed-todigikey-mylists.png | Bin 0 -> 55106 bytes images/plugin-in-PCB-editor.png | Bin 0 -> 57235 bytes images/plugin-installed.png | Bin 0 -> 10344 bytes pcm/build.py | 68 +++++ pcm/metadata_template.json | 35 +++ pcm/resources/icon.png | Bin 0 -> 1560 bytes src/__init__.py | 5 + src/ki_push_thread.py | 63 ++++ src/ki_result_event.py | 19 ++ src/plugin.py | 349 ++++++++++++++++++++++ src/toolbar_icon.png | Bin 0 -> 1027 bytes src/utils.py | 324 ++++++++++++++++++++ test_connection.txt | 1 - 16 files changed, 1004 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 images/parts-pushed-todigikey-mylists.png create mode 100644 images/plugin-in-PCB-editor.png create mode 100644 images/plugin-installed.png create mode 100644 pcm/build.py create mode 100644 pcm/metadata_template.json create mode 100644 pcm/resources/icon.png create mode 100644 src/__init__.py create mode 100644 src/ki_push_thread.py create mode 100644 src/ki_result_event.py create mode 100644 src/plugin.py create mode 100644 src/toolbar_icon.png create mode 100644 src/utils.py delete mode 100644 test_connection.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de58e15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Python cache directory +__pycache__/ + +# Compiled Python bytecode +*.py[cod] + +# Log files +*.log + +# build ouput +build/ + +# JetBrains IDE +.idea/ + +# Generated by MacOS +.DS_Store + +# Generated by Windows +Thumbs.db \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..65018ca --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Digi-Key Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..96403d9 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# KiCad addon: Push parts to Digi-Key myLists + +This addon helps you collect parts in your [KiCad](https://www.kicad.org/) schematic file and push them to Digi-Key [myLists](https://www.digikey.com/en/mylists/). + +> With myLists, you can calculate assemblies, find alternates, calculate attrition, and more. + +## Installation + +- Download the addon from [latest release](https://github.com/Digi-Key/KiCad-Push-to-DigiKey/releases/latest) +- Open KiCad, select KiCad Plugin and Content Manager, click `Install from File...` +- Select the downloaded .zip file in step 1, click `Open` + +## Usage + +- Open the `PCB Editor` (not Schematic Editor), click the `Push to Digi-Key myLists` icon on the toolbar +- In the dialog that opens, press the `Create DigiKey List` button +- Parts will be pushed to Digi-Key myLists + +![Plugin installed](images/plugin-installed.png) +![Plugin in PCB editor](images/plugin-in-PCB-editor.png) +![Parts pushed to Digi-Key myLists](images/parts-pushed-todigikey-mylists.png) + +## Frequently Asked Questions + +Q: The Part Numbers column does not seem right. + +A: The addon tries to guess which column contains part numbers from the schematic file. +If the `Auto` guess is not what you expect, you can choose a column for Part Number manually. + + +Q: Why do some columns end with an asterisk? + +A: Part Number and Quantity columns are required to create a DigiKey myList. They are marked with an asterisk at the end. + + +Q: I don't find any part numbers after opening the addon. + +A: Please make sure the schematic file does have some part numbers. Also try different columns for `Part Number`. +If this persists, it's a bug. Please consider reporting bugs ([guide](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue)). +We appreciate your time and effort. + + +Q: Is Python required to use the addon? + +A: Yes. But because Python is usually bundled into KiCad installation files, you probably don't need to install Python separately. + + +Q: Why do I need to open PCB Editor (instead of Schematic Editor) to get parts in the schematic? + +A: For now, only the PCB Editor provides an interface (`pcbnew`) for plugin development. + +source: +- https://dev-docs.kicad.org/en/python/ +- https://forum.kicad.info/t/writing-and-publishing-a-plugin/38830 + + +Q: Can I add some note to a part number? + +A: Yes. The last column - `Note` - is editable. Scroll the addon window all the way to the right to see this column. Double-click a row to edit, press Enter when you finish. `Note` will be sent to Digi-Key myLists as well. + + +Q: What is `Customer Reference` column for? + +A: It's for Digi-Key customer with a reference number. This column is not required, so you can leave it blank. + + +Q: May I reuse and modify the code? + +A: Yes, you can reuse and modify the code under [MIT license](https://github.com/Digi-Key/KiCad-Push-to-DigiKey/blob/master/LICENSE.md). + + +Q: How to build the addon from the source code? + +A: We have a [section](#building-addon-from-source-code) for building the addon from the source code. + +## Building addon from source code +To build the addon from source code, a separate installation of Python on your machine is recommended. + +1. Install [Python](https://www.python.org/downloads/) if you don't have it yet. Using a [virtual environment](https://docs.python.org/3/library/venv.html) is recommended. +2. Download the source code +3. Make changes (optional) +4. Run `build` command + +### Download the source code + +1. Go to the source code page on [https://github.com/Digi-Key/KiCad-Push-to-DigiKey](https://github.com/Digi-Key/KiCad-Push-to-DigiKey) +2. Click the `Code` button + +You can download the source code via git clone, GitHub CLI, as zip file, and other methods. + +### Run `build` command +Go to the root directory of the source code, the directory should contain `pcm` and `src` directories. + +```bash +python pcm/build.py +``` + +A .zip file will be created in `build/` directory. Use this file to install the addon in KiCad Plugin and Content Manager. + +Note: Running this command will erase and recreate the `build/` directory. \ No newline at end of file diff --git a/images/parts-pushed-todigikey-mylists.png b/images/parts-pushed-todigikey-mylists.png new file mode 100644 index 0000000000000000000000000000000000000000..3401094aa99e1ca0951ec317c3492e4007ce4edb GIT binary patch literal 55106 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 CBjNY} literal 0 HcmV?d00001 diff --git a/images/plugin-in-PCB-editor.png b/images/plugin-in-PCB-editor.png new file mode 100644 index 0000000000000000000000000000000000000000..d3aeacfd5f596b7cf8bdb7d128016871d050c560 GIT binary patch literal 57235 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%0DfC$l{l`zIo7a9X`{)d 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

1(c&}>>iCCU3 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 OI7$kt@}+kT1O6X|7AXw? literal 0 HcmV?d00001 diff --git a/images/plugin-installed.png b/images/plugin-installed.png new file mode 100644 index 0000000000000000000000000000000000000000..144a4544032d46a49d354cf22671095f8341dae5 GIT binary patch literal 10344 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¬5x)banjW@}7xg@?9O16m2vu=ku+JV6>^q{+(}vzI4?ZEDY#_?c2l%O3<) z8Ywj=$4>q!9g9M?OyH;t9iT+)=b(#}~=u+Ws5fh4ks*5!`(ri1m**&z^t9d+$ zXNT_a@rRG$x2>vF#)MWlcjEj@En>=x4BKUh;+zD>nP>Y$3`gT$zNl&V16tl9sFK0> zFY^kFRadyYc#8@XW7q$xeunU%XrFaVm_Bh_8YlaY`nM=#nt~vxC6zlFog5`ZyQ`{s q3%b{mul4KEYP(Y1JO&G?oZoCd8A_ZIb)XqUXKG|=SaIcc)c*lH$@d%p literal 0 HcmV?d00001 diff --git a/pcm/build.py b/pcm/build.py new file mode 100644 index 0000000..acd1deb --- /dev/null +++ b/pcm/build.py @@ -0,0 +1,68 @@ +# Thanks to gregdavill for this script, +# https://github.com/gregdavill/KiBuzzard/tree/main/pcm + +import hashlib +import json +from pathlib import Path +import pathlib +import os +from os import path +import shutil + +src_path = path.join(path.dirname(__file__), '..', 'src') + +metadata_template = path.join(path.dirname(__file__), 'metadata_template.json') +resources_path = path.join(path.dirname(__file__), 'resources') + +build_path = path.join('build') + +try: + shutil.rmtree(build_path) +except FileNotFoundError: + pass +os.mkdir(build_path) +os.mkdir(path.join(build_path, 'plugin')) +os.chdir(build_path) + +shutil.copytree(src_path, path.join('plugin', 'plugins')) + +# clean out any __pycache__ or .pyc files +# (https://stackoverflow.com/a/41386937) +[p.unlink() for p in pathlib.Path('.').rglob('*.py[co]')] +[p.rmdir() for p in pathlib.Path('.').rglob('__pycache__')] + + +# copy metadata +shutil.copy(metadata_template, path.join('plugin', 'metadata.json')) +# copy icon +shutil.copytree(resources_path, path.join('plugin', 'resources'), ignore=shutil.ignore_patterns('.DS_Store')) + +# load up json script +with open(metadata_template) as f: + md = json.load(f) + + +# zip all files +zip_file = 'PushToDigiKeyMyLists-{0}-pcm.zip'.format(md['versions'][0]['version']) +shutil.make_archive(Path(zip_file).stem, 'zip', 'plugin') + + +zip_size = path.getsize(zip_file) + + +uncompressed_size = sum(f.stat().st_size for f in Path( + 'plugin').glob('**/*') if f.is_file()) + +with open(zip_file, 'rb') as f: + zip_sha256 = hashlib.sha256(f.read()).hexdigest() + + +md['versions'][0].update({ + 'install_size': uncompressed_size, + 'download_size': zip_size, + 'download_sha256': zip_sha256, + 'download_url': 'https://example.com/{0}/PushForKiCad-{0}-pcm.zip'.format(md['versions'][0]['version']) +}) + +with open('metadata.json', 'w') as of: + json.dump(md, of, indent=2) diff --git a/pcm/metadata_template.json b/pcm/metadata_template.json new file mode 100644 index 0000000..5dbb28d --- /dev/null +++ b/pcm/metadata_template.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://go.kicad.org/pcm/schemas/v1", + "name": "Push to Digi-Key myLists", + "description": "Push components in the schematic to Digi-Key myLists for easy and quick part ordering.", + "description_full": "Push components in the schematic to Digi-Key myLists for easy and quick part ordering.", + "identifier": "internal.kicad.pushToDigiKeyMyLists", + "type": "plugin", + "author": { + "name": "Trung Ho", + "contact": { + "github": "https://www.digikey.com", + "web": "https://www.digikey.com", + "twitter": "https://www.digikey.com" + } + }, + "maintainer": { + "name": "Trung Ho", + "contact": { + "github": "https://www.digikey.com", + "web": "https://www.digikey.com", + "twitter": "https://www.digikey.com" + } + }, + "license": "MIT", + "resources": { + "homepage": "https://www.digikey.com" + }, + "versions": [ + { + "version": "0.0.6c4", + "status": "testing", + "kicad_version": "6.00" + } + ] +} \ No newline at end of file diff --git a/pcm/resources/icon.png b/pcm/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4d188aa4e4b1d8ce0656923d3ff239a433dedc7c GIT binary patch literal 1560 zcmd6mdrZ?;6vr>G@)A&FT41z@fH*)(DX)S+3q{JK!Gf+cPWwhArQnLDY-*{%e1O1o z=)f^?1PnvwBU7km78HfjR+v1hxIiahDMbVT4$`#I;_04PEMpr!(Vy$Ha@f=i;Eu>e?Z$V|^BKo=z5{{M?W`biMJ5-9%{^FU>h{?gAv zWFZ(?P^e_n7C9w=m?2VzA``El< zR5dorwxNf~+1jBYlU_GjT_X($mLU9|?WgG`##a^>l!B6e->on5xrP~)VOITT;UUQ; ze|c#5#L;8Mg*SSo@)@0}Rg4Zq$G)tnH0hw3Mn;F>Dwzn-xBu`V)=I`Ab+>To{ zn`f_GdxD8F8;!3T8f3wtla*(sTY~yG2PpPYZH&LVL(WL&kx5wq*cY9vsVvFQj_`o3 zm78?4L+!;0>t%1H<&kr(DRway>ava9u~T%bZ`K%279E>3mg);%XO3)bez$+%Qw5Uy z&?S+5;rB5!o}Xn~96b)zwVwmf16!FJjXZjVGxU)XmLawdtGgv+Kp zU{I+{I-AyGrBFmib$0OKT>=Y7>g3c?my6!Ux~!Ct)KdWO>J5CIxTd=L{CCq`Z0j2^ zP*Tx$DYki?FC6g7+k`$Mdtdj7mp?bP3E7sXV0!)4*2cPon-+0ukGkIE>U=>}X>Dw` zb#gL?NOpQNILH!uirZSa6KB9xhohkaWK#FQNn5tC>Ns$g#G7N?~a9x^0*{0*~sl zHXqM?0hg4I5ScYAmcA}~@RqLMT9grb{8Wateo0MYuf(Iu!se6jcc~1&J60T4SZ=U#cpfvLJ#x56Ms$rP8m_W+FA)X>E0Ur^~ndAKm()kf)T726^UdbnbB zc%I{eT37fWPrOnzdvsw|SNJ$bEOqy^o6&{#FvOF@IBTtuqKxonFgD@l;^Gh(jDQ}J zi8y(F$L1;fQx#3=h3qR)Fkn{kIR%6d=H*KoXnp} plugin.py + +from .plugin import DigiKeyMyListsPlugin +plugin = DigiKeyMyListsPlugin() +plugin.register() diff --git a/src/ki_push_thread.py b/src/ki_push_thread.py new file mode 100644 index 0000000..c1a1b9f --- /dev/null +++ b/src/ki_push_thread.py @@ -0,0 +1,63 @@ +import json +import re +import requests +import time +import wx +from threading import Thread +from .ki_result_event import ResultEvent + + +class PushThread(Thread): + def __init__(self, wx_object, json_data, list_name): + Thread.__init__(self) + self.wx_object = wx_object + self.json_data = json_data + self.list_name = list_name + self.start() + + def run(self): + base_api_url = 'https://www.digikey.com/mylists/api/thirdparty' + json_data = self.json_data + params = {'listName': self.list_name} + + self._post_event({'state': 'Initializing...', 'gauge_int': 10}) + time.sleep(0.5) + + self._post_event({'state': 'Uploading your BOM...', 'gauge_int': 40}) + + r = None + try: + r = requests.post(base_api_url, json=json_data, params=params, verify=False) + except requests.exceptions.RequestException: + self._post_event({'state': 'ERR_REQUESTS_EXCEPTION', 'api_url': base_api_url}) + except: + self._post_event({'state': 'ERR_SENDING_REQUEST', 'api_url': base_api_url}) + + self._post_event({'state': 'Preparing the webpage...', 'gauge_int': 70}) + time.sleep(0.5) + + print('\nStatus Code: ', r.status_code) + print('\nr.text data: ', r.text) + + returned_short_url = '' + try: + returned_short_url = json.loads(r.text) + short_url_regex = r'^http.+digikey\.com/short/[0-9a-z]{7}' + if not re.match(short_url_regex, returned_short_url): + self._post_event({'state': 'SHORT_URL_NOT_RETURNED', 'r_text': returned_short_url}) + return + except json.decoder.JSONDecodeError: + self._post_event({'state': 'SHORT_URL_NOT_RETURNED', 'r_text': returned_short_url}) + return + + self._post_event({'state': 'Done', 'gauge_int': 100}) + time.sleep(0.5) + + try: + wx.LaunchDefaultBrowser(returned_short_url) + except: + self._post_event({'state': 'CANNOT_LAUNCH_DEFAULT_BROWSER', 'url': returned_short_url}) + self._post_event({'state': 'Finished'}) # keyword: "Finished", to close the wxForm. + + def _post_event(self, event_data): + wx.PostEvent(self.wx_object, ResultEvent(event_data)) diff --git a/src/ki_result_event.py b/src/ki_result_event.py new file mode 100644 index 0000000..74696ea --- /dev/null +++ b/src/ki_result_event.py @@ -0,0 +1,19 @@ +import wx +# https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/ + +EVT_RESULT_ID = wx.NewId() + + +def EVT_RESULT(win, func): + """Define Result Event.""" + win.Connect(-1, -1, EVT_RESULT_ID, func) + + +class ResultEvent(wx.PyEvent): + """Simple event to carry arbitrary result data.""" + + def __init__(self, data): + """Init Result Event.""" + wx.PyEvent.__init__(self) + self.SetEventType(EVT_RESULT_ID) + self.data = data diff --git a/src/plugin.py b/src/plugin.py new file mode 100644 index 0000000..bdea92d --- /dev/null +++ b/src/plugin.py @@ -0,0 +1,349 @@ +import ctypes + +try: + # to fix blurry text on Windows + # https://stackoverflow.com/questions/50884283/ + ctypes.windll.shcore.SetProcessDpiAwareness(True) +except: + pass + + +import os +import pcbnew +import wx +import wx.lib.mixins.listctrl as listmix +from .ki_result_event import EVT_RESULT +from .ki_push_thread import PushThread +from .utils import get_symbol_dict, auto_select_part_number_field, make_quantity, parse_fields, to_string, \ + score_fields_as_part_number, pcb_2_sch_path, get_sch_file_name, json_from_bom__with_pn_as_key + + +class EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin): + """ TextEditMixin allows any column to be edited. """ + def __init__(self, parent, _id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0): + # use `_id` to avoid built-in `id` + wx.ListCtrl.__init__(self, parent, _id, pos, size, style) + listmix.TextEditMixin.__init__(self) + + +# no code outside of class, or the plugin will not show + + +class BOMFrame(wx.Frame): + def __init__(self, parent=None, title='Save parts to Digi-Key myLists'): + super(BOMFrame, self).__init__(parent, title=title, size=(1000, 600)) + + # prevent user from making the frame too small + self.SetSizeHints(960, 610) + + # data + self.bom = {} + self.bom_by_pn_field = {} + self.max_list_length = 1_000_000 + + board = pcbnew.GetBoard() + pcb_path = board.GetFileName() + self.kicad_sch_path = pcb_2_sch_path(pcb_path) + self.list_name = get_sch_file_name(self.kicad_sch_path) + + self.wx_md = None + + try: + self.symbol_dict = get_symbol_dict(self.kicad_sch_path) + except FileNotFoundError: + error_caption = 'Schematic file (.kicad_sch) not found' + error_message = \ + 'The "Push to Digi-Key myLists" plugin requires KiCad schematic file (.kicad_sch).\n\n' \ + 'If you have an old schematic file (.sch), save it with the Schematic Editor. ' \ + 'This will create the equivalent KiCad schematic file (.kicad_sch).\n\n' \ + 'The schematic file (.kicad_sch) and the PCB file (.kicad_pcb) must have the same name.'.format() + self.show_error_message_then_exit(error_message, error_caption) + except: + error_caption = 'Error parsing schematic file' + error_message = \ + 'There was an error parsing \n{path}.\n\n' \ + 'If you have an old schematic file (.sch), save it with the Schematic Editor. ' \ + 'This will create the equivalent KiCad schematic file (.kicad_sch).\n\n' \ + 'The schematic file (.kicad_sch) and the PCB file (.kicad_pcb) must have the same name.' \ + .format(path=self.kicad_sch_path) + self.show_error_message_then_exit(error_message, error_caption) + + self.auto_pn_field_dict = auto_select_part_number_field(self.symbol_dict) + self.current_pn_field_str = self.auto_pn_field_dict['name'] + + # layout + self.panel = wx.Panel(self) + self.gbs = wx.GridBagSizer(0, 0) + self.gbs_inputs = wx.GridBagSizer(0, 0) + self.gbs_input_pn_field = wx.GridBagSizer(0, 0) + self.gbs_input_list_name = wx.GridBagSizer(0, 0) + self.gbs_inputs = wx.GridBagSizer(0, 0) + self.gbs_button = wx.GridBagSizer(0, 0) + self.gbs_progress = wx.GridBagSizer(0, 0) + self.wx_pn_field_question = None + self.wx_pn_field_dropdown = None + self.wx_list_name_label = None + self.wx_list_name_input = None + self.wx_progress_gauge = None + self.wx_progress_text = None + self.wx_push_btn = None + self.wx_dummy_text_1 = None + self.wx_tos_text = None + self.wx_bom_lc = EditableListCtrl(self.panel, size=(970, 480), style=wx.LC_REPORT | wx.LC_HRULES) + self.InitUI() + self.Centre() + self.Show() + + def InitUI(self): + fields = parse_fields(self.symbol_dict) + # place 'auto' option as the first item + auto_item = 'Auto ({fn})'.format(fn=self.auto_pn_field_dict['name']) + field_list_cb = [auto_item] + for fname in fields: + field_list_cb.append(fname) + + self.wx_pn_field_question = wx.StaticText(self.panel, label='In which column are part numbers listed?') + self.wx_pn_field_dropdown = wx.ComboBox(self.panel, choices=field_list_cb, size=(250, 28), style=wx.CB_READONLY) + self.wx_pn_field_dropdown.SetValue(field_list_cb[0]) + self.wx_pn_field_dropdown.Bind(wx.EVT_COMBOBOX, self.on_pn_field_select) + self.update_listctrl_with_qty(self.symbol_dict, self.auto_pn_field_dict['name']) + self.update_bom_from_listctrl() + self.update_bom_by_pn_field(self.current_pn_field_str) + + self.wx_list_name_label = wx.StaticText(self.panel, label='List name') + self.wx_list_name_input = wx.TextCtrl(self.panel, value=self.list_name) + self.wx_list_name_input.Bind(wx.EVT_TEXT, self.on_list_name_change) + + self.wx_push_btn = wx.Button(self.panel, label='Create DigiKey List', size=(200, 40)) + # self.wx_push_btn.Bind(wx.EVT_BUTTON, self.on_push_button_click) + self.wx_push_btn.Bind(wx.EVT_BUTTON, self.post_bom_data) + + self.wx_dummy_text_1 = wx.StaticText(self.panel, label=' ', size=(200, 2)) + self.wx_progress_text = wx.StaticText(self.panel, label='PROGRESS TEXT', size=(200, 25)) + self.wx_progress_gauge = wx.Gauge(self.panel, range=100, size=(200, 12), style=wx.GA_HORIZONTAL) + + self.gbs_inputs.Add(self.wx_pn_field_question, pos=(0, 0), span=(1, 1), + flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5) + self.gbs_inputs.Add(self.wx_pn_field_dropdown, pos=(0, 1), span=(1, 1), + flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5) + self.gbs_inputs.Add(self.wx_list_name_label, pos=(1, 0), span=(1, 1), + flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, border=5) + self.gbs_inputs.Add(self.wx_list_name_input, pos=(1, 1), span=(1, 1), + flag=wx.EXPAND | wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, border=5) + + self.gbs_button.Add(self.wx_push_btn, pos=(0, 0), span=(1, 1)) + + self.gbs_progress.Add(self.wx_dummy_text_1, pos=(0, 0), span=(1, 1)) + self.gbs_progress.Add(self.wx_progress_text, pos=(1, 0), span=(1, 1)) + self.gbs_progress.Add(self.wx_progress_gauge, pos=(2, 0), span=(1, 1)) + + # Main Grid + self.gbs.Add(self.gbs_inputs, pos=(0, 0), span=(1, 1)) + self.gbs.Add(self.gbs_button, pos=(0, 1), span=(1, 1), + flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, border=5) + self.gbs.Add(self.gbs_progress, pos=(0, 2), span=(1, 1), + flag=wx.ALIGN_LEFT | wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=5) + self.gbs.Add(self.wx_bom_lc, pos=(1, 0), span=(1, 3), + flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5) + + # Allow the listctrl to fill the window if the window grows. + # Usually the row_idx and col_idx of the listctrl in the GridBagSizer. + # Be careful, this might mess with some widget's alignment. + self.gbs.AddGrowableRow(1) + self.gbs.AddGrowableCol(2) + + self.panel.SetSizerAndFit(self.gbs) + + # Hide controls after `SetSizerAndFit()` + self.wx_progress_text.Hide() + self.wx_progress_gauge.Hide() + + EVT_RESULT(self, self.message_handler) # sync state between Push Thread and the UI + + def update_listctrl(self, symbol_dict): + """ update the `self.wx_bom_lc` """ + fields = parse_fields(symbol_dict) + # header + self.wx_bom_lc.ClearAll() + self.wx_bom_lc.InsertColumn(0, 'Row', wx.LIST_FORMAT_LEFT, 75) + field_name_str_to_col_number_int = {} + _col_idx = 0 + for _fname in fields: + self.wx_bom_lc.InsertColumn(_col_idx + 1, _fname, wx.LIST_FORMAT_LEFT, 200) + field_name_str_to_col_number_int[_fname] = _col_idx + 1 + _col_idx += 1 + self.wx_bom_lc.InsertColumn(_col_idx + 2, 'Customer Reference', wx.LIST_FORMAT_LEFT, 150) + self.wx_bom_lc.InsertColumn(_col_idx + 3, 'Note', wx.LIST_FORMAT_LEFT, 150) + + # rows + _idx = 0 + for _idx, symbol_uuid in enumerate(symbol_dict): + row_index = self.wx_bom_lc.InsertItem(self.max_list_length, _idx) + self.wx_bom_lc.SetItem(row_index, 0, str(_idx + 1)) + for symbol_property in symbol_dict[symbol_uuid]: + if symbol_property['name'] in field_name_str_to_col_number_int: + col_index = field_name_str_to_col_number_int[symbol_property['name']] + self.wx_bom_lc.SetItem(row_index, col_index, to_string(symbol_property['value'])) + self.wx_bom_lc.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.on_listctrl_update) + + def update_listctrl_with_qty(self, symbol_dict, pn_field: str): + """ update the `self.wx_bom_lc` """ + bom_obj_by_pn = make_quantity(symbol_dict, pn_field) + fields = parse_fields(symbol_dict) + + # header + self.wx_bom_lc.ClearAll() + self.wx_bom_lc.InsertColumn(0, 'Row', wx.LIST_FORMAT_LEFT, 75) # numbering the rows for better navigation + self.wx_bom_lc.InsertColumn(1, 'Part Number*', wx.LIST_FORMAT_LEFT, 200) # *: mandatory + self.wx_bom_lc.InsertColumn(2, 'Quantity*', wx.LIST_FORMAT_LEFT, 75) + # fill the rest + field_name_str_to_col_number_int = {} + _idx = 0 + for _fname in fields: + if _fname != pn_field: + self.wx_bom_lc.InsertColumn(_idx + 3, _fname, wx.LIST_FORMAT_LEFT, 200) + field_name_str_to_col_number_int[_fname] = _idx + 3 + _idx += 1 + # the last 2 are optional + self.wx_bom_lc.InsertColumn(_idx + 4, 'Customer Reference', wx.LIST_FORMAT_LEFT, 150) + self.wx_bom_lc.InsertColumn(_idx + 5, 'Note', wx.LIST_FORMAT_LEFT, 150) + + # rows + _idx = 0 + for _idx, symbol_pn in enumerate(bom_obj_by_pn): + row_index = self.wx_bom_lc.InsertItem(self.max_list_length, _idx) + self.wx_bom_lc.SetItem(row_index, 0, str(_idx + 1)) + self.wx_bom_lc.SetItem(row_index, 1, symbol_pn) + self.wx_bom_lc.SetItem(row_index, 2, str(bom_obj_by_pn[symbol_pn]['quantity'])) + for p_name, p_obj in bom_obj_by_pn[symbol_pn].items(): + # e.g.: 'DKPN': {'name': 'DKPN', 'values': ['1234-ND', '5678-ND']} + if p_name in field_name_str_to_col_number_int: + col_index = field_name_str_to_col_number_int[p_name] + self.wx_bom_lc.SetItem(row_index, col_index, to_string(p_obj['values'])) + self.wx_bom_lc.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.on_listctrl_update) + + def update_listctrl_from_bom(self, pn_field_str: str): + self.update_listctrl_with_qty(self.symbol_dict, pn_field_str) + column_count = self.wx_bom_lc.GetColumnCount() + customer_ref_col_idx = column_count - 2 + note_col_idx = column_count - 1 + bom = self.bom_by_pn_field[pn_field_str] + for row_idx, mpn in enumerate(bom): + self.wx_bom_lc.SetItem(row_idx, customer_ref_col_idx, bom[mpn]['cusRef']) + self.wx_bom_lc.SetItem(row_idx, note_col_idx, bom[mpn]['note']) + + def update_bom_from_listctrl(self): + column_count = self.wx_bom_lc.GetColumnCount() + customer_ref_col_idx = column_count - 2 + note_col_idx = column_count - 1 + self.bom = {} + for row_idx in range(self.wx_bom_lc.GetItemCount()): + mpn = self.wx_bom_lc.GetItemText(row_idx, 1) + qty = self.wx_bom_lc.GetItemText(row_idx, 2) + cus_ref = self.wx_bom_lc.GetItemText(row_idx, customer_ref_col_idx) + note = self.wx_bom_lc.GetItemText(row_idx, note_col_idx) + self.bom[mpn] = { + 'mpn': mpn, + 'qty': qty, + 'cusRef': cus_ref, + 'note': note, + } + + def update_bom_by_pn_field(self, pn_field: str): + self.bom_by_pn_field[pn_field] = self.bom + + def on_listctrl_update(self, event): + row_id = event.GetIndex() # Get the current row + col_id = event.GetColumn() # Get the current column + new_data = event.GetLabel() # Get the changed data + + print('Item change at ({r}, {c}): {d}'.format(r=row_id, c=col_id, d=new_data)) + self.wx_bom_lc.SetItem(row_id, col_id, new_data) + self.update_bom_from_listctrl() + self.update_bom_by_pn_field(self.current_pn_field_str) + + def on_pn_field_select(self, event): + if self.wx_pn_field_dropdown.GetSelection() == 0: # the first item is "Auto" + _pn_field = self.auto_pn_field_dict['name'] + else: + _pn_field = self.wx_pn_field_dropdown.GetValue() + self.current_pn_field_str = _pn_field + if self.current_pn_field_str in self.bom_by_pn_field: + self.update_listctrl_from_bom(_pn_field) + self.bom = self.bom_by_pn_field[self.current_pn_field_str] + else: + self.update_listctrl_with_qty(self.symbol_dict, _pn_field) + self.update_bom_from_listctrl() + self.update_bom_by_pn_field(self.current_pn_field_str) + + def on_list_name_change(self, event): + _str_value = self.wx_list_name_input.GetValue() + self.list_name = _str_value.strip() + + def on_push_button_click(self, event): + # for testing purpose + print(self.list_name) + + def message_handler(self, message): + _data = message.data + if _data['state'] == 'Finished': + self.Close() + elif _data['state'] == 'ERR_REQUESTS_EXCEPTION': + error_caption = 'Cannot push part data to Digi-Key myLists' + error_message = \ + 'The plugin cannot push part data to Digi-Key myLists.\n\n' \ + 'Cannot connect to {url}.\n\n' \ + 'If your computer is behind a proxy system, please contact your administrator.' \ + ''.format(url=_data['api_url']) + self.show_error_message_then_exit(message=error_message, caption=error_caption) + elif _data['state'] == 'ERR_SENDING_REQUEST': + error_caption = 'Cannot push part data to Digi-Key myLists' + error_message = 'There was an error pushing part data to Digi-Key myLists.' + self.show_error_message_then_exit(message=error_message, caption=error_caption) + elif _data['state'] == 'SHORT_URL_NOT_RETURNED': + error_caption = 'Cannot create Digi-Key list' + error_message = \ + 'There was an error while creating a Digi-Key list from the given part numbers.\n' \ + 'Please try again later or contact Digi-Key at https://www.digikey.com/en/help-support' + self.show_error_message_then_exit(message=error_message, caption=error_caption) + elif _data['state'] == 'CANNOT_LAUNCH_DEFAULT_BROWSER': + error_caption = 'Cannot launch default browser' + error_message = \ + 'We\'ve created a Digi-Key list from the given part numbers, but could not open the list for you.\n' \ + 'To view the list, you can open your preferred browser with this URL: {url}\n' \ + 'Hint: You don\'t have to type the URL manually, ' \ + 'Ctrl+C this message, then Ctrl+V elsewhere to get the message content, including the URL.' \ + ''.format(url=_data['url']) + self.show_error_message_then_exit(message=error_message, caption=error_caption) + else: + self.wx_progress_text.SetLabel(_data['state']) + self.wx_progress_gauge.SetValue(_data['gauge_int']) + + def post_bom_data(self, _bom=None): + self.wx_push_btn.Disable() + self.wx_progress_gauge.Show() + self.wx_progress_text.Show() + + PushThread(self, json_data=json_from_bom__with_pn_as_key(self.bom), list_name=self.list_name) + + def show_error_message_then_exit(self, message='Message content', caption='Caption'): + self.wx_md = wx.MessageDialog(parent=None, message=message, caption=caption) + self.wx_md.ShowModal() + self.Destroy() + + +class DigiKeyMyListsPlugin(pcbnew.ActionPlugin): + def __init__(self): + self.name = 'Push to Digi-Key myLists' + self.category = 'Manufacturing' + self.pcbnew_icon_support = hasattr(self, 'show_toolbar_button') + self.show_toolbar_button = True + self.icon_file_name = os.path.join( + os.path.dirname(__file__), 'toolbar_icon.png') + self.dark_icon_file_name = os.path.join( + os.path.dirname(__file__), 'toolbar_icon.png') + self.description = 'Push given parts to Digi-Key myLists for easy and fast part order.' + + def Run(self): + BOMFrame().Show() diff --git a/src/toolbar_icon.png b/src/toolbar_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d37029b15428f21b334b8ac2a59a8b40252278 GIT binary patch literal 1027 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+081EW`fPl)R&1)x%f|Ns93 z85E+EvdRz>&gvLmu&^cBG7AVXZ#Qp#zkB!l z{rmSTs(`j!a`AY-XYcoW_dlOIe=|PmK~3HN|Nnqqc-+x-Qby^jfAE(}mw&x}eYc?a zl#<5%>e_#Q{yb{$yb+V|{ocLr4<6jf&inb|`PZvguLXvllvR1u)^SQ+<$hJ|?+@=k zoj7sX)$>XJgumauz1y|>g0=mR$B+L0`2PRjzt^kRoHH^%DW~%9*RSWZ=bY6x{QK?e zW(Nz#h>WI;fz$I-h~1Eum65nc3iixgqPPh^G#GhQ`|& zn7p;K7j$gxT|1X`M)rFKqo6p(6$dV!lw^sCY5bJ;?wr7bhc8*p0tHtbxXrHfBztZ4 zljr@; zq8iUnWZCO!uz-Wj^x%m@vUgd8c@C<$8(b9f`Nm?*_i&B7!RMrudf6#&_!;sS9hkag zdtePP2vtj5BT7;dOH!?pi&B9UgOP!ek*{b*F zx%nxXX_aUijEt;|%^(`Q<$^u~HE6(XD9OxCEiOsSEkMy@X=Q9^WoQJ^vwX!vU@S67 vg7gIEr name: "Datasheet", value: "~", id: '3' + property_line_regex = re.compile(r'^\s{4}\(property "(.*)" "(.*)" \(id (\d+)\)') + if not property_line_regex.search(line): + return + _name, _value, _property_id = property_line_regex.findall(line)[0] + return { + 'name': _name, + 'value': _value, + # 'property_id': _property_id # it almost has no use + } + + +def parse_uuid(s: str): + uuid_regex = re.compile(r'([A-Fa-f0-9]{8}' + r'-[A-Fa-f0-9]{4}' + r'-[A-Fa-f0-9]{4}' + r'-[A-Fa-f0-9]{4}' + r'-[A-Fa-f0-9]{12}' + r')') + if not uuid_regex.search(s): + return + return uuid_regex.findall(s)[0] # first matched + + +def get_symbol_dict(kicad_sch_path): + # one traversal to improve performance: 18s -->0.07s + # SAMPLE OUTPUT + # { + # '00000000-0000-0000-0000-00006319aa5a': [ + # {'name': 'Reference', 'value': 'AU1', 'property_id': '0'}, + # {'name': 'Value', 'value': '', 'property_id': '1'}, + # {'name': 'Footprint', 'value': '', 'property_id': '2'}, + # {'name': 'Datasheet', 'value': '', 'property_id': '3'}, + # {'name': 'Name', 'value': '', 'property_id': '4'}, + # {'name': 'Manufacturer', 'value': '', 'property_id': '5'}, + # {'name': 'Manufacturer Part Number', 'value': '', 'property_id': '6'}, + # {'name': 'Digikey Part Number', 'value': '', 'property_id': '7'} + # ], + # '00000000-0000-0000-0000-00006319aa5b': [ + # {'name': 'Reference', 'value': 'AU2', 'property_id': '0'}, + # {'name': 'Value', 'value': '', 'property_id': '1'}, + # ... + # ] + # } + symbols = {} + new_symbol = False + curr_uuid = None + with open(kicad_sch_path, 'r', encoding='utf-8') as fi: + lines = fi.readlines() + for num, line in enumerate(lines): + if ' (symbol (lib_id' in line: + new_symbol = True + curr_uuid = None + if ' (uuid' in line and new_symbol: + new_symbol = False + curr_uuid = parse_uuid(line) + symbols[curr_uuid] = [] + if ' (property ' in line and curr_uuid: + symbol_property = parse_property_line(line) + symbols[curr_uuid].append(symbol_property) + return symbols + + +def score_field_name_as_part_number(field_name: str): + score = 0 + # fname = field_name.lower() + fname = ''.join([c.lower() for c in field_name if c.isalnum() or c.endswith('#')]) + if 'digi' in fname or 'dk' in fname: + score += 50 + if 'number' in fname or 'pn' in fname: + score += 30 + if 'part' in fname: + score += 20 + if 'product' in fname or fname.endswith('#'): + score += 10 + if 'value' in fname: # Cody: sometimes I spotted PN was entered here + score += 5 + # these fields are known not to be part number + if fname in ['caution', 'datasheet', 'designnote', 'designator', 'designnotes', + 'distributed', 'distributedby', 'distributor', + 'environmentalinformation', 'environmentinfo', + 'environmentinformation', 'footprint', 'installation', 'made', + 'madeby', 'madein', 'make', 'maker', 'mfg', 'mfg.', 'mfr', + 'mfr.', 'note', 'notes', 'package', 'packages', 'packaging', + 'pin', 'pincount', 'pins', 'productpage', 'ref', 'refdes', + 'reference', 'series', 'url', 'usage', 'use', 'warning', 'web', + 'webpage', 'website', 'year']: + score -= 20 + return score + + +def score_field_value_as_part_number(field_value: str): + # PLUS + # specific known regexes (60%) + # lower/upper case (20%) + # length (10%) + # containing characters (10%) + # -- not in dictionary (will not do, too difficult) -- + + # MINUS + # non-ASCII characters + # known keywords + + score = 0 + # upper/lower case + # part number is more likely written in upper case + if field_value.isupper(): + score += 20 + fv = field_value.upper() + + # known allowed characters + # may contain: + # - /, -, #, _, comma, dot, space + # - +, (, ), =, &, \, _, *, ;, ", ', %, [, ] + char_and_length_regex = re.compile(r'^[A-Z0-9#+()/\-\s,.=&:\\_*;"\'%\[\]]{1,49}$') + if char_and_length_regex.match(field_value): + score += 10 + # penalty if not ASCII + if not fv.isascii(): + score -= 20 + + # length + # average length in range (decrease in quantity): + # - [11, 24] + # - [10], [25, 31] + # - [8, 9], [32, 37] + # - the rest + if len(fv) in range(11, 25): + score += 10 + elif len(fv) in range(10, 11) or len(fv) in range(25, 32): + score += 5 + elif len(fv) in range(8, 10) or len(fv) in range(32, 38): + score += 2 + + # known regexes + # Digi-Key packaging: + # - Tape & Reel (TR): TR-ND, -2-ND + # - Cut Tape (CT): CT-ND, -1-ND + # - Digi-Reel (DKR): DKR-ND, -6-ND + if fv.endswith('-ND'): + score += 50 + if fv.endswith('TR-ND') or fv.endswith('-2-ND') \ + or fv.endswith('CT-ND') or fv.endswith('-1-ND') \ + or fv.endswith('DKR-ND') or fv.endswith('-6-ND'): + score += 10 + categorized_regex = re.compile(r'^\d{1,4}-.*-ND$') + if categorized_regex.match(fv): + score += 10 + return score + + +def parse_fields(symbol_dict: dict): + # `id` is no longer a reliable for the identifier of a property, + # now use `name` instead. Beware: it's case-sensitive. + + # SAMPLE OUTPUT (`name` redundancy is intended): + # { + # 'Reference': {'name': 'Reference'}, + # 'Value': {'name': 'Value'}, + # 'Footprint': {'name': 'Footprint'}, + # 'Datasheet': {'name': 'Datasheet'}, + # 'Name': {'name': 'Name'}, + # 'Manufacturer': {'name': 'Manufacturer'}, + # 'Manufacturer Part Number': {'name': 'Manufacturer Part Number'}, + # 'Digikey Part Number': {'name': 'Digikey Part Number}, + # } + fields = {} # name (as str): {name, scores} + for _k, _v_symbol in symbol_dict.items(): # every symbol + for _prop in _v_symbol: # every field in symbol + if _prop['name'] not in fields: + fields[_prop['name']] = { + 'name': _prop['name'] + } + return fields + + +def score_fields_as_part_number(symbol_dict: dict): + # SAMPLE OUTPUT: + # { + # 'Reference': {'name': 'Reference', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Value': {'name': 'Value', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Footprint': {'name': 'Footprint', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Datasheet': {'name': 'Datasheet', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Name': {'name': 'Name', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Manufacturer': {'name': 'Manufacturer', 'name_score': 0, 'values_score': 120, 'field_score': 0}, + # 'Manufacturer Part Number': {'name': 'Manufacturer Part Number', 'name_score': 50, 'values_score': 360, 'field_score': 18_000}, + # 'Digikey Part Number': {'name': 'Digikey Part Number', 'name_score': 60, 'values_score': 480, 'field_score': 28_800} + # } + fields_with_score = parse_fields(symbol_dict) + for fname in fields_with_score: + fname_score = score_field_name_as_part_number(fname) + fvalues_score = 0 + for symbol_properties in symbol_dict.values(): + for symbol_property in symbol_properties: + if symbol_property['name'] == fname: + fvalue = symbol_property['value'] + fvalues_score += score_field_value_as_part_number(fvalue) + fields_with_score[fname]['name_score'] = fname_score + fields_with_score[fname]['values_score'] = fvalues_score + fields_with_score[fname]['field_score'] = fname_score * fvalues_score + return fields_with_score + + +# get symbol list +# get fields (headers only) +# choose the field with the highest Part Number score +# if 2 or more fields have score above a threshold +# init sum_score = 0 for each above field +# for every row +# compute score for those fields +# add to the corresponding sum +# choose the field with the highest sum score +# if 2 or more fields have the highest sum score +# pick the field with higher id +# if user picks a column manually (they don't have to), honor user's choice +def auto_select_part_number_field(symbol_dict): + # SAMPLE OUTPUT: + # {'name': 'DK_PN', 'name_score': 80, 'values_score': 1310, 'field_score': 104_800} + field_scores = score_fields_as_part_number(symbol_dict) + _first_field = list(field_scores.keys())[0] + _hi_score = field_scores[_first_field]['field_score'] + _hi_fname = field_scores[_first_field]['name'] + for fname in field_scores: + if field_scores[fname]['name_score'] >= 0: + if field_scores[fname]['field_score'] > _hi_score: + _hi_score = field_scores[fname]['field_score'] + _hi_fname = field_scores[fname]['name'] + return field_scores[_hi_fname] + # only fields with name_score >= threshold are considered + # pick the last highest field_score + # if all fields have name_score < threshold, pick the last field with the highest score + + +def make_quantity(symbol_dict: dict, pn_field_str: str): + # input: symbol_dict with uuid as key + # output: symbol_dict with part number as key (symbol_dict_by_pn), + # with new column: quantity + symbol_dict_by_pn = {} + for k_symbol_uuid, v_symbol_properties in symbol_dict.items(): + symbol_key = None + for symbol_property in v_symbol_properties: + if symbol_property['name'] == pn_field_str: + symbol_key = symbol_property['value'] + if not symbol_key: # ignore None or '' values + continue + if symbol_key not in symbol_dict_by_pn: # add new + symbol_dict_by_pn[symbol_key] = {} + symbol_dict_by_pn[symbol_key]['symbol_uuids'] = [k_symbol_uuid] + symbol_dict_by_pn[symbol_key]['quantity'] = 1 + for symbol_property in v_symbol_properties: + property_name = symbol_property['name'] + property_value = symbol_property['value'] + if property_name != pn_field_str: + symbol_dict_by_pn[symbol_key][property_name] = {} + symbol_dict_by_pn[symbol_key][property_name]['name'] = property_name # singular + symbol_dict_by_pn[symbol_key][property_name]['values'] = [property_value] # plural + else: # append values to an existing + symbol_dict_by_pn[symbol_key]['symbol_uuids'].append(k_symbol_uuid) + symbol_dict_by_pn[symbol_key]['quantity'] += 1 + for symbol_property in v_symbol_properties: + property_name = symbol_property['name'] + property_value = symbol_property['value'] + # print(symbol_key, property_name, property_value) + if property_name != pn_field_str: + if property_name in symbol_dict_by_pn[symbol_key]: + symbol_dict_by_pn[symbol_key][property_name]['values'].append(property_value) + else: + symbol_dict_by_pn[symbol_key][property_name] = {} + symbol_dict_by_pn[symbol_key][property_name]['name'] = property_name + symbol_dict_by_pn[symbol_key][property_name]['values'] = [property_value] + return symbol_dict_by_pn diff --git a/test_connection.txt b/test_connection.txt deleted file mode 100644 index 3b18e51..0000000 --- a/test_connection.txt +++ /dev/null @@ -1 +0,0 @@ -hello world