|
5 | 5 | mock_open,
|
6 | 6 | patch,
|
7 | 7 | )
|
| 8 | +import zipfile |
8 | 9 |
|
9 | 10 | import pytest
|
10 | 11 | import requests
|
|
28 | 29 | get_data_transform_config,
|
29 | 30 | get_deployments,
|
30 | 31 | run_data_transform,
|
| 32 | + upload_zip, |
31 | 33 | verify_data_transform_config,
|
32 | 34 | wait_for_deployment,
|
33 |
| - zip_and_upload_directory, |
| 35 | + zip, |
34 | 36 | )
|
35 | 37 |
|
36 | 38 |
|
@@ -134,22 +136,100 @@ def test_create_deployment_conflict(self, mock_make_api_call):
|
134 | 136 | create_deployment(access_token, metadata)
|
135 | 137 |
|
136 | 138 |
|
137 |
| -class TestZipAndUploadDirectory: |
138 |
| - @patch("datacustomcode.deploy.shutil.make_archive") |
| 139 | +class TestZip: |
| 140 | + @patch("datacustomcode.deploy.has_nonempty_requirements_file") |
| 141 | + @patch("datacustomcode.deploy.prepare_dependency_archive") |
| 142 | + @patch("zipfile.ZipFile") |
| 143 | + @patch("os.walk") |
| 144 | + def test_zip_with_requirements( |
| 145 | + self, mock_walk, mock_zipfile, mock_prepare, mock_has_requirements |
| 146 | + ): |
| 147 | + """Test zipping a directory with requirements.txt.""" |
| 148 | + mock_has_requirements.return_value = True |
| 149 | + mock_zipfile_instance = MagicMock() |
| 150 | + mock_zipfile.return_value.__enter__.return_value = mock_zipfile_instance |
| 151 | + mock_zipfile_instance.write = MagicMock() |
| 152 | + |
| 153 | + # Mock os.walk to return some test files |
| 154 | + mock_walk.return_value = [ |
| 155 | + ("/test/dir", ["subdir"], ["file1.py", "file2.py"]), |
| 156 | + ("/test/dir/subdir", [], ["file3.py"]), |
| 157 | + ] |
| 158 | + |
| 159 | + zip("/test/dir") |
| 160 | + |
| 161 | + mock_has_requirements.assert_called_once_with("/test/dir") |
| 162 | + mock_prepare.assert_called_once_with("/test/dir") |
| 163 | + mock_zipfile.assert_called_once_with( |
| 164 | + "deployment.zip", "w", zipfile.ZIP_DEFLATED |
| 165 | + ) |
| 166 | + assert mock_zipfile_instance.write.call_count == 3 # One call per file |
| 167 | + |
| 168 | + @patch("datacustomcode.deploy.has_nonempty_requirements_file") |
| 169 | + @patch("datacustomcode.deploy.prepare_dependency_archive") |
| 170 | + @patch("zipfile.ZipFile") |
| 171 | + @patch("os.walk") |
| 172 | + def test_zip_without_requirements( |
| 173 | + self, mock_walk, mock_zipfile, mock_prepare, mock_has_requirements |
| 174 | + ): |
| 175 | + """Test zipping a directory without requirements.txt.""" |
| 176 | + mock_has_requirements.return_value = False |
| 177 | + mock_zipfile_instance = MagicMock() |
| 178 | + mock_zipfile.return_value.__enter__.return_value = mock_zipfile_instance |
| 179 | + mock_zipfile_instance.write = MagicMock() |
| 180 | + |
| 181 | + # Mock os.walk to return some test files |
| 182 | + mock_walk.return_value = [ |
| 183 | + ("/test/dir", ["subdir"], ["file1.py", "file2.py"]), |
| 184 | + ("/test/dir/subdir", [], ["file3.py"]), |
| 185 | + ] |
| 186 | + |
| 187 | + zip("/test/dir") |
| 188 | + |
| 189 | + mock_has_requirements.assert_called_once_with("/test/dir") |
| 190 | + mock_prepare.assert_not_called() |
| 191 | + mock_zipfile.assert_called_once_with( |
| 192 | + "deployment.zip", "w", zipfile.ZIP_DEFLATED |
| 193 | + ) |
| 194 | + assert mock_zipfile_instance.write.call_count == 3 # One call per file |
| 195 | + |
| 196 | + |
| 197 | +class TestUploadZip: |
139 | 198 | @patch("datacustomcode.deploy.requests.put")
|
140 | 199 | @patch("builtins.open", new_callable=mock_open, read_data=b"test data")
|
141 |
| - def test_zip_and_upload_directory(self, mock_file, mock_put, mock_make_archive): |
142 |
| - """Test zipping and uploading a directory.""" |
| 200 | + def test_upload_zip_success(self, mock_file, mock_put): |
| 201 | + """Test successful zip upload.""" |
143 | 202 | mock_response = MagicMock()
|
144 | 203 | mock_put.return_value = mock_response
|
145 | 204 |
|
146 |
| - zip_and_upload_directory("/test/dir", "https://upload.example.com") |
| 205 | + upload_zip("https://upload.example.com") |
147 | 206 |
|
148 |
| - mock_make_archive.assert_called_once_with("deployment", "zip", "/test/dir") |
149 | 207 | mock_file.assert_called_once_with("deployment.zip", "rb")
|
150 |
| - mock_put.assert_called_once() |
| 208 | + mock_put.assert_called_once_with( |
| 209 | + "https://upload.example.com", |
| 210 | + data=mock_file.return_value, |
| 211 | + headers={"Content-Type": "application/zip"}, |
| 212 | + ) |
151 | 213 | mock_response.raise_for_status.assert_called_once()
|
152 | 214 |
|
| 215 | + @patch("datacustomcode.deploy.requests.put") |
| 216 | + @patch("builtins.open", new_callable=mock_open, read_data=b"test data") |
| 217 | + def test_upload_zip_http_error(self, mock_file, mock_put): |
| 218 | + """Test zip upload with HTTP error.""" |
| 219 | + mock_response = MagicMock() |
| 220 | + mock_response.raise_for_status.side_effect = requests.HTTPError("Upload failed") |
| 221 | + mock_put.return_value = mock_response |
| 222 | + |
| 223 | + with pytest.raises(requests.HTTPError, match="Upload failed"): |
| 224 | + upload_zip("https://upload.example.com") |
| 225 | + |
| 226 | + mock_file.assert_called_once_with("deployment.zip", "rb") |
| 227 | + mock_put.assert_called_once_with( |
| 228 | + "https://upload.example.com", |
| 229 | + data=mock_file.return_value, |
| 230 | + headers={"Content-Type": "application/zip"}, |
| 231 | + ) |
| 232 | + |
153 | 233 |
|
154 | 234 | class TestGetDeployments:
|
155 | 235 | @patch("datacustomcode.deploy._make_api_call")
|
@@ -328,14 +408,16 @@ class TestDeployFull:
|
328 | 408 | @patch("datacustomcode.deploy.prepare_dependency_archive")
|
329 | 409 | @patch("datacustomcode.deploy.verify_data_transform_config")
|
330 | 410 | @patch("datacustomcode.deploy.create_deployment")
|
331 |
| - @patch("datacustomcode.deploy.zip_and_upload_directory") |
| 411 | + @patch("datacustomcode.deploy.zip") |
| 412 | + @patch("datacustomcode.deploy.upload_zip") |
332 | 413 | @patch("datacustomcode.deploy.wait_for_deployment")
|
333 | 414 | @patch("datacustomcode.deploy.create_data_transform")
|
334 | 415 | def test_deploy_full(
|
335 | 416 | self,
|
336 | 417 | mock_create_transform,
|
337 | 418 | mock_wait,
|
338 |
| - mock_zip_upload, |
| 419 | + mock_upload_zip, |
| 420 | + mock_zip, |
339 | 421 | mock_create_deployment,
|
340 | 422 | mock_verify_config,
|
341 | 423 | mock_prepare,
|
@@ -371,9 +453,8 @@ def test_deploy_full(
|
371 | 453 | mock_prepare.assert_called_once_with("/test/dir")
|
372 | 454 | mock_verify_config.assert_called_once_with("/test/dir")
|
373 | 455 | mock_create_deployment.assert_called_once_with(access_token, metadata)
|
374 |
| - mock_zip_upload.assert_called_once_with( |
375 |
| - "/test/dir", "https://upload.example.com" |
376 |
| - ) |
| 456 | + mock_zip.assert_called_once_with("/test/dir") |
| 457 | + mock_upload_zip.assert_called_once_with("https://upload.example.com") |
377 | 458 | mock_wait.assert_called_once_with(access_token, metadata, callback)
|
378 | 459 | mock_create_transform.assert_called_once_with(
|
379 | 460 | "/test/dir", access_token, metadata
|
|
0 commit comments