2626 OpenPLCNativeUnsupportedError ,
2727)
2828
29+ from .export_config import OpenPLCExportConfig , load_openplc_export_config
30+
2931
3032class L5XExportError (RuntimeError ):
3133 """Raised when an installed L5X export operation cannot complete."""
@@ -43,22 +45,42 @@ def export_l5x_target(
4345 target : str ,
4446 destination : Path ,
4547 schema_path : Path | None ,
46- compile_only : bool ,
48+ compile_only : bool | None ,
49+ config_path : Path | None ,
4750 base_library_path : Path | None ,
4851 plcopen_reference : Path | None ,
52+ dry_run : bool ,
4953 stdout : TextIO ,
5054) -> None :
5155 """Export a Controller L5X using one explicit target adapter."""
5256 try :
5357 if target == "openplc" :
58+ config = (
59+ load_openplc_export_config (config_path )
60+ if config_path is not None
61+ else OpenPLCExportConfig (
62+ schema_version = "1.0" ,
63+ target = "openplc" ,
64+ )
65+ )
5466 _export_openplc_native (
5567 source ,
5668 destination = destination ,
5769 schema_path = schema_path ,
58- compile_only = compile_only ,
70+ compile_only = (
71+ compile_only
72+ if compile_only is not None
73+ else config .compile_only
74+ ),
75+ config = config ,
76+ dry_run = dry_run ,
5977 stdout = stdout ,
6078 )
6179 return
80+ if config_path is not None :
81+ raise L5XExportError (
82+ "--config currently applies only to --target openplc"
83+ )
6284 if target == "automationml" :
6385 _export_automationml (
6486 source ,
@@ -67,6 +89,7 @@ def export_l5x_target(
6789 compile_only = compile_only ,
6890 base_library_path = base_library_path ,
6991 plcopen_reference = plcopen_reference ,
92+ dry_run = dry_run ,
7093 stdout = stdout ,
7194 )
7295 return
@@ -78,7 +101,7 @@ def export_l5x_target(
78101 )
79102
80103 profile = _PROFILES [target ]
81- if compile_only :
104+ if compile_only is not None :
82105 raise L5XExportError (
83106 "--compile-only applies only to --target openplc"
84107 )
@@ -101,8 +124,9 @@ def export_l5x_target(
101124 if schema_path is not None :
102125 validate_plcopen_xml (result .xml , schema_path )
103126
104- destination .parent .mkdir (parents = True , exist_ok = True )
105- destination .write_text (result .xml , encoding = "utf-8" )
127+ if not dry_run :
128+ destination .parent .mkdir (parents = True , exist_ok = True )
129+ destination .write_text (result .xml , encoding = "utf-8" )
106130 except L5XExportError :
107131 raise
108132 except (
@@ -124,7 +148,8 @@ def export_l5x_target(
124148 if profile is PLCopenProfile .STANDARD_201
125149 else "CODESYS PLCopen XML"
126150 )
127- stdout .write (f"Exported { label } to { destination } \n " )
151+ verb = "Ready to export" if dry_run else "Exported"
152+ stdout .write (f"{ verb } { label } to { destination } \n " )
128153 for diagnostic in [* document .diagnostics , * result .diagnostics ]:
129154 object_name = (
130155 f" [{ diagnostic .object_name } ]" if diagnostic .object_name else ""
@@ -140,13 +165,14 @@ def _export_automationml(
140165 * ,
141166 destination : Path ,
142167 schema_path : Path | None ,
143- compile_only : bool ,
168+ compile_only : bool | None ,
144169 base_library_path : Path | None ,
145170 plcopen_reference : Path | None ,
171+ dry_run : bool ,
146172 stdout : TextIO ,
147173) -> None :
148174 """Write a semantically validated AutomationML 2.1 document."""
149- if compile_only :
175+ if compile_only is not None :
150176 raise L5XExportError (
151177 "--compile-only applies only to --target openplc"
152178 )
@@ -181,10 +207,12 @@ def _export_automationml(
181207 if schema_path is not None :
182208 validate_automationml_xml (result .xml , schema_path )
183209 validate_automationml_references (result .xml , destination )
184- destination .parent .mkdir (parents = True , exist_ok = True )
185- destination .write_text (result .xml , encoding = "utf-8" )
210+ if not dry_run :
211+ destination .parent .mkdir (parents = True , exist_ok = True )
212+ destination .write_text (result .xml , encoding = "utf-8" )
186213
187- stdout .write (f"Exported AutomationML 2.1 to { destination } \n " )
214+ verb = "Ready to export" if dry_run else "Exported"
215+ stdout .write (f"{ verb } AutomationML 2.1 to { destination } \n " )
188216 stdout .write (f"Base library reference: { base_reference } \n " )
189217 if plcopen_path is not None :
190218 stdout .write (f"PLCopen document reference: { plcopen_path } \n " )
@@ -209,6 +237,8 @@ def _export_openplc_native(
209237 destination : Path ,
210238 schema_path : Path | None ,
211239 compile_only : bool ,
240+ config : OpenPLCExportConfig ,
241+ dry_run : bool ,
212242 stdout : TextIO ,
213243) -> None :
214244 """Write the runtime-evidenced native OpenPLC project structure."""
@@ -222,19 +252,40 @@ def _export_openplc_native(
222252 raise L5XExportError (
223253 "openplc export currently requires a Controller L5X target; "
224254 f"found { document .target_type .value } "
225- )
226- result = OpenPLCNativeProjectExporter ().export (
255+ )
256+ exporter = OpenPLCNativeProjectExporter ()
257+ plan = exporter .plan (
227258 document .target ,
228- destination = destination ,
229259 project_name = document .target_name ,
230260 compile_only = compile_only ,
261+ locations = config .locations ,
262+ timer_elapsed_locations = config .timer_elapsed_locations ,
263+ counter_accumulator_locations = config .counter_accumulator_locations ,
264+ counter_status_locations = config .counter_status_locations ,
231265 )
232- stdout .write (f"Exported native OpenPLC project to { result .destination } \n " )
266+ if dry_run :
267+ files = tuple (destination / path for path in plan .documents )
268+ else :
269+ result = exporter .export (
270+ document .target ,
271+ destination = destination ,
272+ project_name = document .target_name ,
273+ compile_only = compile_only ,
274+ locations = config .locations ,
275+ timer_elapsed_locations = config .timer_elapsed_locations ,
276+ counter_accumulator_locations = (
277+ config .counter_accumulator_locations
278+ ),
279+ counter_status_locations = config .counter_status_locations ,
280+ )
281+ files = result .files
282+ verb = "Ready to export" if dry_run else "Exported"
283+ stdout .write (f"{ verb } native OpenPLC project to { destination } \n " )
233284 stdout .write (
234- f"Source program { result .source_program_name } was lowered as "
235- f"{ result .native_program_name } .\n "
285+ f"Source program { plan .source_program_name } was lowered as "
286+ f"{ plan .native_program_name } .\n "
236287 )
237- for path in result . files :
288+ for path in files :
238289 stdout .write (f"- { path } \n " )
239290 for diagnostic in document .diagnostics :
240291 object_name = (
0 commit comments