exceptionfactory commented on code in PR #8510:
URL: https://github.com/apache/nifi/pull/8510#discussion_r1525660435


##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/main/java/org/apache/nifi/py4j/PythonProcess.java:
##########
@@ -267,6 +264,21 @@ private Process launchPythonProcess(final int 
listeningPort, final String authTo
         return processBuilder.start();
     }
 
+    String resolvePythonCommand() throws IOException {
+        final File pythonCmdFile = new File(processConfig.getPythonCommand());
+        final String pythonCmd = pythonCmdFile.getName();
+        File[] virtualEnvFileList = virtualEnvHome.listFiles((file, name) -> 
file.isDirectory() && (name.equals("bin") || name.equals("Scripts")));

Review Comment:
   Recommend adding a comment regarding common names, and declaring the result 
as `final`:
   ```suggestion
           // Find command directories according to standard Python venv 
conventions
           final File[] virtualEnvCommandDirectories = 
virtualEnvHome.listFiles((file, name) -> file.isDirectory() && 
(name.equals("bin") || name.equals("Scripts")));
   ```



##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/test/java/org/apache/nifi/py4j/PythonProcessTest.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.py4j;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.nifi.python.ControllerServiceTypeLookup;
+import org.apache.nifi.python.PythonProcessConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class PythonProcessTest {
+
+    private PythonProcess pythonProcess;
+
+    private File virtualEnvHome;
+
+    @Mock
+    private PythonProcessConfig pythonProcessConfigMock;
+
+    @Mock
+    private ControllerServiceTypeLookup controllerServiceTypeLookupMock;
+
+    @BeforeEach
+    public void setUp() {
+        virtualEnvHome = new File("target/virtualEnvHome");
+        virtualEnvHome.mkdirs();
+        MockitoAnnotations.openMocks(this);

Review Comment:
   Instead of this method, the `@ExtendWith(MockitoExtension.class)` annotation 
should be used at the class level.



##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/test/java/org/apache/nifi/py4j/PythonProcessTest.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.py4j;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.nifi.python.ControllerServiceTypeLookup;
+import org.apache.nifi.python.PythonProcessConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class PythonProcessTest {
+
+    private PythonProcess pythonProcess;
+
+    private File virtualEnvHome;
+
+    @Mock
+    private PythonProcessConfig pythonProcessConfigMock;
+
+    @Mock
+    private ControllerServiceTypeLookup controllerServiceTypeLookupMock;
+
+    @BeforeEach
+    public void setUp() {
+        virtualEnvHome = new File("target/virtualEnvHome");
+        virtualEnvHome.mkdirs();
+        MockitoAnnotations.openMocks(this);
+        this.pythonProcess = new PythonProcess(this.pythonProcessConfigMock, 
this.controllerServiceTypeLookupMock, virtualEnvHome, "Controller", 
"Controller");
+    }
+    @Test
+    void testResolvePythonCommandWindows() throws IOException {
+        File scriptsDir = new File(virtualEnvHome, "Scripts");
+        scriptsDir.mkdir();
+        when(pythonProcessConfigMock.getPythonCommand()).thenReturn("python");
+        String result = this.pythonProcess.resolvePythonCommand();
+        assertEquals(this.virtualEnvHome.getAbsolutePath() + File.separator + 
"Scripts" + File.separator + "python", result);

Review Comment:
   For readability, it would be helpful to set an `expected` String value 
containing all of the elements, instead of building the expected value in this 
assertion.



##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/test/java/org/apache/nifi/py4j/PythonProcessTest.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.py4j;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.nifi.python.ControllerServiceTypeLookup;
+import org.apache.nifi.python.PythonProcessConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class PythonProcessTest {
+
+    private PythonProcess pythonProcess;
+
+    private File virtualEnvHome;
+
+    @Mock
+    private PythonProcessConfig pythonProcessConfigMock;
+
+    @Mock
+    private ControllerServiceTypeLookup controllerServiceTypeLookupMock;
+
+    @BeforeEach
+    public void setUp() {
+        virtualEnvHome = new File("target/virtualEnvHome");
+        virtualEnvHome.mkdirs();

Review Comment:
   Instead of creating a static directory in the build directory, which can 
cause build issues, the JUnit `@TempDir` annotation can be used at the class 
level to generate a random directory for each test method. See other tests for 
examples.



##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/test/java/org/apache/nifi/py4j/PythonProcessTest.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.py4j;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.nifi.python.ControllerServiceTypeLookup;
+import org.apache.nifi.python.PythonProcessConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+class PythonProcessTest {
+
+    private PythonProcess pythonProcess;
+
+    private File virtualEnvHome;
+
+    @Mock
+    private PythonProcessConfig pythonProcessConfigMock;
+
+    @Mock
+    private ControllerServiceTypeLookup controllerServiceTypeLookupMock;

Review Comment:
   In general, declaring `mock` as part of the variable name is not necessary.
   ```suggestion
       private PythonProcessConfig pythonProcessConfig;
   
       @Mock
       private ControllerServiceTypeLookup controllerServiceTypeLookup;
   
   ```



##########
nifi-nar-bundles/nifi-py4j-bundle/nifi-py4j-bridge/src/main/java/org/apache/nifi/py4j/PythonProcess.java:
##########
@@ -267,6 +264,21 @@ private Process launchPythonProcess(final int 
listeningPort, final String authTo
         return processBuilder.start();
     }
 
+    String resolvePythonCommand() throws IOException {
+        final File pythonCmdFile = new File(processConfig.getPythonCommand());
+        final String pythonCmd = pythonCmdFile.getName();
+        File[] virtualEnvFileList = virtualEnvHome.listFiles((file, name) -> 
file.isDirectory() && (name.equals("bin") || name.equals("Scripts")));
+        //Prefer bin directory
+        String commandFileExecutableDirectory = "bin";
+        if(virtualEnvFileList == null || virtualEnvFileList.length == 0) {
+            throw new IOException("Python binary directory could not be found 
in " + virtualEnvHome);
+        }else if( virtualEnvFileList.length == 1) {
+            commandFileExecutableDirectory = virtualEnvFileList[0].getName();
+        }

Review Comment:
   Instead of declaring and resetting the value, recommend declaring the 
directory as final and setting it once. Also note spacing adjustments:
   ```suggestion
           final String commandBinaryDirectory;
           if (virtualEnvFileList == null || virtualEnvFileList.length == 0) {
               throw new IOException("Python virtual environment binary 
directory could not be found in " + virtualEnvHome);
           } else if (virtualEnvFileList.length == 1) {
               commandBinaryDirectory = virtualEnvFileList[0].getName();
           } else {
               // Default to bin as the default for Linux and macOS
               commandBinaryDirectory = "bin";
           }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to