11package nl .esciencecenter .e3dchem .python ;
22
3- import java .util .Arrays ;
4- import java .util .Collection ;
5- import java .util .Collections ;
63import java .util .HashSet ;
74import java .util .Locale ;
8- import java .util .Objects ;
95import java .util .Set ;
106
11- import org .knime .python2 .DefaultPythonCommand ;
7+ import org .knime .core .node .InvalidSettingsException ;
8+ import org .knime .core .node .NodeSettingsRO ;
9+ import org .knime .core .node .NodeSettingsWO ;
10+ import org .knime .core .node .workflow .FlowVariable ;
1211import org .knime .python2 .PythonCommand ;
1312import org .knime .python2 .PythonModuleSpec ;
1413import org .knime .python2 .PythonVersion ;
14+ import org .knime .python2 .config .PythonCommandFlowVariableConfig ;
1515import org .knime .python2 .extensions .serializationlibrary .SentinelOption ;
1616import org .knime .python2 .extensions .serializationlibrary .SerializationOptions ;
1717import org .knime .python2 .generic .VariableNames ;
1818import org .knime .python2 .kernel .PythonKernelOptions ;
1919import org .knime .python2 .prefs .PythonPreferences ;
20- import org .knime .core .node .InvalidSettingsException ;
21- import org .knime .core .node .NodeSettingsRO ;
22- import org .knime .core .node .NodeSettingsWO ;
23- import org .knime .core .node .workflow .FlowVariable ;
2420
2521/**
2622 * Configuration for {@link PythonWrapperNodeModel}.
3127 */
3228public class PythonWrapperNodeConfig {
3329 private static final String CFG_PYTHON_VERSION_OPTION = "pythonVersionOption" ;
34- static final String CFG_PYTHON2COMMAND = "python2Command" ;
35- static final String CFG_PYTHON3COMMAND = "python3Command" ;
30+ private static final String CFG_PYTHON2_COMMAND = "python2Command" ;
31+
32+ private static final String CFG_PYTHON3_COMMAND = "python3Command" ;
3633 private static final String CFG_CONVERT_MISSING_TO_PYTHON = "convertMissingToPython" ;
3734 private static final String CFG_CONVERT_MISSING_FROM_PYTHON = "convertMissingFromPython" ;
3835 private static final String CFG_SENTINEL_OPTION = "sentinelOption" ;
3936 private static final String CFG_SENTINEL_VALUE = "sentinelValue" ;
4037 private static final String CFG_CHUNK_SIZE = "chunkSize" ;
4138
42- /**
43- * {@link #m_python2Command} and {@link #m_python3Command} are special in that they currently aren't configurable
44- * via a Python scripting node's dialog but only using flow variables. If no respective flow variables are set,
45- * their value is retrieved from the Python preferences.
46- */
47- private static final String INDICATE_FALLBACK_TO_PREFERENCES_COMMAND_VALUE = "" ;
48-
4939 private PythonVersion m_pythonVersion = PythonPreferences .getPythonVersionPreference ();
5040
51- /**
52- * {@code null} means to fall back to {@link PythonPreferences#getPython2CommandPreference()}.
53- */
54- private PythonCommand m_python2Command = null ;
41+ private PythonCommandFlowVariableConfig m_python2CommandConfig = new PythonCommandFlowVariableConfig (CFG_PYTHON2_COMMAND ,
42+ PythonVersion .PYTHON2 , PythonPreferences ::getCondaInstallationPath );
5543
56- /**
57- * {@code null} means to fall back to {@link PythonPreferences#getPython2CommandPreference()}.
58- */
59- private PythonCommand m_python3Command = null ;
44+ private PythonCommandFlowVariableConfig m_python3CommandConfig = new PythonCommandFlowVariableConfig (CFG_PYTHON3_COMMAND ,
45+ PythonVersion .PYTHON3 , PythonPreferences ::getCondaInstallationPath );
6046
6147 private int m_chunkSize = SerializationOptions .DEFAULT_CHUNK_SIZE ;
6248
@@ -118,13 +104,20 @@ public void setPythonVersion(final PythonVersion pythonVersion) {
118104 m_pythonVersion = pythonVersion ;
119105 }
120106
107+ /**
108+ * @return The config of the Python 2 command.
109+ */
110+ public PythonCommandFlowVariableConfig getPython2CommandConfig () {
111+ return m_python2CommandConfig ;
112+ }
113+
121114 /**
122115 * @return The Python 2 command to use. May be {@code null} in which case no specific Python 2 command is configured
123116 * and one has to resort to - e.g., - the {@link PythonPreferences#getPython2CommandPreference() global
124117 * preferences}.
125118 */
126119 public PythonCommand getPython2Command () {
127- return m_python2Command ;
120+ return m_python2CommandConfig . getCommand (). orElse ( null ) ;
128121 }
129122
130123 /**
@@ -133,16 +126,23 @@ public PythonCommand getPython2Command() {
133126 * {@link PythonPreferences#getPython2CommandPreference() global preferences}.
134127 */
135128 public void setPython2Command (final PythonCommand python2Command ) {
136- m_python2Command = python2Command ;
129+ m_python2CommandConfig .setCommand (python2Command );
130+ }
131+
132+ /**
133+ * @return The config of the Python 3 command.
134+ */
135+ public PythonCommandFlowVariableConfig getPython3CommandConfig () {
136+ return m_python3CommandConfig ;
137137 }
138138
139139 /**
140140 * @return The Python 3 command to use. May be {@code null} in which case no specific Python 3 command is configured
141141 * and one has to resort to - e.g., - the {@link PythonPreferences#getPython3CommandPreference() global
142142 * preferences}.
143143 */
144- public PythonCommand getPython3Command () {
145- return m_python3Command ;
144+ public PythonCommand getPython3Command () {
145+ return m_python3CommandConfig . getCommand (). orElse ( null ) ;
146146 }
147147
148148 /**
@@ -151,9 +151,9 @@ public PythonCommand getPython3Command() {
151151 * {@link PythonPreferences#getPython3CommandPreference() global preferences}.
152152 */
153153 public void setPython3Command (final PythonCommand python3Command ) {
154- m_python3Command = python3Command ;
154+ m_python3CommandConfig . setCommand ( python3Command ) ;
155155 }
156-
156+
157157 /**
158158 *
159159 * @return The configured number of rows to transfer to/from Python per chunk of an input/output table.
@@ -273,13 +273,13 @@ public void saveTo(final NodeSettingsWO settings) {
273273 */
274274 public void saveToInDialog (NodeSettingsWO settings ) {
275275 settings .addString (CFG_PYTHON_VERSION_OPTION , getPythonVersion ().getId ());
276- settings .addString (CFG_PYTHON2COMMAND , commandToString (getPython2Command ()));
277- settings .addString (CFG_PYTHON3COMMAND , commandToString (getPython3Command ()));
278276 settings .addInt (CFG_CHUNK_SIZE , getChunkSize ());
279277 settings .addBoolean (CFG_CONVERT_MISSING_TO_PYTHON , getConvertMissingToPython ());
280278 settings .addBoolean (CFG_CONVERT_MISSING_FROM_PYTHON , getConvertMissingFromPython ());
281279 settings .addString (CFG_SENTINEL_OPTION , getSentinelOption ().name ());
282280 settings .addInt (CFG_SENTINEL_VALUE , getSentinelValue ());
281+ m_python2CommandConfig .saveSettingsTo (settings );
282+ m_python3CommandConfig .saveSettingsTo (settings );
283283 }
284284
285285 /**
@@ -300,39 +300,22 @@ public void loadFrom(final NodeSettingsRO settings) throws InvalidSettingsExcept
300300 *
301301 * @param settings
302302 * The settings to load from
303+ * @throws InvalidSettingsException
303304 */
304- public void loadFromInDialog (final NodeSettingsRO settings ) {
305+ public void loadFromInDialog (final NodeSettingsRO settings ) throws InvalidSettingsException {
305306 final String pythonVersionString = settings .getString (CFG_PYTHON_VERSION_OPTION , getPythonVersion ().getId ());
306307 // Backward compatibility: old saved versions may be all upper case.
307308 setPythonVersion (PythonVersion .fromId (pythonVersionString .toLowerCase (Locale .ROOT )));
308- final String python2CommandString =
309- settings .getString (CFG_PYTHON2COMMAND , commandToString (getPython2Command ()));
310- setPython2Command (commandFromString (python2CommandString ));
311- final String python3CommandString =
312- settings .getString (CFG_PYTHON3COMMAND , commandToString (getPython3Command ()));
313- setPython3Command (commandFromString (python3CommandString ));
314309 setChunkSize (settings .getInt (CFG_CHUNK_SIZE , getChunkSize ()));
315310 setConvertMissingToPython (settings .getBoolean (CFG_CONVERT_MISSING_TO_PYTHON , getConvertMissingToPython ()));
316311 setConvertMissingFromPython (
317312 settings .getBoolean (CFG_CONVERT_MISSING_FROM_PYTHON , getConvertMissingFromPython ()));
318313 setSentinelOption (SentinelOption .valueOf (settings .getString (CFG_SENTINEL_OPTION , getSentinelOption ().name ())));
319314 setSentinelValue (settings .getInt (CFG_SENTINEL_VALUE , getSentinelValue ()));
315+ m_python2CommandConfig .loadSettingsFrom (settings );
316+ m_python3CommandConfig .loadSettingsFrom (settings );
320317 }
321318
322- private static String commandToString (final PythonCommand command ) {
323- return command != null //
324- ? command .toString () //
325- : INDICATE_FALLBACK_TO_PREFERENCES_COMMAND_VALUE ;
326- }
327-
328- private static PythonCommand commandFromString (final String commandString ) {
329- return Objects .equals (commandString , INDICATE_FALLBACK_TO_PREFERENCES_COMMAND_VALUE ) //
330- ? null //
331- // TODO: This only works for ordinary paths ("manual configuration"), not for Conda directory + environment
332- // name ("Conda configuration").
333- : new DefaultPythonCommand (commandString );
334- }
335-
336319 /**
337320 * Set of key/value pairs which inside Python script will be a dictionary
338321 * named by {@link #getOptionsName()}.
@@ -352,9 +335,8 @@ public Set<FlowVariable> getOptionsValues() {
352335 public PythonKernelOptions getKernelOptions () {
353336 final SerializationOptions serializationOptions = new SerializationOptions (getChunkSize (),
354337 getConvertMissingToPython (), getConvertMissingFromPython (), getSentinelOption (), getSentinelValue ());
355- PythonKernelOptions opt = new PythonKernelOptions (getPythonVersion (), getPython2Command (), getPython3Command (),
356- serializationOptions );
357- return opt .forAddedAdditionalRequiredModules (additionalRequiredModules ).forExternalCustomPath (externalCustomPath );
338+ PythonKernelOptions opt = new PythonKernelOptions ();
339+ return opt .forSerializationOptions (serializationOptions ).forAddedAdditionalRequiredModules (additionalRequiredModules ).forExternalCustomPath (externalCustomPath );
358340 }
359341
360342 /**
0 commit comments