22
33from unittest .mock import (
44 MagicMock ,
5+ call ,
56 mock_open ,
67 patch ,
7- call ,
88)
99import zipfile
1010
4141
4242class TestPrepareDependencyArchive :
4343 # Shared expected commands
44- EXPECTED_DOCKER_IMAGES_CMD = "docker images -q datacloud-custom-code-dependency-builder"
45- EXPECTED_BUILD_CMD = "DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build -t datacloud-custom-code-dependency-builder -f Dockerfile.dependencies ."
44+ EXPECTED_DOCKER_IMAGES_CMD = (
45+ "docker images -q datacloud-custom-code-dependency-builder"
46+ )
47+ EXPECTED_BUILD_CMD = (
48+ "DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build "
49+ "-t datacloud-custom-code-dependency-builder -f Dockerfile.dependencies ."
50+ )
4651 EXPECTED_DOCKER_RUN_CMD = (
4752 "DOCKER_DEFAULT_PLATFORM=linux/amd64 docker run --rm "
4853 "-v /tmp/test_dir:/workspace "
@@ -89,7 +94,10 @@ def test_prepare_dependency_archive_image_exists(
8994 mock_makedirs .assert_called_once_with ("payload/archives" , exist_ok = True )
9095
9196 # Verify archive was copied back
92- mock_copy .assert_any_call ("/tmp/test_dir/native_dependencies.tar.gz" , "payload/archives/native_dependencies.tar.gz" )
97+ mock_copy .assert_any_call (
98+ "/tmp/test_dir/native_dependencies.tar.gz" ,
99+ "payload/archives/native_dependencies.tar.gz" ,
100+ )
93101
94102 @patch ("datacustomcode.deploy.cmd_output" )
95103 @patch ("datacustomcode.deploy.shutil.copy" )
@@ -132,7 +140,10 @@ def test_prepare_dependency_archive_build_image(
132140 mock_makedirs .assert_called_once_with ("payload/archives" , exist_ok = True )
133141
134142 # Verify archive was copied back
135- mock_copy .assert_any_call ("/tmp/test_dir/native_dependencies.tar.gz" , "payload/archives/native_dependencies.tar.gz" )
143+ mock_copy .assert_any_call (
144+ "/tmp/test_dir/native_dependencies.tar.gz" ,
145+ "payload/archives/native_dependencies.tar.gz" ,
146+ )
136147
137148 @patch ("datacustomcode.deploy.cmd_output" )
138149 @patch ("datacustomcode.deploy.shutil.copy" )
@@ -151,9 +162,12 @@ def test_prepare_dependency_archive_docker_build_failure(
151162
152163 # Mock cmd_output to return None for image check, then raise exception for build
153164 from datacustomcode .cmd import CalledProcessError
165+
154166 mock_cmd_output .side_effect = [
155167 None , # Image doesn't exist
156- CalledProcessError (1 , ("docker" , "build" ), b"Build failed" , b"Error" ), # Build fails
168+ CalledProcessError (
169+ 1 , ("docker" , "build" ), b"Build failed" , b"Error"
170+ ), # Build fails
157171 ]
158172
159173 with pytest .raises (CalledProcessError , match = "Build failed" ):
@@ -182,9 +196,12 @@ def test_prepare_dependency_archive_docker_run_failure(
182196
183197 # Mock cmd_output to return image ID, then raise exception for run
184198 from datacustomcode .cmd import CalledProcessError
199+
185200 mock_cmd_output .side_effect = [
186201 "abc123" , # Image exists
187- CalledProcessError (1 , ("docker" , "run" ), b"Run failed" , b"Error" ), # Run fails
202+ CalledProcessError (
203+ 1 , ("docker" , "run" ), b"Run failed" , b"Error"
204+ ), # Run fails
188205 ]
189206
190207 with pytest .raises (CalledProcessError , match = "Run failed" ):
@@ -234,35 +251,51 @@ def test_prepare_dependency_archive_file_copy_failure(
234251class TestHasNonemptyRequirementsFile :
235252 @patch ("datacustomcode.deploy.os.path.dirname" )
236253 @patch ("datacustomcode.deploy.os.path.isfile" )
237- @patch ("builtins.open" , new_callable = mock_open , read_data = "numpy==1.21.0\n pandas==1.3.0" )
254+ @patch (
255+ "builtins.open" ,
256+ new_callable = mock_open ,
257+ read_data = "numpy==1.21.0\n pandas==1.3.0" ,
258+ )
238259 def test_has_nonempty_requirements_file_with_dependencies (
239260 self , mock_file , mock_isfile , mock_dirname
240261 ):
241- """Test has_nonempty_requirements_file when requirements.txt has dependencies."""
262+ """
263+ Test has_nonempty_requirements_file when requirements.txt has dependencies.
264+ """
242265 mock_dirname .return_value = "/parent/dir"
243266 mock_isfile .return_value = True
244267
245268 result = has_nonempty_requirements_file ("/test/dir" )
246269
247270 assert result is True
248271 mock_isfile .assert_called_once_with ("/parent/dir/requirements.txt" )
249- mock_file .assert_called_once_with ("/parent/dir/requirements.txt" , "r" , encoding = "utf-8" )
272+ mock_file .assert_called_once_with (
273+ "/parent/dir/requirements.txt" , "r" , encoding = "utf-8"
274+ )
250275
251276 @patch ("datacustomcode.deploy.os.path.dirname" )
252277 @patch ("datacustomcode.deploy.os.path.isfile" )
253- @patch ("builtins.open" , new_callable = mock_open , read_data = "# This is a comment\n \n # Another comment" )
278+ @patch (
279+ "builtins.open" ,
280+ new_callable = mock_open ,
281+ read_data = "# This is a comment\n \n # Another comment" ,
282+ )
254283 def test_has_nonempty_requirements_file_only_comments (
255284 self , mock_file , mock_isfile , mock_dirname
256285 ):
257- """Test has_nonempty_requirements_file when requirements.txt has only comments."""
286+ """
287+ Test has_nonempty_requirements_file when requirements.txt has only comments.
288+ """
258289 mock_dirname .return_value = "/parent/dir"
259290 mock_isfile .return_value = True
260291
261292 result = has_nonempty_requirements_file ("/test/dir" )
262293
263294 assert result is False
264295 mock_isfile .assert_called_once_with ("/parent/dir/requirements.txt" )
265- mock_file .assert_called_once_with ("/parent/dir/requirements.txt" , "r" , encoding = "utf-8" )
296+ mock_file .assert_called_once_with (
297+ "/parent/dir/requirements.txt" , "r" , encoding = "utf-8"
298+ )
266299
267300 @patch ("datacustomcode.deploy.os.path.dirname" )
268301 @patch ("datacustomcode.deploy.os.path.isfile" )
@@ -278,13 +311,13 @@ def test_has_nonempty_requirements_file_empty_file(
278311
279312 assert result is False
280313 mock_isfile .assert_called_once_with ("/parent/dir/requirements.txt" )
281- mock_file .assert_called_once_with ("/parent/dir/requirements.txt" , "r" , encoding = "utf-8" )
314+ mock_file .assert_called_once_with (
315+ "/parent/dir/requirements.txt" , "r" , encoding = "utf-8"
316+ )
282317
283318 @patch ("datacustomcode.deploy.os.path.dirname" )
284319 @patch ("datacustomcode.deploy.os.path.isfile" )
285- def test_has_nonempty_requirements_file_not_exists (
286- self , mock_isfile , mock_dirname
287- ):
320+ def test_has_nonempty_requirements_file_not_exists (self , mock_isfile , mock_dirname ):
288321 """Test has_nonempty_requirements_file when requirements.txt doesn't exist."""
289322 mock_dirname .return_value = "/parent/dir"
290323 mock_isfile .return_value = False
@@ -308,11 +341,17 @@ def test_has_nonempty_requirements_file_permission_error(
308341
309342 assert result is False
310343 mock_isfile .assert_called_once_with ("/parent/dir/requirements.txt" )
311- mock_file .assert_called_once_with ("/parent/dir/requirements.txt" , "r" , encoding = "utf-8" )
344+ mock_file .assert_called_once_with (
345+ "/parent/dir/requirements.txt" , "r" , encoding = "utf-8"
346+ )
312347
313348 @patch ("datacustomcode.deploy.os.path.dirname" )
314349 @patch ("datacustomcode.deploy.os.path.isfile" )
315- @patch ("builtins.open" , new_callable = mock_open , read_data = "numpy==1.21.0\n # Comment\n pandas==1.3.0" )
350+ @patch (
351+ "builtins.open" ,
352+ new_callable = mock_open ,
353+ read_data = "numpy==1.21.0\n # Comment\n pandas==1.3.0" ,
354+ )
316355 def test_has_nonempty_requirements_file_mixed_content (
317356 self , mock_file , mock_isfile , mock_dirname
318357 ):
@@ -324,7 +363,9 @@ def test_has_nonempty_requirements_file_mixed_content(
324363
325364 assert result is True
326365 mock_isfile .assert_called_once_with ("/parent/dir/requirements.txt" )
327- mock_file .assert_called_once_with ("/parent/dir/requirements.txt" , "r" , encoding = "utf-8" )
366+ mock_file .assert_called_once_with (
367+ "/parent/dir/requirements.txt" , "r" , encoding = "utf-8"
368+ )
328369
329370
330371class TestMakeApiCall :
0 commit comments