Coverage for JLC2KiCadLib / JLC2KiCadLib.py: 51%

45 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-04 22:17 +0100

1import argparse 

2import json 

3import logging 

4from importlib.metadata import version as pkg_version 

5 

6import requests 

7 

8from . import helper 

9 

10__version__ = pkg_version("JLC2KiCadLib") 

11 

12from .footprint.footprint import create_footprint, get_footprint_info 

13from .symbol.symbol import create_symbol 

14 

15 

16def add_component(component_id, args): 

17 logging.info(f"creating library for component {component_id}") 

18 data = json.loads( 

19 requests.get( 

20 f"https://easyeda.com/api/products/{component_id}/svgs" 

21 ).content.decode() 

22 ) 

23 

24 if not data["success"]: 

25 logging.error( 

26 f"failed to get component uuid for {component_id}\n" 

27 "The component # is probably wrong. Check a possible typo and that the " 

28 "component exists on easyEDA" 

29 ) 

30 return () 

31 

32 footprint_component_uuid = data["result"][-1]["component_uuid"] 

33 symbol_component_uuid = [i["component_uuid"] for i in data["result"][:-1]] 

34 

35 if args.footprint_creation: 

36 footprint_name, datasheet_link = create_footprint( 

37 footprint_component_uuid=footprint_component_uuid, 

38 component_id=component_id, 

39 footprint_lib=args.footprint_lib, 

40 output_dir=args.output_dir, 

41 model_base_variable=args.model_base_variable, 

42 model_dir=args.model_dir, 

43 skip_existing=args.skip_existing, 

44 models=args.models, 

45 ) 

46 else: 

47 _, datasheet_link, _, _ = get_footprint_info(footprint_component_uuid) 

48 footprint_name = "" 

49 

50 if args.symbol_creation: 

51 create_symbol( 

52 symbol_component_uuid=symbol_component_uuid, 

53 footprint_name=footprint_name.replace( 

54 ".pretty", "" 

55 ), # see https://github.com/TousstNicolas/JLC2KiCad_lib/issues/47 

56 datasheet_link=datasheet_link, 

57 library_name=args.symbol_lib, 

58 symbol_path=args.symbol_lib_dir, 

59 output_dir=args.output_dir, 

60 component_id=component_id, 

61 skip_existing=args.skip_existing, 

62 ) 

63 

64 

65def main(): 

66 parser = argparse.ArgumentParser( 

67 description=( 

68 "take a JLCPCB part # and create the according component'skicad's library" 

69 ), 

70 epilog=( 

71 "example use : \n" 

72 " JLC2KiCadLib C1337258 C24112 -dir My_lib " 

73 "-symbol_lib My_Symbol_lib --no_footprint" 

74 ), 

75 formatter_class=argparse.RawDescriptionHelpFormatter, 

76 ) 

77 

78 parser.add_argument( 

79 "components", 

80 metavar="JLCPCB_part_#", 

81 type=str, 

82 nargs="+", 

83 help="List of JLCPCB part # from the components you want to create", 

84 ) 

85 

86 parser.add_argument( 

87 "-dir", 

88 dest="output_dir", 

89 type=str, 

90 default="JLC2KiCad_lib", 

91 help="Base directory for output library files", 

92 ) 

93 

94 parser.add_argument( 

95 "--no_footprint", 

96 dest="footprint_creation", 

97 action="store_false", 

98 help="Use --no_footprint if you do not want to create the footprint", 

99 ) 

100 

101 parser.add_argument( 

102 "--no_symbol", 

103 dest="symbol_creation", 

104 action="store_false", 

105 help="Use --no_symbol if you do not want to create the symbol", 

106 ) 

107 

108 parser.add_argument( 

109 "-symbol_lib", 

110 dest="symbol_lib", 

111 type=str, 

112 default=None, 

113 help='Set symbol library name, default is "default_lib"', 

114 ) 

115 

116 parser.add_argument( 

117 "-symbol_lib_dir", 

118 dest="symbol_lib_dir", 

119 type=str, 

120 default="symbol", 

121 help='Set symbol library path, default is "symbol" (relative to OUTPUT_DIR)', 

122 ) 

123 

124 parser.add_argument( 

125 "-footprint_lib", 

126 dest="footprint_lib", 

127 type=str, 

128 default="footprint", 

129 help='Set footprint library name, default is "footprint"', 

130 ) 

131 

132 parser.add_argument( 

133 "-models", 

134 dest="models", 

135 nargs="*", 

136 choices=["STEP", "WRL"], 

137 type=str, 

138 default="STEP", 

139 help=( 

140 "Select the 3D model you want to use. Default is STEP. " 

141 "If both are selected, only the STEP model will be added to the footprint " 

142 "(the WRL model will still be generated alongside the STEP model). " 

143 "If you do not want any model to be generated, use the --models " 

144 "without arguments" 

145 ), 

146 ) 

147 

148 parser.add_argument( 

149 "-model_dir", 

150 dest="model_dir", 

151 type=str, 

152 default="packages3d", 

153 help=( 

154 'Set directory for storing 3d models, default is "packages3d" ' 

155 "(relative to FOOTPRINT_LIB)" 

156 ), 

157 ) 

158 

159 parser.add_argument( # argument to skip already existing files and symbols 

160 "--skip_existing", 

161 dest="skip_existing", 

162 action="store_true", 

163 help=( 

164 "Use --skip_existing if you want do not want to replace already existing " 

165 "footprints and symbols" 

166 ), 

167 ) 

168 

169 parser.add_argument( 

170 "-model_base_variable", 

171 dest="model_base_variable", 

172 type=str, 

173 default="", 

174 help=( 

175 "Use -model_base_variable if you want to specify the base path of the 3D " 

176 "model using a path variable. If the specified variable starts with '$' it " 

177 "is used 'as-is', otherwise it is encapsulated: $(MODEL_BASE_VARIABLE)" 

178 ), 

179 ) 

180 

181 parser.add_argument( 

182 "-logging_level", 

183 dest="logging_level", 

184 type=str, 

185 default="INFO", 

186 choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], 

187 help=( 

188 "Set logging level. If DEBUG is used, the debug logs are only written in " 

189 "the log file if the option --log_file is set " 

190 ), 

191 ) 

192 

193 parser.add_argument( 

194 "--log_file", 

195 dest="log_file", 

196 action="store_true", 

197 help="Use --log_file if you want logs to be written in a file", 

198 ) 

199 

200 parser.add_argument( 

201 "--version", 

202 action="version", 

203 version=f"%(prog)s {__version__}", 

204 help="Print version number and exit", 

205 ) 

206 

207 args = parser.parse_args() 

208 

209 helper.set_logging(args.logging_level, args.log_file) 

210 

211 for component in args.components: 

212 add_component(component, args) 

213 

214 

215if __name__ == "__main__": 

216 main()