InteractiveHtmlBom 2.11.0__tar.gz → 2.11.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad.py +13 -7
  2. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/version.py +1 -1
  3. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/PKG-INFO +1 -1
  4. interactivehtmlbom-2.11.2/make_release.py +158 -0
  5. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/.github/workflows/ci.yml +0 -0
  6. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/.github/workflows/release.yml +0 -0
  7. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/.gitignore +0 -0
  8. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/.jsbeautifyrc +0 -0
  9. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/DATAFORMAT.md +0 -0
  10. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/.gitattributes +0 -0
  11. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/Run.bat +0 -0
  12. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/__init__.py +0 -0
  13. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/compat.py +0 -0
  14. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/__init__.py +0 -0
  15. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/config.py +0 -0
  16. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/fontparser.py +0 -0
  17. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/ibom.py +0 -0
  18. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/lzstring.py +0 -0
  19. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/newstroke_font.py +0 -0
  20. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/core/units.py +0 -0
  21. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/__init__.py +0 -0
  22. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/bitmaps/btn-arrow-down.png +0 -0
  23. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/bitmaps/btn-arrow-up.png +0 -0
  24. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/bitmaps/btn-minus.png +0 -0
  25. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/bitmaps/btn-plus.png +0 -0
  26. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/bitmaps/btn-question.png +0 -0
  27. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/dialog_base.py +0 -0
  28. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog/settings_dialog.py +0 -0
  29. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/dialog_test.py +0 -0
  30. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/__init__.py +0 -0
  31. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/common.py +0 -0
  32. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/easyeda.py +0 -0
  33. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/fusion_eagle.py +0 -0
  34. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/genericjson.py +0 -0
  35. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad_extra/__init__.py +0 -0
  36. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py +0 -0
  37. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad_extra/parser_base.py +0 -0
  38. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py +0 -0
  39. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py +0 -0
  40. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/schema/genericjsonpcbdata_v1.schema +0 -0
  41. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/ecad/svgpath.py +0 -0
  42. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/errors.py +0 -0
  43. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/generate_interactive_bom.py +0 -0
  44. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/i18n/language_en.bat +0 -0
  45. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/i18n/language_zh.bat +0 -0
  46. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/icon.png +0 -0
  47. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/ibom.css +0 -0
  48. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/ibom.html +0 -0
  49. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/ibom.js +0 -0
  50. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/lz-string.js +0 -0
  51. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/pep.js +0 -0
  52. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/render.js +0 -0
  53. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/split.js +0 -0
  54. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/table-util.js +0 -0
  55. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/InteractiveHtmlBom/web/util.js +0 -0
  56. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/LICENSE +0 -0
  57. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/README.md +0 -0
  58. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/__init__.py +0 -0
  59. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/baseline-settings-20px.svg +0 -0
  60. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-grouped-32px.svg +0 -0
  61. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-left-right-32px.svg +0 -0
  62. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-netlist-32px.svg +0 -0
  63. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-only-32px.svg +0 -0
  64. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-top-bot-32px.svg +0 -0
  65. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/bom-ungrouped-32px.svg +0 -0
  66. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/btn-arrow-down.svg +0 -0
  67. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/btn-arrow-up.svg +0 -0
  68. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/btn-minus.svg +0 -0
  69. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/btn-plus.svg +0 -0
  70. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/btn-question.svg +0 -0
  71. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/copy-48px.svg +0 -0
  72. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/io-36px.svg +0 -0
  73. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/plugin.svg +0 -0
  74. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/plugin_icon_big.png +0 -0
  75. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/icons/stats-36px.svg +0 -0
  76. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/pyproject.toml +0 -0
  77. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/settings_dialog.fbp +0 -0
  78. {interactivehtmlbom-2.11.0 → interactivehtmlbom-2.11.2}/tests/test_module.py +0 -0
@@ -71,8 +71,7 @@ class PcbnewParser(EcadParser):
71
71
  var_fields = variant.GetFields()
72
72
  for k in var_fields.keys():
73
73
  props[str(k)] = str(f.GetFieldShownText(str(k)))
74
- if variant.GetDNP():
75
- props["kicad_dnp"] = "DNP"
74
+ props["kicad_dnp"] = "DNP" if variant.GetDNP() else ""
76
75
 
77
76
  return props
78
77
 
@@ -223,7 +222,8 @@ class PcbnewParser(EcadParser):
223
222
  "angle": angle,
224
223
  "polygons": polygons
225
224
  }
226
- if hasattr(d, "IsFilled") and not d.IsFilled():
225
+ if ((hasattr(d, "IsFilled") and not d.IsFilled()) or
226
+ (hasattr(d, "IsSolidFill") and not d.IsSolidFill())):
227
227
  shape_dict["filled"] = 0
228
228
  shape_dict["width"] = d.GetWidth() * 1e-6
229
229
  return shape_dict
@@ -493,7 +493,8 @@ class PcbnewParser(EcadParser):
493
493
  pads.append(pad_dict)
494
494
  return pads
495
495
  else:
