From c07840c9612fe6fcfdb5e9fb3dc9ae259ec20089 Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 5 Apr 2023 08:45:38 +0200 Subject: [PATCH 1/9] fix *.paste pads for THT + try to guess THT footprint type using name --- easyeda2kicad/easyeda/easyeda_importer.py | 4 ++-- easyeda2kicad/kicad/export_kicad_footprint.py | 15 +++++---------- easyeda2kicad/kicad/parameters_kicad_footprint.py | 9 +++++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/easyeda2kicad/easyeda/easyeda_importer.py b/easyeda2kicad/easyeda/easyeda_importer.py index f289299..3af8930 100644 --- a/easyeda2kicad/easyeda/easyeda_importer.py +++ b/easyeda2kicad/easyeda/easyeda_importer.py @@ -149,7 +149,8 @@ def __init__(self, easyeda_cp_cad_data: dict): self.output = self.extract_easyeda_data( ee_data_str=self.input["packageDetail"]["dataStr"], ee_data_info=self.input["packageDetail"]["dataStr"]["head"]["c_para"], - is_smd=self.input.get("SMT"), + is_smd=self.input.get("SMT") + and "-TH_" not in self.input["packageDetail"]["title"], ) def get_footprint(self): @@ -172,7 +173,6 @@ def extract_easyeda_data( ) for line in ee_data_str["shape"]: - ee_designator = line.split("~")[0] ee_fields = line.split("~")[1:] diff --git a/easyeda2kicad/kicad/export_kicad_footprint.py b/easyeda2kicad/kicad/export_kicad_footprint.py index f8b9a0d..56ce8d0 100644 --- a/easyeda2kicad/kicad/export_kicad_footprint.py +++ b/easyeda2kicad/kicad/export_kicad_footprint.py @@ -32,7 +32,6 @@ def compute_arc( end_x: float, end_y: float, ) -> Tuple[float, float, float]: - # Compute the half distance between the current and the final point dx2 = (start_x - end_x) / 2.0 dy2 = (start_y - end_y) / 2.0 @@ -130,7 +129,6 @@ def drill_to_ki( and hole_length is not None and hole_length != 0 ): - max_distance_hole = max(hole_radius * 2, hole_length) pos_0 = pad_height - max_distance_hole pos_90 = pad_width - max_distance_hole @@ -176,7 +174,6 @@ def __init__(self, footprint: ee_footprint): self.generate_kicad_footprint() def generate_kicad_footprint(self) -> None: - # Convert dimension from easyeda to kicad self.input.bbox.convert_to_mm() @@ -233,14 +230,15 @@ def generate_kicad_footprint(self) -> None: pos_y=ee_pad.center_y - self.input.bbox.y, width=max(ee_pad.width, 0.01), height=max(ee_pad.height, 0.01), - layers=KI_PAD_LAYER[ee_pad.layer_id] - if ee_pad.layer_id in KI_PAD_LAYER - else "", + layers=( + KI_PAD_LAYER if ee_pad.hole_radius <= 0 else KI_PAD_LAYER_THT + ).get(ee_pad.layer_id, ""), number=ee_pad.number, drill=0.0, orientation=angle_to_ki(ee_pad.rotation), polygon="", ) + ki_pad.drill = drill_to_ki( ee_pad.hole_radius, ee_pad.hole_length, ki_pad.height, ki_pad.width ) @@ -253,9 +251,7 @@ def generate_kicad_footprint(self) -> None: if is_custom_shape: if len(point_list) <= 0: logging.warning( - "PAD ${id} is a polygon, but has no points defined".format( - id=ee_pad.id - ) + f"PAD ${ee_pad.id} is a polygon, but has no points defined" ) else: # Replace pad width & height since kicad doesn't care @@ -447,7 +443,6 @@ def get_ki_footprint(self) -> KiFootprint: return self.output def export(self, footprint_full_path: str, model_3d_path: str) -> None: - ki = self.output ki_lib = "" diff --git a/easyeda2kicad/kicad/parameters_kicad_footprint.py b/easyeda2kicad/kicad/parameters_kicad_footprint.py index d754825..788da32 100644 --- a/easyeda2kicad/kicad/parameters_kicad_footprint.py +++ b/easyeda2kicad/kicad/parameters_kicad_footprint.py @@ -77,6 +77,15 @@ 15: "Dwgs.User", } +KI_PAD_LAYER_THT = { + 1: "F.Cu F.Mask", + 2: "B.Cu B.Mask", + 3: "F.SilkS", + 11: "*.Cu *.Mask", + 13: "F.Fab", + 15: "Dwgs.User", +} + KI_LAYERS = { 1: "F.Cu", 2: "B.Cu", From 5ffba74fbc6baf61bcb7ec6057b89ad6adeb6390 Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 5 Apr 2023 08:55:55 +0200 Subject: [PATCH 2/9] try fixing z height issue for THT components #91 --- easyeda2kicad/kicad/export_kicad_footprint.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/easyeda2kicad/kicad/export_kicad_footprint.py b/easyeda2kicad/kicad/export_kicad_footprint.py index 56ce8d0..7758ff0 100644 --- a/easyeda2kicad/kicad/export_kicad_footprint.py +++ b/easyeda2kicad/kicad/export_kicad_footprint.py @@ -204,7 +204,9 @@ def generate_kicad_footprint(self) -> None: y=-round( (self.input.model_3d.translation.y - self.input.bbox.y), 2 ), - z=-round(self.input.model_3d.translation.z, 2), + z=-round(self.input.model_3d.translation.z, 2) + if self.input.info.fp_type == "smd" + else 0, ), rotation=Ki3dModelBase( x=(360 - self.input.model_3d.rotation.x) % 360, @@ -450,8 +452,10 @@ def export(self, footprint_full_path: str, model_3d_path: str) -> None: package_lib="easyeda2kicad", package_name=ki.info.name, edit="5DC5F6A4" ) - if ki.info.fp_type and ki.info.fp_type == "smd": - ki_lib += KI_FP_TYPE.format(component_type=ki.info.fp_type) + if ki.info.fp_type: + ki_lib += KI_FP_TYPE.format( + component_type=("smd" if ki.info.fp_type == "smd" else "through_hole") + ) # Get y_min and y_max to put component info y_low = min(pad.pos_y for pad in ki.pads) From 30eca42d88559de62b2bd4e2ac536d76701b94d1 Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 5 Apr 2023 08:56:12 +0200 Subject: [PATCH 3/9] =?UTF-8?q?Bump=20version:=200.6.3=20=E2=86=92=200.6.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- easyeda2kicad/__init__.py | 2 +- setup.cfg | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 72300a2..48fed77 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# easyeda2kicad v0.6.3 +# easyeda2kicad v0.6.4 _________________ [![PyPI version](https://badge.fury.io/py/easyeda2kicad.svg)](https://badge.fury.io/py/easyeda2kicad) diff --git a/easyeda2kicad/__init__.py b/easyeda2kicad/__init__.py index 62cc8fb..871cbd0 100644 --- a/easyeda2kicad/__init__.py +++ b/easyeda2kicad/__init__.py @@ -1,3 +1,3 @@ -__version__ = "0.6.3" +__version__ = "0.6.4" __author__ = "uPesy" __email__ = "contact@upesy.com" diff --git a/setup.cfg b/setup.cfg index 759f3bf..87d8d1b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.6.3 +current_version = 0.6.4 commit = True tag = True diff --git a/setup.py b/setup.py index af1543f..da4fff5 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ ), long_description=long_description, long_description_content_type="text/markdown", - version="0.6.3", + version="0.6.4", author="uPesy", author_email="contact@upesy.com", url="https://github.com/uPesy/easyeda2kicad.py", From 36ef655a7a46c2c48e77844fd065342119297660 Mon Sep 17 00:00:00 2001 From: Matt Wildoer Date: Tue, 18 Jul 2023 16:55:28 -0700 Subject: [PATCH 4/9] Upgrade to Pydantic V2 Pydantic V2 has breaking API changes, but provides a tool to automatically refactor code. This commit bumps the Pydantic version and upgrades the API calls using their tool. Migration guide: https://docs.pydantic.dev/2.0/migration/ --- easyeda2kicad/easyeda/parameters_easyeda.py | 102 +++++++++++++------- requirements.txt | 4 +- setup.py | 2 +- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/easyeda2kicad/easyeda/parameters_easyeda.py b/easyeda2kicad/easyeda/parameters_easyeda.py index 9acbf0c..a53ecc2 100644 --- a/easyeda2kicad/easyeda/parameters_easyeda.py +++ b/easyeda2kicad/easyeda/parameters_easyeda.py @@ -3,7 +3,7 @@ from enum import Enum from typing import List, Union -from pydantic import BaseModel, validator +from pydantic import field_validator, BaseModel from easyeda2kicad.easyeda.svg_path_parser import parse_svg_path @@ -33,19 +33,23 @@ class EeSymbolPinSettings(BaseModel): id: str is_locked: bool - @validator("is_displayed", pre=True) + @field_validator("is_displayed", mode="before") + @classmethod def parse_display_field(cls, field: str) -> bool: return True if field == "show" else field - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, is_locked: str) -> str: return is_locked or False - @validator("rotation", pre=True) + @field_validator("rotation", mode="before") + @classmethod def empty_str_rotation(cls, rotation: str) -> str: return rotation or 0.0 - @validator("type", pre=True) + @field_validator("type", mode="before") + @classmethod def convert_pin_type(cls, field: str) -> str: return ( EasyedaPinType(int(field or 0)) @@ -63,7 +67,8 @@ class EeSymbolPinPath(BaseModel): path: str color: str - @validator("path", pre=True) + @field_validator("path", mode="before") + @classmethod def tune_path(cls, field: str) -> str: return field.replace("v", "h") @@ -78,17 +83,20 @@ class EeSymbolPinName(BaseModel): font: str font_size: float - @validator("font_size", pre=True) + @field_validator("font_size", mode="before") + @classmethod def empty_str_font(cls, font_size: str) -> float: if isinstance(font_size, str) and "pt" in font_size: return float(font_size.replace("pt", "")) return font_size or 7.0 - @validator("is_displayed", pre=True) + @field_validator("is_displayed", mode="before") + @classmethod def parse_display_field(cls, field: str) -> str: return True if field == "show" else field - @validator("rotation", pre=True) + @field_validator("rotation", mode="before") + @classmethod def empty_str_rotation(cls, rotation: str) -> str: return rotation or 0.0 @@ -98,7 +106,8 @@ class EeSymbolPinDotBis(BaseModel): circle_x: float circle_y: float - @validator("is_displayed", pre=True) + @field_validator("is_displayed", mode="before") + @classmethod def parse_display_field(cls, field: str) -> str: return True if field == "show" else field @@ -107,7 +116,8 @@ class EeSymbolPinClock(BaseModel): is_displayed: bool path: str - @validator("is_displayed", pre=True) + @field_validator("is_displayed", mode="before") + @classmethod def parse_display_field(cls, field: str) -> str: return True if field == "show" else field @@ -126,8 +136,8 @@ class EeSymbolPin: class EeSymbolRectangle(BaseModel): pos_x: float pos_y: float - rx: Union[float, None] - ry: Union[float, None] + rx: Union[float, None] = None + ry: Union[float, None] = None width: float height: float stroke_color: str @@ -137,7 +147,8 @@ class EeSymbolRectangle(BaseModel): id: str is_locked: bool - @validator("*", pre=True) + @field_validator("*", mode="before") + @classmethod def empty_str_to_none(cls, field: str) -> str: return field or None @@ -154,11 +165,13 @@ class EeSymbolCircle(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("fill_color", pre=True) + @field_validator("fill_color", mode="before") + @classmethod def parse_background_filling(cls, fill_color: str) -> str: return bool(fill_color and fill_color.lower() != "none") @@ -174,15 +187,18 @@ class EeSymbolArc(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("fill_color", pre=True) + @field_validator("fill_color", mode="before") + @classmethod def parse_background_filling(cls, fill_color: str) -> str: return bool(fill_color and fill_color.lower() != "none") - @validator("path", pre=True) + @field_validator("path", mode="before") + @classmethod def convert_svg_path(cls, path: str) -> list: return parse_svg_path(svg_path=path) @@ -199,11 +215,13 @@ class EeSymbolEllipse(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("fill_color", pre=True) + @field_validator("fill_color", mode="before") + @classmethod def parse_background_filling(cls, fill_color: str) -> str: return bool(fill_color and fill_color.lower() != "none") @@ -218,11 +236,13 @@ class EeSymbolPolyline(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("fill_color", pre=True) + @field_validator("fill_color", mode="before") + @classmethod def parse_background_filling(cls, fill_color: str) -> str: return bool(fill_color and fill_color.lower() != "none") @@ -245,11 +265,13 @@ class EeSymbolPath(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("fill_color", pre=True) + @field_validator("fill_color", mode="before") + @classmethod def parse_background_filling(cls, fill_color: str) -> str: return bool(fill_color and fill_color.lower() != "none") @@ -328,11 +350,13 @@ def convert_to_mm(self) -> None: self.hole_radius = convert_to_mm(self.hole_radius) self.hole_length = convert_to_mm(self.hole_length) - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False - @validator("rotation", pre=True) + @field_validator("rotation", mode="before") + @classmethod def empty_str_rotation(cls, field: str) -> str: return field or 0.0 @@ -345,7 +369,8 @@ class EeFootprintTrack(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False @@ -360,7 +385,8 @@ class EeFootprintHole(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False @@ -379,7 +405,8 @@ class EeFootprintCircle(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field: str) -> str: return field or False @@ -400,7 +427,8 @@ class EeFootprintRectangle(BaseModel): layer_id: int is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field): return False if field == "" else field @@ -420,7 +448,8 @@ class EeFootprintArc(BaseModel): id: str is_locked: bool - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field): return False if field == "" else field @@ -441,15 +470,18 @@ class EeFootprintText(BaseModel): id: str is_locked: bool - @validator("is_displayed", pre=True) + @field_validator("is_displayed", mode="before") + @classmethod def empty_str_display(cls, field): return True if field == "" else field - @validator("is_locked", pre=True) + @field_validator("is_locked", mode="before") + @classmethod def empty_str_lock(cls, field): return False if field == "" else field - @validator("rotation", pre=True) + @field_validator("rotation", mode="before") + @classmethod def empty_str_rotation(cls, field): return 0.0 if field == "" else field diff --git a/requirements.txt b/requirements.txt index b890cd7..7238d4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pre-commit>=2.17.0 -pydantic>=1.5 +pydantic>=2.0.0 requests>2.0.0 +pre-commit>=2.17.0 \ No newline at end of file diff --git a/setup.py b/setup.py index da4fff5..116b69d 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ with open("README.md") as fh: long_description = fh.read() -production_dependencies = ["pydantic>=1.5", "requests>2.0.0"] +production_dependencies = ["pydantic>=2.0.0", "requests>2.0.0"] development_dependencies = [ "pre-commit>=2.17.0", From 2a2f6b1ca7194f1a6d1d8bee85a3097faf97dcd4 Mon Sep 17 00:00:00 2001 From: uPesy Electronics Date: Fri, 21 Jul 2023 10:43:42 +0200 Subject: [PATCH 5/9] Update check-code-style.yml --- .github/workflows/check-code-style.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-code-style.yml b/.github/workflows/check-code-style.yml index e4cd494..3d37b9f 100644 --- a/.github/workflows/check-code-style.yml +++ b/.github/workflows/check-code-style.yml @@ -14,6 +14,6 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.x" + python-version: "3.8" cache: "pip" - uses: pre-commit/action@v3.0.0 From 23afd948e8b2675309d6f06f86d69b7d16838b79 Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 30 Aug 2023 10:49:31 +0200 Subject: [PATCH 6/9] fix 0.5 bool issue for is_locked --- easyeda2kicad/easyeda/parameters_easyeda.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easyeda2kicad/easyeda/parameters_easyeda.py b/easyeda2kicad/easyeda/parameters_easyeda.py index a53ecc2..54767ec 100644 --- a/easyeda2kicad/easyeda/parameters_easyeda.py +++ b/easyeda2kicad/easyeda/parameters_easyeda.py @@ -3,7 +3,7 @@ from enum import Enum from typing import List, Union -from pydantic import field_validator, BaseModel +from pydantic import BaseModel, field_validator from easyeda2kicad.easyeda.svg_path_parser import parse_svg_path @@ -430,7 +430,7 @@ class EeFootprintRectangle(BaseModel): @field_validator("is_locked", mode="before") @classmethod def empty_str_lock(cls, field): - return False if field == "" else field + return False if field == "" else bool(float(field)) def convert_to_mm(self): self.x = convert_to_mm(self.x) From 438c80ec8987680315a3d5185b856a04d421378e Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 30 Aug 2023 10:50:13 +0200 Subject: [PATCH 7/9] fix 0.5 bool issue for is_locked --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7238d4c..20893eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ +pre-commit>=2.17.0 pydantic>=2.0.0 requests>2.0.0 -pre-commit>=2.17.0 \ No newline at end of file From da7728ea6f1ceae93c02e8be3d9cf1fae516ed9b Mon Sep 17 00:00:00 2001 From: uPesy-computer Date: Wed, 30 Aug 2023 11:00:13 +0200 Subject: [PATCH 8/9] =?UTF-8?q?Bump=20version:=200.6.4=20=E2=86=92=200.6.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- easyeda2kicad/__init__.py | 2 +- setup.cfg | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 48fed77..be19699 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# easyeda2kicad v0.6.4 +# easyeda2kicad v0.6.5 _________________ [![PyPI version](https://badge.fury.io/py/easyeda2kicad.svg)](https://badge.fury.io/py/easyeda2kicad) diff --git a/easyeda2kicad/__init__.py b/easyeda2kicad/__init__.py index 871cbd0..34fc0ee 100644 --- a/easyeda2kicad/__init__.py +++ b/easyeda2kicad/__init__.py @@ -1,3 +1,3 @@ -__version__ = "0.6.4" +__version__ = "0.6.5" __author__ = "uPesy" __email__ = "contact@upesy.com" diff --git a/setup.cfg b/setup.cfg index 87d8d1b..b7a1507 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.6.4 +current_version = 0.6.5 commit = True tag = True diff --git a/setup.py b/setup.py index 116b69d..ef48fbf 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ ), long_description=long_description, long_description_content_type="text/markdown", - version="0.6.4", + version="0.6.5", author="uPesy", author_email="contact@upesy.com", url="https://github.com/uPesy/easyeda2kicad.py", From c3b51c96fdeb8a171f40603b747cf6e98ed94d52 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Mon, 28 Aug 2023 15:02:15 +0200 Subject: [PATCH 9/9] Recursivily create default_folder If no output folder is supplied, and thus the default_folder is used, the application currently tries to create a new folder under `Documents/Kicad`. However, if some of these folders do not exist, python crashes with a nasty traceback. ``` -- easyeda2kicad.py v0.6.0 -- Traceback (most recent call last): File "/usr/bin/easyeda2kicad", line 33, in sys.exit(load_entry_point('easyeda2kicad==0.6.0', 'console_scripts', 'easyeda2kicad')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/site-packages/easyeda2kicad/__main__.py", line 237, in main if not valid_arguments(arguments=arguments): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/site-packages/easyeda2kicad/__main__.py", line 161, in valid_arguments os.mkdir(default_folder) FileNotFoundError: [Errno 2] No such file or directory: '/home/user/Documents/Kicad/easyeda2kicad' ``` Instead, use os.makedirs, which has been available in python since 3.2 which avoids this issue altogether. --- easyeda2kicad/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easyeda2kicad/__main__.py b/easyeda2kicad/__main__.py index 7cca178..a4bec62 100644 --- a/easyeda2kicad/__main__.py +++ b/easyeda2kicad/__main__.py @@ -158,7 +158,7 @@ def valid_arguments(arguments: dict) -> bool: "easyeda2kicad", ) if not os.path.isdir(default_folder): - os.mkdir(default_folder) + os.makedirs(default_folder, exist_ok=True) base_folder = default_folder lib_name = "easyeda2kicad"