synapseclient 4.2.0__tar.gz → 4.3.0__tar.gz
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.
- {synapseclient-4.2.0/synapseclient.egg-info → synapseclient-4.3.0}/PKG-INFO +27 -10
- {synapseclient-4.2.0 → synapseclient-4.3.0}/README.md +20 -5
- {synapseclient-4.2.0 → synapseclient-4.3.0}/setup.cfg +9 -6
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/__init__.py +5 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/__main__.py +1 -3
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/api/__init__.py +2 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/api/entity_services.py +20 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/client.py +51 -39
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/cache.py +1 -1
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/credentials/credential_provider.py +3 -3
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/logging_setup.py +10 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/retry.py +4 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/multipart_upload_async.py +25 -3
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/utils.py +6 -2
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/activity.py +30 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/file.py +99 -9
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/mixins/storable_container.py +5 -1
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/activity_protocol.py +21 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/services/storable_entity_components.py +47 -4
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/table.py +11 -1
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/synapsePythonClient +1 -1
- {synapseclient-4.2.0 → synapseclient-4.3.0/synapseclient.egg-info}/PKG-INFO +27 -10
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/requires.txt +6 -4
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/__init__.py +2 -1
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/monitor.py +87 -3
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/sync.py +348 -282
- {synapseclient-4.2.0 → synapseclient-4.3.0}/MANIFEST.in +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/pyproject.toml +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/setup.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/.synapseConfig +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/activity.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/annotations.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/api/annotations.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/api/entity_bundle_services_v2.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/api/file_services.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/async_utils.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/config.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/constants/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/constants/concrete_types.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/constants/config_file_constants.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/constants/limits.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/constants/method_flags.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/credentials/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/credentials/cred_data.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/cumulative_transfer_progress.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/dozer.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/exceptions.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/lock.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/models/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/models/custom_json.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/models/dict_object.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/models/permission.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/multithread_download/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/multithread_download/download_threads.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/pool_provider.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/remote_file_storage_wrappers.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/sts_transfer.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/multipart_upload.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/upload_functions.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/upload_functions_async.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/upload_utils.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/version_check.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/entity.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/evaluation.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/annotations.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/evaluation.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/folder.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/mixins/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/mixins/access_control.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/project.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/access_control_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/annotations_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/file_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/folder_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/project_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/storable_container_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/table_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/team_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/protocols/user_protocol.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/services/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/services/search.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/services/storable_entity.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/team.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/user.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/models/wiki.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/services/__init__.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/services/json_schema.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/table.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/team.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/wiki.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/SOURCES.txt +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/dependency_links.txt +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/entry_points.txt +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/not-zip-safe +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient.egg-info/top_level.txt +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/copy_functions.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/describe_functions.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/migrate_functions.py +0 -0
- {synapseclient-4.2.0 → synapseclient-4.3.0}/synapseutils/walk_functions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: synapseclient
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: A client for Synapse, a collaborative, open-source research platform that allows teams to share data, track analyses, and collaborate.
|
|
5
5
|
Home-page: https://www.synapse.org
|
|
6
6
|
Author: The Synapse Engineering Team
|
|
@@ -43,10 +43,10 @@ Requires-Dist: loky~=3.0.0
|
|
|
43
43
|
Requires-Dist: async-lru~=2.0.4
|
|
44
44
|
Requires-Dist: psutil~=5.9.8
|
|
45
45
|
Provides-Extra: dev
|
|
46
|
-
Requires-Dist: pytest<
|
|
46
|
+
Requires-Dist: pytest<8.0,>=7.0.0; extra == "dev"
|
|
47
47
|
Requires-Dist: pytest-mock<4.0,>=3.0; extra == "dev"
|
|
48
48
|
Requires-Dist: pytest-socket~=0.6.0; extra == "dev"
|
|
49
|
-
Requires-Dist: pytest-asyncio
|
|
49
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23.6; extra == "dev"
|
|
50
50
|
Requires-Dist: flake8<4.0,>=3.7.0; extra == "dev"
|
|
51
51
|
Requires-Dist: pytest-xdist[psutil]<3.0.0,>=2.2; extra == "dev"
|
|
52
52
|
Requires-Dist: pytest-rerunfailures~=12.0; extra == "dev"
|
|
@@ -54,16 +54,18 @@ Requires-Dist: func-timeout~=4.3; extra == "dev"
|
|
|
54
54
|
Requires-Dist: pytest-cov~=4.1.0; extra == "dev"
|
|
55
55
|
Requires-Dist: black; extra == "dev"
|
|
56
56
|
Requires-Dist: pre-commit; extra == "dev"
|
|
57
|
+
Requires-Dist: pandas<3.0,>=1.5; extra == "dev"
|
|
57
58
|
Provides-Extra: tests
|
|
58
|
-
Requires-Dist: pytest<
|
|
59
|
+
Requires-Dist: pytest<8.0,>=7.0.0; extra == "tests"
|
|
59
60
|
Requires-Dist: pytest-mock<4.0,>=3.0; extra == "tests"
|
|
60
61
|
Requires-Dist: pytest-socket~=0.6.0; extra == "tests"
|
|
61
|
-
Requires-Dist: pytest-asyncio
|
|
62
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23.6; extra == "tests"
|
|
62
63
|
Requires-Dist: flake8<4.0,>=3.7.0; extra == "tests"
|
|
63
64
|
Requires-Dist: pytest-xdist[psutil]<3.0.0,>=2.2; extra == "tests"
|
|
64
65
|
Requires-Dist: pytest-rerunfailures~=12.0; extra == "tests"
|
|
65
66
|
Requires-Dist: func-timeout~=4.3; extra == "tests"
|
|
66
67
|
Requires-Dist: pytest-cov~=4.1.0; extra == "tests"
|
|
68
|
+
Requires-Dist: pandas<3.0,>=1.5; extra == "tests"
|
|
67
69
|
Provides-Extra: pandas
|
|
68
70
|
Requires-Dist: pandas<3.0,>=1.5; extra == "pandas"
|
|
69
71
|
Provides-Extra: pysftp
|
|
@@ -125,16 +127,24 @@ The Python Synapse client has been tested on 3.8, 3.9, 3.10 and 3.11 on Mac OS X
|
|
|
125
127
|
|
|
126
128
|
The [Python Synapse Client is on PyPI](https://pypi.python.org/pypi/synapseclient) and can be installed with pip:
|
|
127
129
|
|
|
128
|
-
|
|
130
|
+
# Here are a few ways to install the client. Choose the one that fits your use-case
|
|
131
|
+
# sudo may optionally be needed depending on your setup
|
|
132
|
+
|
|
133
|
+
pip install --upgrade synapseclient
|
|
134
|
+
pip install --upgrade "synapseclient[pandas]"
|
|
135
|
+
pip install --upgrade "synapseclient[pandas, pysftp, boto3]"
|
|
129
136
|
|
|
130
137
|
...or to upgrade an existing installation of the Synapse client:
|
|
131
138
|
|
|
132
|
-
|
|
139
|
+
# sudo may optionally be needed depending on your setup
|
|
140
|
+
pip install --upgrade synapseclient
|
|
133
141
|
|
|
134
|
-
The dependencies on `pandas` and `
|
|
142
|
+
The dependencies on `pandas`, `pysftp`, and `boto3` are optional. Synapse
|
|
143
|
+
[Tables](https://python-docs.synapse.org/reference/tables/) integrate
|
|
135
144
|
with [Pandas](http://pandas.pydata.org/). The library `pysftp` is required for users of
|
|
136
|
-
[SFTP](https://python-docs.synapse.org/guides/data_storage/#sftp) file storage.
|
|
137
|
-
to be compiled or installed separately from prebuilt
|
|
145
|
+
[SFTP](https://python-docs.synapse.org/guides/data_storage/#sftp) file storage. All
|
|
146
|
+
libraries require native code to be compiled or installed separately from prebuilt
|
|
147
|
+
binaries.
|
|
138
148
|
|
|
139
149
|
### Install from source
|
|
140
150
|
|
|
@@ -144,6 +154,13 @@ Clone the [source code repository](https://github.com/Sage-Bionetworks/synapsePy
|
|
|
144
154
|
cd synapsePythonClient
|
|
145
155
|
pip install .
|
|
146
156
|
|
|
157
|
+
Alternatively, you can use pip to install a particular branch, commit, or other git reference:
|
|
158
|
+
|
|
159
|
+
pip install git+https://github.com/Sage-Bionetworks/synapsePythonClient@master
|
|
160
|
+
|
|
161
|
+
or
|
|
162
|
+
|
|
163
|
+
pip install git+https://github.com/Sage-Bionetworks/synapsePythonClient@my-commit-hash
|
|
147
164
|
|
|
148
165
|
Command line usage
|
|
149
166
|
------------------
|
|
@@ -44,16 +44,24 @@ The Python Synapse client has been tested on 3.8, 3.9, 3.10 and 3.11 on Mac OS X
|
|
|
44
44
|
|
|
45
45
|
The [Python Synapse Client is on PyPI](https://pypi.python.org/pypi/synapseclient) and can be installed with pip:
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
# Here are a few ways to install the client. Choose the one that fits your use-case
|
|
48
|
+
# sudo may optionally be needed depending on your setup
|
|
49
|
+
|
|
50
|
+
pip install --upgrade synapseclient
|
|
51
|
+
pip install --upgrade "synapseclient[pandas]"
|
|
52
|
+
pip install --upgrade "synapseclient[pandas, pysftp, boto3]"
|
|
48
53
|
|
|
49
54
|
...or to upgrade an existing installation of the Synapse client:
|
|
50
55
|
|
|
51
|
-
|
|
56
|
+
# sudo may optionally be needed depending on your setup
|
|
57
|
+
pip install --upgrade synapseclient
|
|
52
58
|
|
|
53
|
-
The dependencies on `pandas` and `
|
|
59
|
+
The dependencies on `pandas`, `pysftp`, and `boto3` are optional. Synapse
|
|
60
|
+
[Tables](https://python-docs.synapse.org/reference/tables/) integrate
|
|
54
61
|
with [Pandas](http://pandas.pydata.org/). The library `pysftp` is required for users of
|
|
55
|
-
[SFTP](https://python-docs.synapse.org/guides/data_storage/#sftp) file storage.
|
|
56
|
-
to be compiled or installed separately from prebuilt
|
|
62
|
+
[SFTP](https://python-docs.synapse.org/guides/data_storage/#sftp) file storage. All
|
|
63
|
+
libraries require native code to be compiled or installed separately from prebuilt
|
|
64
|
+
binaries.
|
|
57
65
|
|
|
58
66
|
### Install from source
|
|
59
67
|
|
|
@@ -63,6 +71,13 @@ Clone the [source code repository](https://github.com/Sage-Bionetworks/synapsePy
|
|
|
63
71
|
cd synapsePythonClient
|
|
64
72
|
pip install .
|
|
65
73
|
|
|
74
|
+
Alternatively, you can use pip to install a particular branch, commit, or other git reference:
|
|
75
|
+
|
|
76
|
+
pip install git+https://github.com/Sage-Bionetworks/synapsePythonClient@master
|
|
77
|
+
|
|
78
|
+
or
|
|
79
|
+
|
|
80
|
+
pip install git+https://github.com/Sage-Bionetworks/synapsePythonClient@my-commit-hash
|
|
66
81
|
|
|
67
82
|
Command line usage
|
|
68
83
|
------------------
|
|
@@ -52,22 +52,23 @@ install_requires =
|
|
|
52
52
|
async-lru~=2.0.4
|
|
53
53
|
psutil~=5.9.8
|
|
54
54
|
tests_require =
|
|
55
|
-
pytest>=
|
|
55
|
+
pytest>=7.0.0,<8.0
|
|
56
56
|
pytest-mock>=3.0,<4.0
|
|
57
57
|
pytest-socket~=0.6.0
|
|
58
|
-
pytest-asyncio
|
|
58
|
+
pytest-asyncio>=0.23.6,<1.0
|
|
59
59
|
flake8>=3.7.0,<4.0
|
|
60
60
|
pytest-xdist[psutil]>=2.2,<3.0.0
|
|
61
61
|
pytest-rerunfailures~=12.0
|
|
62
62
|
func-timeout~=4.3
|
|
63
63
|
pytest-cov~=4.1.0
|
|
64
|
+
pandas>=1.5,<3.0
|
|
64
65
|
|
|
65
66
|
[options.extras_require]
|
|
66
67
|
dev =
|
|
67
|
-
pytest>=
|
|
68
|
+
pytest>=7.0.0,<8.0
|
|
68
69
|
pytest-mock>=3.0,<4.0
|
|
69
70
|
pytest-socket~=0.6.0
|
|
70
|
-
pytest-asyncio
|
|
71
|
+
pytest-asyncio>=0.23.6,<1.0
|
|
71
72
|
flake8>=3.7.0,<4.0
|
|
72
73
|
pytest-xdist[psutil]>=2.2,<3.0.0
|
|
73
74
|
pytest-rerunfailures~=12.0
|
|
@@ -75,16 +76,18 @@ dev =
|
|
|
75
76
|
pytest-cov~=4.1.0
|
|
76
77
|
black
|
|
77
78
|
pre-commit
|
|
79
|
+
pandas>=1.5,<3.0
|
|
78
80
|
tests =
|
|
79
|
-
pytest>=
|
|
81
|
+
pytest>=7.0.0,<8.0
|
|
80
82
|
pytest-mock>=3.0,<4.0
|
|
81
83
|
pytest-socket~=0.6.0
|
|
82
|
-
pytest-asyncio
|
|
84
|
+
pytest-asyncio>=0.23.6,<1.0
|
|
83
85
|
flake8>=3.7.0,<4.0
|
|
84
86
|
pytest-xdist[psutil]>=2.2,<3.0.0
|
|
85
87
|
pytest-rerunfailures~=12.0
|
|
86
88
|
func-timeout~=4.3
|
|
87
89
|
pytest-cov~=4.1.0
|
|
90
|
+
pandas>=1.5,<3.0
|
|
88
91
|
pandas =
|
|
89
92
|
pandas>=1.5,<3.0
|
|
90
93
|
pysftp =
|
|
@@ -88,6 +88,11 @@ USER_AGENT = {
|
|
|
88
88
|
% (__version__, requests.utils.default_user_agent())
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
USER_AGENT_COMMAND_LINE = {
|
|
92
|
+
"User-Agent": "synapsecommandlineclient/%s %s"
|
|
93
|
+
% (__version__, requests.utils.default_user_agent())
|
|
94
|
+
}
|
|
95
|
+
|
|
91
96
|
# patch json
|
|
92
97
|
from .core.models import custom_json # noqa
|
|
93
98
|
|
|
@@ -1871,9 +1871,7 @@ def _authenticate_login(
|
|
|
1871
1871
|
|
|
1872
1872
|
def main():
|
|
1873
1873
|
args = build_parser().parse_args()
|
|
1874
|
-
synapseclient.USER_AGENT
|
|
1875
|
-
"synapsecommandlineclient " + synapseclient.USER_AGENT["User-Agent"]
|
|
1876
|
-
)
|
|
1874
|
+
synapseclient.USER_AGENT = synapseclient.USER_AGENT_COMMAND_LINE
|
|
1877
1875
|
if args.otel:
|
|
1878
1876
|
trace.set_tracer_provider(
|
|
1879
1877
|
TracerProvider(
|
|
@@ -13,6 +13,7 @@ from .entity_services import (
|
|
|
13
13
|
post_entity,
|
|
14
14
|
put_entity,
|
|
15
15
|
create_access_requirements_if_none,
|
|
16
|
+
delete_entity_generated_by,
|
|
16
17
|
)
|
|
17
18
|
from .file_services import (
|
|
18
19
|
get_file_handle,
|
|
@@ -51,4 +52,5 @@ __all__ = [
|
|
|
51
52
|
"get_upload_destination",
|
|
52
53
|
"get_upload_destination_location",
|
|
53
54
|
"create_access_requirements_if_none",
|
|
55
|
+
"delete_entity_generated_by",
|
|
54
56
|
]
|
|
@@ -175,3 +175,23 @@ async def create_access_requirements_if_none(
|
|
|
175
175
|
"the Synapse access control team to start the process of adding "
|
|
176
176
|
"terms-of-use or review board approval for this entity."
|
|
177
177
|
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
async def delete_entity_generated_by(
|
|
181
|
+
entity_id: str,
|
|
182
|
+
synapse_client: Optional["Synapse"] = None,
|
|
183
|
+
) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Arguments:
|
|
186
|
+
entity_id: The ID of the entity.
|
|
187
|
+
synapse_client: If not passed in or None this will use the last client from
|
|
188
|
+
the `.login()` method.
|
|
189
|
+
|
|
190
|
+
Returns: None
|
|
191
|
+
"""
|
|
192
|
+
from synapseclient import Synapse
|
|
193
|
+
|
|
194
|
+
client = Synapse.get_client(synapse_client=synapse_client)
|
|
195
|
+
return await client.rest_delete_async(
|
|
196
|
+
uri=f"/entity/{entity_id}/generatedBy",
|
|
197
|
+
)
|
|
@@ -121,9 +121,6 @@ from synapseclient.core.upload.multipart_upload_async import (
|
|
|
121
121
|
multipart_upload_string_async,
|
|
122
122
|
)
|
|
123
123
|
from synapseclient.core.remote_file_storage_wrappers import S3ClientWrapper, SFTPWrapper
|
|
124
|
-
from synapseclient.core.upload.upload_functions import (
|
|
125
|
-
upload_file_handle,
|
|
126
|
-
)
|
|
127
124
|
from synapseclient.core.upload.upload_functions_async import (
|
|
128
125
|
upload_file_handle as upload_file_handle_async,
|
|
129
126
|
upload_synapse_s3,
|
|
@@ -136,7 +133,6 @@ from synapseclient.core.models.permission import Permissions
|
|
|
136
133
|
from opentelemetry import trace
|
|
137
134
|
from opentelemetry.trace import SpanKind
|
|
138
135
|
|
|
139
|
-
|
|
140
136
|
tracer = trace.get_tracer("synapseclient")
|
|
141
137
|
|
|
142
138
|
PRODUCTION_ENDPOINTS = {
|
|
@@ -348,7 +344,7 @@ class Synapse(object):
|
|
|
348
344
|
span.end()
|
|
349
345
|
|
|
350
346
|
event_hooks = {"request": [log_request], "response": [log_response]}
|
|
351
|
-
httpx_timeout = httpx.Timeout(70)
|
|
347
|
+
httpx_timeout = httpx.Timeout(70, pool=None)
|
|
352
348
|
self._requests_session_storage = requests_session_storage or httpx.Client(
|
|
353
349
|
timeout=httpx_timeout, event_hooks=event_hooks
|
|
354
350
|
)
|
|
@@ -402,6 +398,7 @@ class Synapse(object):
|
|
|
402
398
|
self.max_threads = transfer_config["max_threads"]
|
|
403
399
|
self._thread_executor = {}
|
|
404
400
|
self._process_executor = {}
|
|
401
|
+
self._parallel_file_transfer_semaphore = {}
|
|
405
402
|
self._md5_semaphore = {}
|
|
406
403
|
self.use_boto_sts_transfers = transfer_config["use_boto_sts"]
|
|
407
404
|
|
|
@@ -435,7 +432,7 @@ class Synapse(object):
|
|
|
435
432
|
await self._requests_session_async_synapse[asyncio_event_loop].aclose()
|
|
436
433
|
del self._requests_session_async_synapse[asyncio_event_loop]
|
|
437
434
|
|
|
438
|
-
httpx_timeout = httpx.Timeout(70)
|
|
435
|
+
httpx_timeout = httpx.Timeout(70, pool=None)
|
|
439
436
|
span_dict: Dict[httpx.Request, trace.Span] = {}
|
|
440
437
|
|
|
441
438
|
async def log_request(request: httpx.Request) -> None:
|
|
@@ -562,6 +559,45 @@ class Synapse(object):
|
|
|
562
559
|
|
|
563
560
|
return self._md5_semaphore[asyncio_event_loop]
|
|
564
561
|
|
|
562
|
+
def _get_parallel_file_transfer_semaphore(
|
|
563
|
+
self, asyncio_event_loop: asyncio.AbstractEventLoop
|
|
564
|
+
) -> asyncio.Semaphore:
|
|
565
|
+
"""
|
|
566
|
+
Retrieve the semaphore for the Synapse client. Or create a new one if it does
|
|
567
|
+
not exist. This semaphore is used to limit the number of files that can actively
|
|
568
|
+
enter the uploading/downloading process.
|
|
569
|
+
|
|
570
|
+
This is expected to be called from within an AsyncIO loop.
|
|
571
|
+
|
|
572
|
+
By default the number of files that can enter the "uploading" state will be
|
|
573
|
+
limited to 2 * max_threads. This is to ensure that the files that are entering
|
|
574
|
+
into the "uploading" state will have priority to finish. Additionally, it means
|
|
575
|
+
that there should be a good spread of files getting up to the "uploading"
|
|
576
|
+
state, entering the "uploading" state, and finishing the "uploading" state.
|
|
577
|
+
|
|
578
|
+
If we break these states down into large components they would look like:
|
|
579
|
+
- Before "uploading" state: HTTP rest calls to retrieve what data Synapse has
|
|
580
|
+
- Entering "uploading" state: MD5 calculation and HTTP rest calls to determine
|
|
581
|
+
how/where to upload a file to.
|
|
582
|
+
- During "uploading" state: Uploading the file to a storage provider.
|
|
583
|
+
- After "uploading" state: HTTP rest calls to finalize the upload.
|
|
584
|
+
|
|
585
|
+
This has not yet been applied to parallel file downloads. That will take place
|
|
586
|
+
later on.
|
|
587
|
+
"""
|
|
588
|
+
if (
|
|
589
|
+
hasattr(self, "_parallel_file_transfer_semaphore")
|
|
590
|
+
and asyncio_event_loop in self._parallel_file_transfer_semaphore
|
|
591
|
+
and self._parallel_file_transfer_semaphore[asyncio_event_loop] is not None
|
|
592
|
+
):
|
|
593
|
+
return self._parallel_file_transfer_semaphore[asyncio_event_loop]
|
|
594
|
+
|
|
595
|
+
self._parallel_file_transfer_semaphore.update(
|
|
596
|
+
{asyncio_event_loop: asyncio.Semaphore(max(self.max_threads * 2, 1))}
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
return self._parallel_file_transfer_semaphore[asyncio_event_loop]
|
|
600
|
+
|
|
565
601
|
# initialize logging
|
|
566
602
|
def _init_logger(self):
|
|
567
603
|
"""
|
|
@@ -716,10 +752,10 @@ class Synapse(object):
|
|
|
716
752
|
If no login arguments are provided or only username is provided, login() will attempt to log in using
|
|
717
753
|
information from these sources (in order of preference):
|
|
718
754
|
|
|
719
|
-
1.
|
|
720
|
-
2. User
|
|
755
|
+
1. .synapseConfig file (in user home folder unless configured otherwise)
|
|
756
|
+
2. User defined arguments during a CLI session
|
|
757
|
+
3. User's Personal Access Token (aka: Synapse Auth Token)
|
|
721
758
|
from the environment variable: SYNAPSE_AUTH_TOKEN
|
|
722
|
-
3. .synapseConfig file (in user home folder unless configured otherwise)
|
|
723
759
|
4. Retrieves user's authentication token from AWS SSM Parameter store (if configured)
|
|
724
760
|
|
|
725
761
|
Arguments:
|
|
@@ -1729,7 +1765,6 @@ class Synapse(object):
|
|
|
1729
1765
|
activityName=None,
|
|
1730
1766
|
activityDescription=None,
|
|
1731
1767
|
set_annotations=True,
|
|
1732
|
-
async_file_handle_upload: bool = True,
|
|
1733
1768
|
):
|
|
1734
1769
|
"""
|
|
1735
1770
|
Creates a new Entity or updates an existing Entity, uploading any files in the process.
|
|
@@ -1752,11 +1787,6 @@ class Synapse(object):
|
|
|
1752
1787
|
You will be contacted with regards to the specific data being restricted and the
|
|
1753
1788
|
requirements of access.
|
|
1754
1789
|
set_annotations: If True, set the annotations on the entity. If False, do not set the annotations.
|
|
1755
|
-
async_file_handle_upload: Temporary feature flag that will be removed at an
|
|
1756
|
-
unannounced later date. This is used during the Synapse Utils
|
|
1757
|
-
syncToSynapse to disable the async file handle upload. The is because
|
|
1758
|
-
the multi-threaded logic in the syncToSynapse is not compatible with
|
|
1759
|
-
the async file handle upload.
|
|
1760
1790
|
|
|
1761
1791
|
Returns:
|
|
1762
1792
|
A Synapse Entity, Evaluation, or Wiki
|
|
@@ -1916,37 +1946,20 @@ class Synapse(object):
|
|
|
1916
1946
|
"Entities of type File must have a parentId."
|
|
1917
1947
|
)
|
|
1918
1948
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
upload_file_handle_async(
|
|
1922
|
-
self,
|
|
1923
|
-
parent_id_for_upload,
|
|
1924
|
-
local_state["path"]
|
|
1925
|
-
if (
|
|
1926
|
-
synapseStore
|
|
1927
|
-
or local_state_fh.get("externalURL") is None
|
|
1928
|
-
)
|
|
1929
|
-
else local_state_fh.get("externalURL"),
|
|
1930
|
-
synapse_store=synapseStore,
|
|
1931
|
-
md5=local_file_md5_hex or local_state_fh.get("contentMd5"),
|
|
1932
|
-
file_size=local_state_fh.get("contentSize"),
|
|
1933
|
-
mimetype=local_state_fh.get("contentType"),
|
|
1934
|
-
),
|
|
1935
|
-
self,
|
|
1936
|
-
)
|
|
1937
|
-
else:
|
|
1938
|
-
fileHandle = upload_file_handle(
|
|
1949
|
+
fileHandle = wrap_async_to_sync(
|
|
1950
|
+
upload_file_handle_async(
|
|
1939
1951
|
self,
|
|
1940
1952
|
parent_id_for_upload,
|
|
1941
1953
|
local_state["path"]
|
|
1942
1954
|
if (synapseStore or local_state_fh.get("externalURL") is None)
|
|
1943
1955
|
else local_state_fh.get("externalURL"),
|
|
1944
|
-
|
|
1956
|
+
synapse_store=synapseStore,
|
|
1945
1957
|
md5=local_file_md5_hex or local_state_fh.get("contentMd5"),
|
|
1946
1958
|
file_size=local_state_fh.get("contentSize"),
|
|
1947
1959
|
mimetype=local_state_fh.get("contentType"),
|
|
1948
|
-
|
|
1949
|
-
|
|
1960
|
+
),
|
|
1961
|
+
self,
|
|
1962
|
+
)
|
|
1950
1963
|
properties["dataFileHandleId"] = fileHandle["id"]
|
|
1951
1964
|
local_state["_file_handle"] = fileHandle
|
|
1952
1965
|
|
|
@@ -6027,7 +6040,6 @@ class Synapse(object):
|
|
|
6027
6040
|
else:
|
|
6028
6041
|
return
|
|
6029
6042
|
data_dict = json.loads(data_to_parse)
|
|
6030
|
-
|
|
6031
6043
|
if "parentId" in data_dict:
|
|
6032
6044
|
current_span.set_attribute(
|
|
6033
6045
|
"synapse.parent_id", data_dict["parentId"]
|
|
@@ -87,7 +87,7 @@ class Cache:
|
|
|
87
87
|
value = os.path.expandvars(os.path.expanduser(value))
|
|
88
88
|
# create the cache_root_dir if it does not already exist
|
|
89
89
|
if not os.path.exists(value):
|
|
90
|
-
os.makedirs(value)
|
|
90
|
+
os.makedirs(value, exist_ok=True)
|
|
91
91
|
self.__dict__[key] = value
|
|
92
92
|
|
|
93
93
|
def __init__(self, cache_root_dir=CACHE_ROOT_DIR, fanout=1000):
|
{synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/credentials/credential_provider.py
RENAMED
|
@@ -209,9 +209,9 @@ class SynapseCredentialsProviderChain(object):
|
|
|
209
209
|
|
|
210
210
|
By default this class uses the following providers in this order:
|
|
211
211
|
|
|
212
|
-
1. [
|
|
213
|
-
2. [
|
|
214
|
-
3. [
|
|
212
|
+
1. [ConfigFileCredentialsProvider][synapseclient.core.credentials.credential_provider.ConfigFileCredentialsProvider]
|
|
213
|
+
2. [UserArgsCredentialsProvider][synapseclient.core.credentials.credential_provider.UserArgsCredentialsProvider]
|
|
214
|
+
3. [EnvironmentVariableCredentialsProvider][synapseclient.core.credentials.credential_provider.EnvironmentVariableCredentialsProvider]
|
|
215
215
|
4. [AWSParameterStoreCredentialsProvider][synapseclient.core.credentials.credential_provider.AWSParameterStoreCredentialsProvider]
|
|
216
216
|
|
|
217
217
|
Attributes:
|
|
@@ -96,6 +96,16 @@ logging_config.dictConfig(
|
|
|
96
96
|
"propagate": True,
|
|
97
97
|
},
|
|
98
98
|
SILENT_LOGGER_NAME: {"handlers": [], "level": "INFO", "propagate": False},
|
|
99
|
+
# "httpx": {
|
|
100
|
+
# "handlers": ["debug_stderr"],
|
|
101
|
+
# "level": "DEBUG",
|
|
102
|
+
# "propagate": True,
|
|
103
|
+
# },
|
|
104
|
+
# "httpcore": {
|
|
105
|
+
# "handlers": ["debug_stderr"],
|
|
106
|
+
# "level": "DEBUG",
|
|
107
|
+
# "propagate": True,
|
|
108
|
+
# },
|
|
99
109
|
},
|
|
100
110
|
}
|
|
101
111
|
)
|
|
@@ -328,6 +328,8 @@ async def with_retry_time_based_async(
|
|
|
328
328
|
caught_exception = None
|
|
329
329
|
caught_exception_info = None
|
|
330
330
|
response = None
|
|
331
|
+
current_span = trace.get_current_span()
|
|
332
|
+
current_span.set_attribute("synapse.retries", str(retries + 1))
|
|
331
333
|
|
|
332
334
|
try:
|
|
333
335
|
response = await function()
|
|
@@ -449,6 +451,8 @@ def with_retry_time_based(
|
|
|
449
451
|
caught_exception = None
|
|
450
452
|
caught_exception_info = None
|
|
451
453
|
response = None
|
|
454
|
+
current_span = trace.get_current_span()
|
|
455
|
+
current_span.set_attribute("synapse.retries", str(retries + 1))
|
|
452
456
|
|
|
453
457
|
try:
|
|
454
458
|
response = function()
|
{synapseclient-4.2.0 → synapseclient-4.3.0}/synapseclient/core/upload/multipart_upload_async.py
RENAMED
|
@@ -64,6 +64,7 @@ flowchart TD
|
|
|
64
64
|
|
|
65
65
|
# pylint: disable=protected-access
|
|
66
66
|
import asyncio
|
|
67
|
+
from contextlib import contextmanager
|
|
67
68
|
import gc
|
|
68
69
|
import mimetypes
|
|
69
70
|
import os
|
|
@@ -126,6 +127,22 @@ MIN_PART_SIZE = 5 * MB
|
|
|
126
127
|
DEFAULT_PART_SIZE = 8 * MB
|
|
127
128
|
MAX_RETRIES = 7
|
|
128
129
|
|
|
130
|
+
_thread_local = threading.local()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@contextmanager
|
|
134
|
+
def shared_progress_bar(progress_bar):
|
|
135
|
+
"""An outside process that will eventually trigger an upload through this module
|
|
136
|
+
can configure a shared Progress Bar by running its code within this context manager.
|
|
137
|
+
"""
|
|
138
|
+
_thread_local.progress_bar = progress_bar
|
|
139
|
+
try:
|
|
140
|
+
yield
|
|
141
|
+
finally:
|
|
142
|
+
_thread_local.progress_bar.close()
|
|
143
|
+
_thread_local.progress_bar.refresh()
|
|
144
|
+
del _thread_local.progress_bar
|
|
145
|
+
|
|
129
146
|
|
|
130
147
|
@dataclass
|
|
131
148
|
class HandlePartResult:
|
|
@@ -173,6 +190,7 @@ class UploadAttemptAsync:
|
|
|
173
190
|
self._aborted = False
|
|
174
191
|
self._storage_str = storage_str
|
|
175
192
|
|
|
193
|
+
self._close_progress_bar = getattr(_thread_local, "progress_bar", None) is None
|
|
176
194
|
# populated later
|
|
177
195
|
self._upload_id: Optional[str] = None
|
|
178
196
|
self._pre_signed_part_urls: Optional[Mapping[int, str]] = None
|
|
@@ -329,7 +347,9 @@ class UploadAttemptAsync:
|
|
|
329
347
|
if self._is_copy():
|
|
330
348
|
# we won't have bytes to measure during a copy so the byte oriented
|
|
331
349
|
# progress bar is not useful
|
|
332
|
-
self._progress_bar =
|
|
350
|
+
self._progress_bar = getattr(
|
|
351
|
+
_thread_local, "progress_bar", None
|
|
352
|
+
) or tqdm(
|
|
333
353
|
total=part_count,
|
|
334
354
|
desc=self._storage_str or "Copying",
|
|
335
355
|
unit_scale=True,
|
|
@@ -343,7 +363,9 @@ class UploadAttemptAsync:
|
|
|
343
363
|
file_size,
|
|
344
364
|
)
|
|
345
365
|
|
|
346
|
-
self._progress_bar =
|
|
366
|
+
self._progress_bar = getattr(
|
|
367
|
+
_thread_local, "progress_bar", None
|
|
368
|
+
) or tqdm(
|
|
347
369
|
total=file_size,
|
|
348
370
|
desc=self._storage_str or "Uploading",
|
|
349
371
|
unit="B",
|
|
@@ -448,7 +470,7 @@ class UploadAttemptAsync:
|
|
|
448
470
|
Returns:
|
|
449
471
|
The response from the server for the completed upload.
|
|
450
472
|
"""
|
|
451
|
-
if not self._syn.silent and self._progress_bar:
|
|
473
|
+
if not self._syn.silent and self._progress_bar and self._close_progress_bar:
|
|
452
474
|
self._progress_bar.close()
|
|
453
475
|
upload_status_response = await put_file_multipart_complete(
|
|
454
476
|
upload_id=self._upload_id,
|
|
@@ -1400,8 +1400,9 @@ def delete_none_keys(incoming_object: typing.Dict) -> None:
|
|
|
1400
1400
|
|
|
1401
1401
|
def merge_dataclass_entities(
|
|
1402
1402
|
source: typing.Union["Project", "Folder", "File"],
|
|
1403
|
-
destination: typing.Union["Project", "Folder"],
|
|
1404
|
-
|
|
1403
|
+
destination: typing.Union["Project", "Folder", "File"],
|
|
1404
|
+
fields_to_ignore: typing.List[str] = None,
|
|
1405
|
+
) -> typing.Union["Project", "Folder", "File"]:
|
|
1405
1406
|
"""
|
|
1406
1407
|
Utility function to merge two dataclass entities together. This is used when we are
|
|
1407
1408
|
upserting an entity from the Synapse service with the requested changes.
|
|
@@ -1409,6 +1410,7 @@ def merge_dataclass_entities(
|
|
|
1409
1410
|
Arguments:
|
|
1410
1411
|
source: The source entity to merge from.
|
|
1411
1412
|
destination: The destination entity to merge into.
|
|
1413
|
+
fields_to_ignore: A list of fields to ignore when merging.
|
|
1412
1414
|
|
|
1413
1415
|
Returns:
|
|
1414
1416
|
The destination entity with the merged values.
|
|
@@ -1420,6 +1422,8 @@ def merge_dataclass_entities(
|
|
|
1420
1422
|
|
|
1421
1423
|
# Update destination_dict with source_dict, keeping destination's values in case of conflicts
|
|
1422
1424
|
for key, value in source_dict.items():
|
|
1425
|
+
if fields_to_ignore is not None and key in fields_to_ignore:
|
|
1426
|
+
continue
|
|
1423
1427
|
if is_dataclass(getattr(source, key)):
|
|
1424
1428
|
if hasattr(destination, key):
|
|
1425
1429
|
setattr(destination, key, getattr(source, key))
|
|
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Dict, List, NamedTuple, Optional, Union
|
|
|
5
5
|
from opentelemetry import context, trace
|
|
6
6
|
|
|
7
7
|
from synapseclient import Synapse
|
|
8
|
+
from synapseclient.api import delete_entity_generated_by
|
|
8
9
|
from synapseclient.activity import Activity as Synapse_Activity
|
|
9
10
|
from synapseclient.core.async_utils import async_to_sync, otel_trace_method
|
|
10
11
|
from synapseclient.core.constants.concrete_types import USED_ENTITY, USED_URL
|
|
@@ -389,3 +390,32 @@ class Activity(ActivitySynchronousProtocol):
|
|
|
389
390
|
current_context,
|
|
390
391
|
),
|
|
391
392
|
)
|
|
393
|
+
parent.activity = None
|
|
394
|
+
|
|
395
|
+
@classmethod
|
|
396
|
+
async def disassociate_from_entity_async(
|
|
397
|
+
cls,
|
|
398
|
+
parent: Union["Table", "File"],
|
|
399
|
+
synapse_client: Optional[Synapse] = None,
|
|
400
|
+
) -> None:
|
|
401
|
+
"""
|
|
402
|
+
Disassociate the Activity from the parent entity. This is the first step in
|
|
403
|
+
deleting the Activity. If you have other entities that are associated with this
|
|
404
|
+
Activity you must disassociate them by calling this method on them as well.
|
|
405
|
+
|
|
406
|
+
Arguments:
|
|
407
|
+
parent: The parent entity this activity is associated with.
|
|
408
|
+
synapse_client: If not passed in or None this will use the last client
|
|
409
|
+
from the `.login()` method.
|
|
410
|
+
|
|
411
|
+
Raises:
|
|
412
|
+
ValueError: If the parent does not have an ID.
|
|
413
|
+
"""
|
|
414
|
+
# TODO: Input validation: SYNPY-1400
|
|
415
|
+
with tracer.start_as_current_span(
|
|
416
|
+
name=f"Activity_disassociate: Parent_ID: {parent.id}"
|
|
417
|
+
):
|
|
418
|
+
await delete_entity_generated_by(
|
|
419
|
+
entity_id=parent.id, synapse_client=synapse_client
|
|
420
|
+
)
|
|
421
|
+
parent.activity = None
|