496
- pad_dict = self.parse_pad_layer(pad, layers_set[0])
496
+ pad_layer = layers_set[0] if layers_set else pcbnew.F_Cu
497
+ pad_dict = self.parse_pad_layer(pad, pad_layer)
497
498
  pad_dict["layers"] = layers
498
499
  return [pad_dict]
499
500
 
@@ -757,19 +758,24 @@ class PcbnewParser(EcadParser):
757
758
  return nets
758
759
 
759
760
  def footprint_to_component(self, footprint, extra_fields):
761
+ # type: (pcbnew.FOOTPRINT, list) -> Component
760
762
  try:
761
763
  footprint_name = str(footprint.GetFPID().GetFootprintName())
762
764
  except AttributeError:
763
765
  footprint_name = str(footprint.GetFPID().GetLibItemName())
764
766
 
767
+ value = footprint.GetValue()
768
+ if hasattr(footprint, 'GetFieldValueForVariant'):
769
+ value = footprint.GetFieldValueForVariant(
770
+ self.config.kicad_variant, 'Value')
765
771
  attr = 'Normal'
766
772
  if hasattr(pcbnew, 'FP_EXCLUDE_FROM_BOM'):
767
- if footprint.GetAttributes() & pcbnew.FP_EXCLUDE_FROM_BOM:
768
- attr = 'Virtual'
769
773
  if hasattr(footprint, 'GetExcludedFromBOMForVariant'):
770
774
  if footprint.GetExcludedFromBOMForVariant(
771
775
  self.config.kicad_variant):
772
776
  attr = 'Virtual'
777
+ elif footprint.GetAttributes() & pcbnew.FP_EXCLUDE_FROM_BOM:
778
+ attr = 'Virtual'
773
779
  elif hasattr(pcbnew, 'MOD_VIRTUAL'):
774
780
  if footprint.GetAttributes() == pcbnew.MOD_VIRTUAL:
775
781
  attr = 'Virtual'
@@ -779,7 +785,7 @@ class PcbnewParser(EcadParser):
779
785
  }.get(footprint.GetLayer())
780
786
 
