ciocore 9.1.0rc3__py2.py3-none-any.whl → 9.1.1b1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ciocore might be problematic. Click here for more details.
- ciocore/VERSION +1 -1
- ciocore/cli.py +113 -26
- ciocore/docsite/apidoc/api_client/index.html +33 -33
- ciocore/docsite/apidoc/config/index.html +11 -11
- ciocore/docsite/apidoc/data/index.html +10 -10
- ciocore/docsite/apidoc/hardware_set/index.html +32 -32
- ciocore/docsite/apidoc/package_environment/index.html +13 -13
- ciocore/docsite/apidoc/package_tree/index.html +28 -28
- ciocore/docsite/how-to-guides/index.html +2 -2
- ciocore/docsite/sitemap.xml.gz +0 -0
- ciocore/downloader/base_downloader.py +71 -33
- {ciocore-9.1.0rc3.dist-info → ciocore-9.1.1b1.dist-info}/METADATA +70 -7
- {ciocore-9.1.0rc3.dist-info → ciocore-9.1.1b1.dist-info}/RECORD +18 -18
- tests/test_base_downloader.py +189 -13
- tests/test_config.py +15 -4
- {ciocore-9.1.0rc3.dist-info → ciocore-9.1.1b1.dist-info}/WHEEL +0 -0
- {ciocore-9.1.0rc3.dist-info → ciocore-9.1.1b1.dist-info}/entry_points.txt +0 -0
- {ciocore-9.1.0rc3.dist-info → ciocore-9.1.1b1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ciocore
|
|
3
|
-
Version: 9.1.
|
|
3
|
+
Version: 9.1.1b1
|
|
4
4
|
Summary: Core functionality for Conductor's client tools
|
|
5
5
|
Home-page: https://github.com/ConductorTechnologies/ciocore
|
|
6
6
|
Author: conductor
|
|
@@ -34,8 +34,10 @@ conductor --help
|
|
|
34
34
|
Get help for a specific sub command
|
|
35
35
|
```bash
|
|
36
36
|
conductor downloader --help
|
|
37
|
-
conductor
|
|
38
|
-
conductor
|
|
37
|
+
conductor upload --help
|
|
38
|
+
conductor download --help
|
|
39
|
+
conductor packages --help
|
|
40
|
+
conductor docs --help
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
Example API usage
|
|
@@ -46,15 +48,76 @@ print(api_client.request_software_packages()[0])
|
|
|
46
48
|
```
|
|
47
49
|
## Contributing
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
If you are contributing to the Conductor Core project, it's recommended to set up a virtual environment to manage dependencies and isolate your development environment. Follow these steps to get started:
|
|
52
|
+
|
|
53
|
+
### Setting Up a Virtual Environment
|
|
54
|
+
|
|
55
|
+
1. **Create a Virtual Environment:**
|
|
56
|
+
|
|
57
|
+
Navigate to the root directory of the project and create a virtual environment:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m venv venv
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. **Activate the Virtual Environment:**
|
|
64
|
+
|
|
65
|
+
- On Windows:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
.\venv\Scripts\activate
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- On macOS and Linux:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
source venv/bin/activate
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
3. **Install the Package in Editable Mode:**
|
|
78
|
+
|
|
79
|
+
With the virtual environment activated, install the package in editable mode. This allows you to make changes to the code and test them without reinstalling the package:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install -r requirements.txt # if you want to publish and so on.
|
|
83
|
+
pip install -e . # To develop and test the package.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Running Conductor Commands
|
|
87
|
+
|
|
88
|
+
Once the package is installed, you can run any Conductor command. Here are a few examples:
|
|
89
|
+
|
|
90
|
+
- **Display Help for the Main Command:**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
conductor --help
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- **Get Help for Specific Subcommands:**
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
conductor download --help
|
|
100
|
+
conductor upload --help
|
|
101
|
+
conductor packages --help
|
|
102
|
+
conductor docs
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
These commands will provide you with detailed information on how to use the Conductor CLI and its subcommands.
|
|
106
|
+
|
|
107
|
+
For more detailed contribution guidelines, please refer to the [CONTRIBUTING](CONTRIBUTING.md) document.
|
|
50
108
|
|
|
51
109
|
## Changelog
|
|
52
110
|
|
|
53
|
-
## Version:9.1.
|
|
111
|
+
## Version:9.1.1-beta.1 -- 20 Feb 2025
|
|
112
|
+
|
|
113
|
+
* Added contributor guidelines section to README.md
|
|
114
|
+
* Added validation for job IDs and output paths in download command
|
|
115
|
+
* Improved output path handling in BaseDownloader class
|
|
54
116
|
|
|
117
|
+
## Version:9.1.0 -- 20 Dec 2024
|
|
55
118
|
|
|
56
|
-
*
|
|
57
|
-
*
|
|
119
|
+
* Added support for new required JWT authentication parameters
|
|
120
|
+
* Removed Python 2.7 compatibility to focus on modern Python versions
|
|
58
121
|
|
|
59
122
|
## Version:8.3.3 -- 04 Dec 2024
|
|
60
123
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
ciocore/VERSION,sha256=
|
|
1
|
+
ciocore/VERSION,sha256=FuQPkXEkRVKmKtO24mViA1RsTr3EjFrrRdgT_pg8YAg,12
|
|
2
2
|
ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
|
|
3
3
|
ciocore/api_client.py,sha256=KKL7TsYygNcfkFZDPPq1CSJsrVN_QLK4PqP44vXsCQg,33101
|
|
4
|
-
ciocore/cli.py,sha256=
|
|
4
|
+
ciocore/cli.py,sha256=Vzoc_3UBQIQfGaoG-Ef2Klh2IBMj5dJCAEiWvWH6tns,17477
|
|
5
5
|
ciocore/client_db.py,sha256=tTz3bl2xeDPPcYSDS3g3QgV_xYihJMx0Kj6OeN2klK0,12978
|
|
6
6
|
ciocore/common.py,sha256=mBIS6KiYoQsjWe6aIFUGRRvCMl8BIN2kmLZ4J8icap8,14982
|
|
7
7
|
ciocore/conductor_submit.py,sha256=bxvzdyNzscAOOOsqTvAYh5DQsTWyCQJNb16Mf-n_F0M,9702
|
|
@@ -25,14 +25,14 @@ ciocore/docsite/index.html,sha256=NEK4HaX2yaetTajVtQuTmS9C5cPnkAtxgeKEj7wQ9t0,20
|
|
|
25
25
|
ciocore/docsite/logo.png,sha256=gArgFFWdw8w985-0TkuGIgU_pW9sziEMZdqytXb5WLo,2825
|
|
26
26
|
ciocore/docsite/objects.inv,sha256=XwmLactPEWWC4fAWqHNPBXGsluRxLLTrwDLQqq51ONY,775
|
|
27
27
|
ciocore/docsite/sitemap.xml,sha256=M_V85zl0y2adRvzJAnoCxlZH_Hl7TLnIb1A-6l_xGmI,109
|
|
28
|
-
ciocore/docsite/sitemap.xml.gz,sha256=
|
|
29
|
-
ciocore/docsite/apidoc/api_client/index.html,sha256=
|
|
28
|
+
ciocore/docsite/sitemap.xml.gz,sha256=frEWw8iRQPdzBRxKi34sMHbxRw6VmtUsfa4Rvqf6Su8,127
|
|
29
|
+
ciocore/docsite/apidoc/api_client/index.html,sha256=6d-3jDp3qOOWjLlOjbJY8SehOb2ZeX3iXPNEynrA3yA,190619
|
|
30
30
|
ciocore/docsite/apidoc/apidoc/index.html,sha256=GOSvv6KZPOtgekgshRE4j7aDvJkkaiBQLwA_By9J94g,26171
|
|
31
|
-
ciocore/docsite/apidoc/config/index.html,sha256=
|
|
32
|
-
ciocore/docsite/apidoc/data/index.html,sha256=
|
|
33
|
-
ciocore/docsite/apidoc/hardware_set/index.html,sha256=
|
|
34
|
-
ciocore/docsite/apidoc/package_environment/index.html,sha256=
|
|
35
|
-
ciocore/docsite/apidoc/package_tree/index.html,sha256=
|
|
31
|
+
ciocore/docsite/apidoc/config/index.html,sha256=NAPA-09l_r0CLYPruJZNeRzX_FTucV_oExMpK83EAcY,72835
|
|
32
|
+
ciocore/docsite/apidoc/data/index.html,sha256=ogsCr6IaLXojBInDdIWh74KAsq7W5AILVsHWJa-3t0A,51926
|
|
33
|
+
ciocore/docsite/apidoc/hardware_set/index.html,sha256=9dT-7TuEu8bknDmL51a3nuwUli1BWw1_nMfJRaqqIc4,123985
|
|
34
|
+
ciocore/docsite/apidoc/package_environment/index.html,sha256=mP0vktOJJxo3etQ4755etLDNiO_LrDXVVcoG0s6lIng,69570
|
|
35
|
+
ciocore/docsite/apidoc/package_tree/index.html,sha256=lsXi0MT4PHABR-uhPKb8Yaq4jWMve4Yxk5V3EgG0zxQ,109859
|
|
36
36
|
ciocore/docsite/assets/_mkdocstrings.css,sha256=K3bqYEmxlOHQ3-M11JNbBWHCBDBLarkFRm8HuEYrAG4,341
|
|
37
37
|
ciocore/docsite/assets/images/favicon.png,sha256=AjhUxD_Eslt5XuSVHIAZ494Fk__rb5GLXR8qm0elfP4,1870
|
|
38
38
|
ciocore/docsite/assets/javascripts/bundle.4e31edb1.min.js,sha256=vMxCR_BtNIcbmbPV6j8Z-YDLQ9ckt4RzvGuzCTg034s,97250
|
|
@@ -79,12 +79,12 @@ ciocore/docsite/cmdline/docs/index.html,sha256=-TMLZX8gnXwRcWoaylF8zHRwWAo4BHk6g
|
|
|
79
79
|
ciocore/docsite/cmdline/downloader/index.html,sha256=nygj-0GQmpD79B5AxHjwzQxOFv8vxHiu6LP_T2dN_kg,23171
|
|
80
80
|
ciocore/docsite/cmdline/packages/index.html,sha256=_kXB85PBAgrqW09OerYpxnJuyERHMbcLn6qBGRdyHwk,20923
|
|
81
81
|
ciocore/docsite/cmdline/uploader/index.html,sha256=vuQ06Gys9Eoxs87PXlqnM5AgB6Ag00BlDIy6oaprjis,25123
|
|
82
|
-
ciocore/docsite/how-to-guides/index.html,sha256=
|
|
82
|
+
ciocore/docsite/how-to-guides/index.html,sha256=9ZSygr8m3nRpE2JTvifeS9RHleoD3kPjCGZGCs6x-Rk,20192
|
|
83
83
|
ciocore/docsite/search/search_index.json,sha256=LP1ck_wuTP9A_dWTyaVF8Fugg22q1O0XS6hGqg2zk0M,189860
|
|
84
84
|
ciocore/docsite/stylesheets/extra.css,sha256=_Cxe9Dhg1BBi6Kqaz_iZD9z9VyqxA9vtONRjP4PVic0,354
|
|
85
85
|
ciocore/docsite/stylesheets/tables.css,sha256=LE_zwGRxGcdPIy-9QiVPecOzlEBSqZb_WP5vDkFE0ZM,3235
|
|
86
86
|
ciocore/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
|
-
ciocore/downloader/base_downloader.py,sha256=
|
|
87
|
+
ciocore/downloader/base_downloader.py,sha256=yO2gDOeWatJGmHomns9Bvo_dafdtG-_NPWY89-iNCgc,27417
|
|
88
88
|
ciocore/downloader/download_runner_base.py,sha256=cWTWKhFX5FLG84Wh8_s7xpk3n0nmQ4fDiD2rYV6a3u0,1612
|
|
89
89
|
ciocore/downloader/job_downloader.py,sha256=HAhr95RyCsj3KTp5W58Znc4JmqHY-mrM5b8vo6kRIJ0,5697
|
|
90
90
|
ciocore/downloader/legacy_downloader.py,sha256=LIbT3BxuY56lq_UW_io9FSgK_2VIKwFVMENyF-5KllA,51158
|
|
@@ -101,10 +101,10 @@ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
101
101
|
tests/instance_type_fixtures.py,sha256=uIzQduqKQVgjllMuyXaYnRC-pwqk5lnTx3NY2M5Nujo,4320
|
|
102
102
|
tests/package_fixtures.py,sha256=od7ZHofG8ubpQ3PqlUsrcHBcbmD3qVWih9eiIg1WtSQ,5361
|
|
103
103
|
tests/test_api_client.py,sha256=isntMDs3QTyTWdghBa_LbFAiC7ydZD1RWb655oEZo24,14452
|
|
104
|
-
tests/test_base_downloader.py,sha256=
|
|
104
|
+
tests/test_base_downloader.py,sha256=Oj50qzt0jNPu34r1tdPRC0crLw1gYeQaDvDNsozYWn4,11804
|
|
105
105
|
tests/test_cli.py,sha256=_WTs2SWlEgd6wtg1hmOBlFnbWVdFLvqp0KqNhy-y2e8,5532
|
|
106
106
|
tests/test_common.py,sha256=5N9xeeGVuwN4kcjIg30eBliUD8PePzCNNLuLipGuTgk,410
|
|
107
|
-
tests/test_config.py,sha256=
|
|
107
|
+
tests/test_config.py,sha256=ahDLB6yVX8pA-B1qvxEpcJ1Wf1HS499rEg7lloeyxfk,11526
|
|
108
108
|
tests/test_data.py,sha256=o320GdvOJ2TouWtuA8jcs8Cr_gQWlQ6KxWVSWtmARlY,7614
|
|
109
109
|
tests/test_downloader.py,sha256=hceljsjnuvk5Vk5X4mHgavIEcpbv8ylPwpz7rTwJ-aE,4721
|
|
110
110
|
tests/test_hardware_set.py,sha256=hW7A_suyYdU7WkB7qoHSBPLxaAP2CKqI0i_ULfO5GeY,4408
|
|
@@ -118,8 +118,8 @@ tests/test_uploader.py,sha256=JGp6GEyqRXRtbQSb-IW-cCX_BzNotWdCbnJnLwZvpUM,2869
|
|
|
118
118
|
tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
|
|
119
119
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
120
120
|
tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
|
|
121
|
-
ciocore-9.1.
|
|
122
|
-
ciocore-9.1.
|
|
123
|
-
ciocore-9.1.
|
|
124
|
-
ciocore-9.1.
|
|
125
|
-
ciocore-9.1.
|
|
121
|
+
ciocore-9.1.1b1.dist-info/METADATA,sha256=ffXtlEfKw2KYi6mtX-XRyCAaghtxUUDzVhTNflXV5D4,20826
|
|
122
|
+
ciocore-9.1.1b1.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
|
|
123
|
+
ciocore-9.1.1b1.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
|
|
124
|
+
ciocore-9.1.1b1.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
|
|
125
|
+
ciocore-9.1.1b1.dist-info/RECORD,,
|
tests/test_base_downloader.py
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
2
|
+
from unittest import mock
|
|
3
|
+
from unittest.mock import patch, PropertyMock
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from ciocore import api_client
|
|
1
7
|
from ciocore.downloader.base_downloader import (
|
|
2
8
|
BaseDownloader,
|
|
3
|
-
DEFAULT_NUM_THREADS,
|
|
4
|
-
DEFAULT_PROGRESS_INTERVAL,
|
|
5
|
-
DEFAULT_MAX_ATTEMPTS,
|
|
6
9
|
DEFAULT_DELAY,
|
|
7
10
|
DEFAULT_JITTER,
|
|
11
|
+
DEFAULT_MAX_ATTEMPTS,
|
|
12
|
+
DEFAULT_NUM_THREADS,
|
|
8
13
|
DEFAULT_PAGE_SIZE,
|
|
14
|
+
DEFAULT_PROGRESS_INTERVAL,
|
|
15
|
+
ensure_writable_output_path,
|
|
16
|
+
ensure_path_valid
|
|
9
17
|
)
|
|
10
|
-
import unittest
|
|
11
|
-
from unittest import mock
|
|
12
|
-
|
|
13
|
-
from ciocore import api_client
|
|
14
|
-
|
|
15
|
-
from unittest.mock import patch
|
|
16
|
-
|
|
17
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
18
|
-
|
|
19
18
|
|
|
20
19
|
class TestBaseDownloaderInit(unittest.TestCase):
|
|
21
20
|
def test_default_values(self):
|
|
@@ -37,7 +36,6 @@ class TestBaseDownloaderInit(unittest.TestCase):
|
|
|
37
36
|
self.assertEqual(downloader.jitter, DEFAULT_JITTER)
|
|
38
37
|
self.assertIsNone(downloader.regex)
|
|
39
38
|
|
|
40
|
-
|
|
41
39
|
def test_custom_values(self):
|
|
42
40
|
output_path = "/path/to/destination"
|
|
43
41
|
num_threads = 4
|
|
@@ -102,3 +100,181 @@ class TestBaseDownloaderRun(unittest.TestCase):
|
|
|
102
100
|
|
|
103
101
|
mock_get_some_tasks.assert_called_with(None)
|
|
104
102
|
self.downloader.download_tasks.assert_called_with(tasks, my_mock_executor)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class TestEnsureWritableOutputPath(unittest.TestCase):
|
|
106
|
+
|
|
107
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid", return_value=True)
|
|
108
|
+
def test_user_specified_path_is_returned_with_job_id_if_valid(
|
|
109
|
+
self, mock_ensure_path_valid
|
|
110
|
+
):
|
|
111
|
+
file_info = {"job_id": "00123", "task_id": "task1", "relative_path": "file.txt"}
|
|
112
|
+
task_info = {"job_id": "00123"}
|
|
113
|
+
user_specified_path = "/my/new/path"
|
|
114
|
+
|
|
115
|
+
result = ensure_writable_output_path(file_info, task_info, user_specified_path)
|
|
116
|
+
self.assertEqual(result, "/my/new/path/00123")
|
|
117
|
+
mock_ensure_path_valid.assert_called_with("/my/new/path/00123")
|
|
118
|
+
|
|
119
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid")
|
|
120
|
+
@patch("ciocore.downloader.base_downloader.get_fallback_path")
|
|
121
|
+
def test_user_specified_path_is_invalid_so_fallback_path_is_returned(
|
|
122
|
+
self, mock_get_fallback_path, mock_ensure_path_valid
|
|
123
|
+
):
|
|
124
|
+
file_info = {"job_id": "00123", "task_id": "task1", "relative_path": "file.txt"}
|
|
125
|
+
task_info = {"job_id": "00123"}
|
|
126
|
+
user_specified_path = "/invalid/path"
|
|
127
|
+
|
|
128
|
+
# Mock ensure_path_valid to return False for user_specified_path and True for fallback path
|
|
129
|
+
mock_ensure_path_valid.side_effect = lambda path: "invalid" not in path
|
|
130
|
+
|
|
131
|
+
# Mock get_fallback_path to return a specific fallback path
|
|
132
|
+
fallback_path = "/valid/fallback/path/00123"
|
|
133
|
+
mock_get_fallback_path.return_value = fallback_path
|
|
134
|
+
|
|
135
|
+
result = ensure_writable_output_path(file_info, task_info, user_specified_path)
|
|
136
|
+
|
|
137
|
+
# Assert that the fallback path is returned
|
|
138
|
+
self.assertEqual(result, fallback_path)
|
|
139
|
+
|
|
140
|
+
# Ensure that ensure_path_valid was called with the correct paths
|
|
141
|
+
mock_ensure_path_valid.assert_any_call("/invalid/path/00123")
|
|
142
|
+
mock_ensure_path_valid.assert_any_call(fallback_path)
|
|
143
|
+
|
|
144
|
+
# Ensure get_fallback_path was called with the correct job_id
|
|
145
|
+
mock_get_fallback_path.assert_called_with(task_info["job_id"])
|
|
146
|
+
|
|
147
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid")
|
|
148
|
+
@patch("ciocore.downloader.base_downloader.get_fallback_path")
|
|
149
|
+
def test_user_specified_path_and_fallback_path_are_invalid_so_none_is_returned(
|
|
150
|
+
self, mock_get_fallback_path, mock_ensure_path_valid
|
|
151
|
+
):
|
|
152
|
+
file_info = {
|
|
153
|
+
"job_id": "00123",
|
|
154
|
+
"task_id": "task1",
|
|
155
|
+
"relative_path": "file.txt"
|
|
156
|
+
}
|
|
157
|
+
task_info = {"job_id": "00123"}
|
|
158
|
+
user_specified_path = "/invalid/user/path"
|
|
159
|
+
|
|
160
|
+
# Mock ensure_path_valid to return False for all paths
|
|
161
|
+
mock_ensure_path_valid.return_value = False
|
|
162
|
+
|
|
163
|
+
# Mock get_fallback_path to return a specific fallback path
|
|
164
|
+
mock_get_fallback_path.return_value = "/invalid/fallback/path/00123"
|
|
165
|
+
|
|
166
|
+
result = ensure_writable_output_path(file_info, task_info, user_specified_path)
|
|
167
|
+
|
|
168
|
+
# Assert that None is returned when no valid paths are found
|
|
169
|
+
self.assertIsNone(result)
|
|
170
|
+
|
|
171
|
+
# Ensure that ensure_path_valid was called with both paths
|
|
172
|
+
mock_ensure_path_valid.assert_any_call("/invalid/user/path/00123")
|
|
173
|
+
mock_ensure_path_valid.assert_any_call("/invalid/fallback/path/00123")
|
|
174
|
+
|
|
175
|
+
# Ensure get_fallback_path was called with the correct job_id
|
|
176
|
+
mock_get_fallback_path.assert_called_with(task_info["job_id"])
|
|
177
|
+
|
|
178
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid", return_value=True)
|
|
179
|
+
def test_output_dir_is_returned_if_valid_and_no_user_specified_path(
|
|
180
|
+
self, mock_ensure_path_valid
|
|
181
|
+
):
|
|
182
|
+
file_info = {"output_dir": "/valid/output/dir", "job_id": "00123", "task_id": "task1", "relative_path": "file.txt"}
|
|
183
|
+
task_info = {"job_id": "00123"}
|
|
184
|
+
|
|
185
|
+
result = ensure_writable_output_path(file_info, task_info)
|
|
186
|
+
|
|
187
|
+
# Assert that the output directory from file_info is returned
|
|
188
|
+
self.assertEqual(result, file_info["output_dir"])
|
|
189
|
+
|
|
190
|
+
# Ensure that ensure_path_valid was called with the correct path
|
|
191
|
+
mock_ensure_path_valid.assert_called_with(file_info["output_dir"])
|
|
192
|
+
|
|
193
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid")
|
|
194
|
+
@patch("ciocore.downloader.base_downloader.get_fallback_path")
|
|
195
|
+
def test_fallback_path_is_returned_if_output_dir_is_invalid_and_no_user_specified_path(
|
|
196
|
+
self, mock_get_fallback_path, mock_ensure_path_valid
|
|
197
|
+
):
|
|
198
|
+
file_info = {"output_dir": "/invalid/output/dir", "job_id": "00123", "task_id": "task1", "relative_path": "file.txt"}
|
|
199
|
+
task_info = {"job_id": "00123"}
|
|
200
|
+
user_specified_path = None # No user-specified path
|
|
201
|
+
fallback_path = "/valid/fallback/path/00123"
|
|
202
|
+
|
|
203
|
+
# Mock ensure_path_valid to return False for output_dir and True for fallback path
|
|
204
|
+
mock_ensure_path_valid.side_effect = lambda path: path == fallback_path
|
|
205
|
+
|
|
206
|
+
# Mock get_fallback_path to return a specific fallback path
|
|
207
|
+
mock_get_fallback_path.return_value = fallback_path
|
|
208
|
+
|
|
209
|
+
result = ensure_writable_output_path(file_info, task_info, user_specified_path)
|
|
210
|
+
|
|
211
|
+
# Assert that the fallback path is returned
|
|
212
|
+
self.assertEqual(result, fallback_path)
|
|
213
|
+
|
|
214
|
+
# Ensure that ensure_path_valid was called with the correct paths
|
|
215
|
+
mock_ensure_path_valid.assert_any_call(file_info["output_dir"])
|
|
216
|
+
mock_ensure_path_valid.assert_any_call(fallback_path)
|
|
217
|
+
|
|
218
|
+
# Ensure get_fallback_path was called with the correct job_id
|
|
219
|
+
mock_get_fallback_path.assert_called_with(task_info["job_id"])
|
|
220
|
+
|
|
221
|
+
@patch("ciocore.downloader.base_downloader.ensure_path_valid", return_value=False)
|
|
222
|
+
@patch("ciocore.downloader.base_downloader.get_fallback_path")
|
|
223
|
+
def test_none_is_returned_if_output_dir_and_fallback_path_are_invalid(
|
|
224
|
+
self, mock_get_fallback_path, mock_ensure_path_valid
|
|
225
|
+
):
|
|
226
|
+
file_info = {"output_dir": "/invalid/output/dir", "job_id": "00123", "task_id": "task1", "relative_path": "file.txt"}
|
|
227
|
+
task_info = {"job_id": "00123"}
|
|
228
|
+
user_specified_path = None # No user-specified path
|
|
229
|
+
fallback_path = "/invalid/fallback/path/00123"
|
|
230
|
+
|
|
231
|
+
# Mock get_fallback_path to return a specific fallback path
|
|
232
|
+
mock_get_fallback_path.return_value = fallback_path
|
|
233
|
+
|
|
234
|
+
result = ensure_writable_output_path(file_info, task_info, user_specified_path)
|
|
235
|
+
|
|
236
|
+
# Assert that None is returned when no valid paths are found
|
|
237
|
+
self.assertIsNone(result)
|
|
238
|
+
|
|
239
|
+
# Ensure that ensure_path_valid was called with both paths
|
|
240
|
+
mock_ensure_path_valid.assert_any_call(file_info["output_dir"])
|
|
241
|
+
mock_ensure_path_valid.assert_any_call(fallback_path)
|
|
242
|
+
|
|
243
|
+
# Ensure get_fallback_path was called with the correct job_id
|
|
244
|
+
mock_get_fallback_path.assert_called_with(task_info["job_id"])
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class TestEnsurePathValid(unittest.TestCase):
|
|
248
|
+
|
|
249
|
+
@patch("ciocore.downloader.base_downloader.os.makedirs")
|
|
250
|
+
@patch("ciocore.downloader.base_downloader.os")
|
|
251
|
+
def test_drive_letter_path_on_linux_returns_false(self, mock_os, mock_makedirs):
|
|
252
|
+
# Set os.name to 'posix' to simulate a Linux environment
|
|
253
|
+
mock_os.name = 'posix'
|
|
254
|
+
|
|
255
|
+
# Define a path with a drive letter
|
|
256
|
+
path_with_drive_letter = "C:/some/path"
|
|
257
|
+
|
|
258
|
+
# Call ensure_path_valid and assert it returns False
|
|
259
|
+
result = ensure_path_valid(path_with_drive_letter)
|
|
260
|
+
self.assertFalse(result)
|
|
261
|
+
|
|
262
|
+
# Ensure os.makedirs is not called since the path is already invalid
|
|
263
|
+
mock_makedirs.assert_not_called()
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@patch("ciocore.downloader.base_downloader.os.makedirs")
|
|
267
|
+
@patch("ciocore.downloader.base_downloader.os")
|
|
268
|
+
def test_drive_letter_path_on_windows_calls_makedirs_and_returns_true(self, mock_os, mock_makedirs):
|
|
269
|
+
# Set os.name to 'nt' to simulate a Windows environment
|
|
270
|
+
mock_os.name = 'nt'
|
|
271
|
+
|
|
272
|
+
# Define a path with a drive letter
|
|
273
|
+
path_with_drive_letter = "C:/some/path"
|
|
274
|
+
|
|
275
|
+
# Call ensure_path_valid and assert it returns True
|
|
276
|
+
result = ensure_path_valid(path_with_drive_letter)
|
|
277
|
+
self.assertTrue(result)
|
|
278
|
+
|
|
279
|
+
# Ensure os.makedirs is called since the path is valid
|
|
280
|
+
mock_makedirs.assert_called_with(path_with_drive_letter, exist_ok=True)
|
tests/test_config.py
CHANGED
|
@@ -8,7 +8,18 @@ import logging
|
|
|
8
8
|
|
|
9
9
|
from unittest import mock
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
MOCK_API_KEY = '''{
|
|
12
|
+
"type": "service_account",
|
|
13
|
+
"project_id": "mock-project",
|
|
14
|
+
"private_key_id": "mock-key-id",
|
|
15
|
+
"private_key": "-----BEGIN PRIVATE KEY-----\\nMOCKKEY\\n-----END PRIVATE KEY-----\\n",
|
|
16
|
+
"client_email": "mock@example.com",
|
|
17
|
+
"client_id": "123456789",
|
|
18
|
+
"auth_uri": "https://accounts.example.com/oauth2/auth",
|
|
19
|
+
"token_uri": "https://oauth2.example.com/token",
|
|
20
|
+
"auth_provider_x509_cert_url": "https://www.example.com/oauth2/v1/certs",
|
|
21
|
+
"client_x509_cert_url": "https://www.example.com/robot/v1/metadata/x509/mock%40example.com"
|
|
22
|
+
}'''
|
|
12
23
|
|
|
13
24
|
PY3 = sys.version_info >= (3, 0)
|
|
14
25
|
BUILTIN_OPEN = "builtins.open" if PY3 else "__builtin__.open"
|
|
@@ -264,7 +275,7 @@ class ApiKeyFromVariableTest(unittest.TestCase):
|
|
|
264
275
|
self.down()
|
|
265
276
|
|
|
266
277
|
def test_returns_dict_if_key_is_b64encoded(self):
|
|
267
|
-
key =
|
|
278
|
+
key = MOCK_API_KEY
|
|
268
279
|
if sys.version_info < (3, 0):
|
|
269
280
|
self.up(env={"CONDUCTOR_API_KEY": base64.b64encode(key)})
|
|
270
281
|
else:
|
|
@@ -299,7 +310,7 @@ class ApiKeyFromFileTest(unittest.TestCase):
|
|
|
299
310
|
self.assertEqual(result, None)
|
|
300
311
|
self.down()
|
|
301
312
|
|
|
302
|
-
@mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=
|
|
313
|
+
@mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=MOCK_API_KEY, create=True)
|
|
303
314
|
def test_open_called_with_api_key_path(self, mock_file_open):
|
|
304
315
|
self.up(env={"CONDUCTOR_API_KEY_PATH": "path/to/api_key"})
|
|
305
316
|
config.Config.get_api_key_from_file()
|
|
@@ -313,7 +324,7 @@ class ApiKeyFromFileTest(unittest.TestCase):
|
|
|
313
324
|
config.Config.get_api_key_from_file()
|
|
314
325
|
self.down()
|
|
315
326
|
|
|
316
|
-
@mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=
|
|
327
|
+
@mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=MOCK_API_KEY, create=True)
|
|
317
328
|
def test_returns_dict_if_key_is_valid_json(self, mock_file_open):
|
|
318
329
|
self.up(env={"CONDUCTOR_API_KEY_PATH": "path/to/api_key"})
|
|
319
330
|
result = config.Config.get_api_key_from_file()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|