169 lines
7.9 KiB
Python
169 lines
7.9 KiB
Python
import os
|
|
import os.path
|
|
import logging
|
|
import shutil
|
|
import re
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_variable(env_var):
|
|
path = os.getenv(env_var)
|
|
|
|
if path is None and (env_var == "KISYS3DMOD" or re.match("KICAD.*_3DMODEL_DIR", env_var)):
|
|
path = os.getenv("KICAD9_3DMODEL_DIR")
|
|
|
|
if path is None:
|
|
path = os.getenv("KICAD8_3DMODEL_DIR")
|
|
if path is None:
|
|
path = os.getenv("KICAD7_3DMODEL_DIR")
|
|
if path is None:
|
|
path = os.getenv("KICAD6_3DMODEL_DIR")
|
|
|
|
return path
|
|
|
|
|
|
class Archiver():
|
|
def __init__(self, model_local_path="/packages3D"):
|
|
self.model_local_path = model_local_path
|
|
|
|
def archive_3d_models(self, board, remap_missing_models=False):
|
|
logger.info("Starting to archive 3D models")
|
|
|
|
logger.debug("All defined environment variables: " + repr(os.environ))
|
|
|
|
# prepare folder for 3D models
|
|
prj_path = os.path.dirname(os.path.abspath(board.GetFileName()))
|
|
model_folder_path = os.path.normpath(prj_path + self.model_local_path)
|
|
|
|
# go to project folder
|
|
os.chdir(prj_path)
|
|
|
|
if not os.path.exists(model_folder_path):
|
|
os.makedirs(model_folder_path)
|
|
|
|
# get all footprints
|
|
footprints = board.GetFootprints()
|
|
|
|
# go through all footprints
|
|
not_copied = []
|
|
for fp in footprints:
|
|
fp_ref = fp.GetReference()
|
|
logger.info("Getting 3D models for footprint of: " + fp_ref)
|
|
# find all 3D models linked to footprint
|
|
models = fp.Models()
|
|
# go through all models bound to footprint
|
|
# bad python API
|
|
nr_models = len(models)
|
|
models_to_push_back = []
|
|
for index in range(nr_models):
|
|
# pop one 3D model from the list
|
|
model = models.pop()
|
|
# copy 3D model
|
|
model_path = model.m_Filename
|
|
logger.info("Trying to copy: " + model_path)
|
|
|
|
# check if model path includes environment variable
|
|
abs_model_path = None
|
|
if "${" in model_path:
|
|
start_index = model_path.find("${")+2
|
|
end_index = model_path.find("}")
|
|
env_var = model_path[start_index:end_index]
|
|
|
|
path = get_variable(env_var)
|
|
# if variable is defined, find proper model path
|
|
if path is not None:
|
|
abs_model_path = os.path.normpath(path+model_path[end_index+1:])
|
|
# if variable is not defined, we can not find the model. Thus don't put it on the list
|
|
else:
|
|
logger.info("Can not find model defined with enviroment variable:\n" + model_path)
|
|
abs_model_path = None
|
|
elif "$(" in model_path:
|
|
start_index = model_path.find("$(")+2
|
|
end_index = model_path.find(")")
|
|
env_var = model_path[start_index:end_index]
|
|
|
|
path = get_variable(env_var)
|
|
# if variable is defined, find proper model path
|
|
if path is not None:
|
|
abs_model_path = os.path.normpath(path+model_path[end_index+1:])
|
|
# if variable is not defined, we can not find the model. Thus don't put it on the list
|
|
else:
|
|
logger.info("Can not find model defined with enviroment variable:\n" + model_path)
|
|
abs_model_path = None
|
|
# check if there is no path (model is local to project)
|
|
elif prj_path == os.path.dirname(os.path.abspath(model_path)):
|
|
abs_model_path = os.path.abspath(model_path)
|
|
# check if model is given with absolute path
|
|
elif os.path.exists(model_path):
|
|
abs_model_path = os.path.abspath(model_path)
|
|
# otherwise we don't know how to parse the path
|
|
else:
|
|
logger.info("Ambiguous path for the model: " + model_path)
|
|
# test default 3D_library location if defined
|
|
if os.getenv("KICAD6_3DMODEL_DIR"):
|
|
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD6_3DMODEL_DIR"), model_path))):
|
|
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD6_3DMODEL_DIR"), model_path))
|
|
logger.info("Going with: " + abs_model_path)
|
|
elif os.getenv("KICAD7_3DMODEL_DIR"):
|
|
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD7_3DMODEL_DIR"), model_path))):
|
|
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD7_3DMODEL_DIR"), model_path))
|
|
logger.info("Going with: " + abs_model_path)
|
|
elif os.getenv("KICAD8_3DMODEL_DIR"):
|
|
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD8_3DMODEL_DIR"), model_path))):
|
|
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD8_3DMODEL_DIR"), model_path))
|
|
logger.info("Going with: " + abs_model_path)
|
|
elif os.getenv("KICAD9_3DMODEL_DIR"):
|
|
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD9_3DMODEL_DIR"), model_path))):
|
|
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD9_3DMODEL_DIR"), model_path))
|
|
logger.info("Going with: " + abs_model_path)
|
|
# testing project folder location
|
|
elif os.path.exists(os.path.normpath(os.path.join(prj_path, model_path))):
|
|
abs_model_path = os.path.normpath(os.path.join(prj_path, model_path))
|
|
logger.info("Going with: " + abs_model_path)
|
|
else:
|
|
abs_model_path = None
|
|
logger.info("Can not find model defined with: " + model_path)
|
|
|
|
# copy model
|
|
model_missing = True
|
|
if abs_model_path:
|
|
model_without_extension = abs_model_path.rsplit('.', 1)[0]
|
|
for ext in ['.wrl', '.stp', '.step', '.igs', '.WRL', '.STP', '.STEP', '.IGS']:
|
|
try:
|
|
shutil.copy2(model_without_extension + ext, model_folder_path)
|
|
model_missing = False
|
|
# src and dst are the same
|
|
except shutil.Error:
|
|
model_missing = False
|
|
# file not found
|
|
except (OSError, IOError):
|
|
pass
|
|
# correct abs_model path for logging
|
|
else:
|
|
abs_model_path = model_path
|
|
|
|
if model_missing:
|
|
logger.info("Did not copy: " + model.m_Filename)
|
|
not_copied.append((fp_ref, model.m_Filename))
|
|
|
|
if not model_missing or remap_missing_models:
|
|
logger.info("Remapping: " + model.m_Filename)
|
|
filename = os.path.basename(abs_model_path)
|
|
new_path = "${KIPRJMOD}" + self.model_local_path + "/" + filename
|
|
model.m_Filename = new_path
|
|
|
|
# and push it to the back of the list (changed or unchaged)
|
|
models_to_push_back.append(model)
|
|
# push all the models back
|
|
for m in models_to_push_back:
|
|
models.push_back(m)
|
|
|
|
if not_copied:
|
|
not_copied_pretty = [(x[0], os.path.normpath(x[1])) for x in not_copied]
|
|
str_list = [repr(x) for x in not_copied_pretty]
|
|
logger.info("Did not succeed to copy 3D models!\n"
|
|
+ "\n".join(str_list))
|
|
return not_copied
|
|
else:
|
|
return []
|