781
787
  return Component(footprint.GetReference(),
782
- footprint.GetValue(),
788
+ value,
783
789
  footprint_name,
784
790
  layer,
785
791
  attr,
@@ -3,7 +3,7 @@ import os
3
3
  import subprocess
4
4
 
5
5
 
6
- LAST_TAG = 'v2.11.0'
6
+ LAST_TAG = 'v2.11.2'
7
7
 
8
8
 
9
9
  def _get_git_version():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: InteractiveHtmlBom
3
- Version: 2.11.0
3
+ Version: 2.11.2
4
4
  Summary: Generate Interactive Html BOM for your electronics projects
5
5
  Project-URL: Documentation, https://github.com/openscopeproject/InteractiveHtmlBom/wiki
6
6
  Project-URL: Issues, https://github.com/openscopeproject/InteractiveHtmlBom/issues
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env python3
2
+ """Create a release zip for InteractiveHtmlBom per user's steps.
3
+
4
+ Steps implemented:
5
+ 1. Determine current git tag; require repo clean and HEAD tagged.
6
+ 2. Verify LAST_TAG in InteractiveHtmlBom/version.py matches git tag.
7
+ 3. Create releases/<tag> folder.
8
+ 4. Create a tmp dir.
9
+ 5. Copy `resources` folder into tmp dir.
10
+ 6. Copy `InteractiveHtmlBom` into tmp/plugins,
11
+ excluding __pycache__ and .ini files.
12
+ 7. Set `versions[0].version` in `releases/metadata.json` to tag
13
+ without leading 'v'.
14
+ 8. Copy resulting metadata.json into tmp dir.
15
+ 9. Zip tmp dir contents to `InteractiveHtmlBom_{version}_pcm.zip`
16
+ inside releases/<tag>.
17
+ 10.Zip plugin code into InteractiveHtmlBom.zip suitable for manual install.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ import re
24
+ import shutil
25
+ import subprocess
26
+ import sys
27
+ import tempfile
28
+ from pathlib import Path
29
+
30
+
31
+ def run(cmd: list[str]) -> str:
32
+ return subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True).strip()
33
+
34
+
35
+ def get_head_tag() -> str:
36
+ tags = run(["git", "tag", "--points-at", "HEAD"]).splitlines()
37
+ if not tags:
38
+ raise SystemExit("ERROR: current commit is not tagged. Aborting.")
39
+ return tags[0]
40
+
41
+
42
+ def repo_is_dirty() -> bool:
43
+ status = run(["git", "status", "--porcelain"]).strip()
44
+ return bool(status)
45
+
46
+
47
+ def read_last_tag_from_version_file(path: Path) -> str | None:
48
+ text = path.read_text(encoding="utf8")
49
+ m = re.search(r"LAST_TAG\s*=\s*['\"]([^'\"]+)['\"]", text)
50
+ return m.group(1) if m else None
51
+
52
+
53
+ def update_metadata_version(metadata_path: Path, version: str) -> None:
54
+ data = json.loads(metadata_path.read_text(encoding="utf8"))
55
+ if "versions" not in data or not isinstance(data["versions"], list) or not data["versions"]:
56
+ raise SystemExit(f"ERROR: {metadata_path} has no versions[0] entry")
57
+ data["versions"][0]["version"] = version
58
+ metadata_path.write_text(json.dumps(
59
+ data, indent=4, ensure_ascii=False), encoding="utf8")
60
+
61
+
62
+ def copy_interactive_html_bom(src: Path, dst: Path) -> None:
63
+ # copytree with ignore patterns for __pycache__ directories and .ini files
64
+ def _ignore(dir, names):
65
+ ignored = set()
66
+ for name in list(names):
67
+ if name == "__pycache__" or name.endswith(".ini"):
68
+ ignored.add(name)
69
+ return ignored
70
+
71
+ shutil.copytree(src, dst, ignore=_ignore)
72
+
73
+
74
+ def main() -> None:
75
+ root = Path.cwd()
76
+
77
+ # 1. Ensure repo clean and HEAD is tagged
78
+ if repo_is_dirty():
79
+ raise SystemExit(
80
+ "ERROR: repository has uncommitted changes (dirty). Commit or stash before releasing.")
81
+
82
+ tag = get_head_tag()
83
+ print(f"Found tag: {tag}")
84
+
85
+ # 2. Verify LAST_TAG in InteractiveHtmlBom/version.py
86
+ version_file = root / "InteractiveHtmlBom" / "version.py"
87
+ if not version_file.exists():
88
+ raise SystemExit(f"ERROR: {version_file} not found")
89
+ last_tag = read_last_tag_from_version_file(version_file)
90
+ if last_tag is None:
91
+ raise SystemExit(f"ERROR: LAST_TAG not found in {version_file}")
92
+ if last_tag != tag:
93
+ raise SystemExit(
94
+ f"ERROR: LAST_TAG ({last_tag}) does not match git tag ({tag})")
95
+ print("LAST_TAG matches git tag.")
96
+
97
+ # 3. Create releases/<tag> folder
98
+ releases_dir = root / "releases"
99
+ version_dir = releases_dir / tag
100
+ version_dir.mkdir(parents=True, exist_ok=True)
101
+ print(f"Created/verified release folder: {version_dir}")
102
+
103
+ # 4-9 inside a temporary directory
104
+ with tempfile.TemporaryDirectory() as tmp:
105
+ tmp_path = Path(tmp)
106
+
107
+ # 5. Copy resources folder from repo root into tmp dir
108
+ resources_src = root / "releases" / "resources"
109
+ if not resources_src.exists() or not resources_src.is_dir():
110
+ raise SystemExit(
111
+ f"ERROR: resources folder not found at {resources_src}")
112
+ shutil.copytree(resources_src, tmp_path / "resources")
113
+ print("Copied resources into tmp dir.")
114
+
115
+ # 6. Copy InteractiveHtmlBom into tmp/plugins excluding patterns
116
+ plugins_dir = tmp_path / "plugins"
117
+ copy_interactive_html_bom(
118
+ root / "InteractiveHtmlBom", plugins_dir)
119
+ print("Copied InteractiveHtmlBom into tmp/plugins (excluded __pycache__ and .ini files)")
120
+
121
+ # 7. Set versions[0].version inside releases/metadata.json to package version without leading 'v'
122
+ metadata_path = releases_dir / "metadata.json"
123
+ if not metadata_path.exists():
124
+ raise SystemExit(f"ERROR: {metadata_path} not found")
125
+ package_version = tag.lstrip("v")
126
+ update_metadata_version(metadata_path, package_version)
127
+ print(
128
+ f"Updated {metadata_path} versions[0].version to {package_version}")
129
+
130
+ # 8. Copy resulting metadata.json file into tmp dir
131
+ shutil.copy2(metadata_path, tmp_path / "metadata.json")
132
+ print("Copied metadata.json into tmp dir.")
133
+
134
+ # 9. Zip tmp dir contents into InteractiveHtmlBom-{version}-pcm.zip into the version folder
135
+ zip_name = f"InteractiveHtmlBom_{tag}_pcm"
136
+ archive_path = shutil.make_archive(
137
+ str(version_dir / zip_name), 'zip', root_dir=tmp_path)
138
+ print(f"Created archive: {archive_path}")
139
+
140
+ # 10. Create "normal" zip of just plugin code
141
+ shutil.move(plugins_dir, tmp_path / "InteractiveHtmlBom")
142
+ zip_name = f"InteractiveHtmlBom"
143
+ archive_path = shutil.make_archive(
144
+ str(version_dir / zip_name), 'zip', root_dir=tmp_path, base_dir="InteractiveHtmlBom")
145
+ print(f"Created archive: {archive_path}")
146
+
147
+ print("Release package created successfully.")
148
+
149
+
150
+ if __name__ == '__main__':
151
+ try:
152
+ main()
153
+ except subprocess.CalledProcessError as e:
154
+ print("ERROR: git command failed:\n", e.output, file=sys.stderr)
155
+ sys.exit(2)
156
+ except Exception as e:
157
+ print(e, file=sys.stderr)
158
+ sys.exit(1)