Skip to content

Commit 0dac202

Browse files
authored
[SYNPY-1511] Correct missing synapse client propogation and caching (#1125)
* Correct missing propogation and move when synapseClient instance is cached
1 parent bc46199 commit 0dac202

14 files changed

+83
-63
lines changed

synapseclient/client.py

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
The `Synapse` object encapsulates a connection to the Synapse service and is used for building projects, uploading and
33
retrieving data, and recording provenance of data analysis.
44
"""
5-
65
import asyncio
76
import collections
87
import collections.abc
@@ -278,6 +277,7 @@ def __init__(
278277
requests_session_async_synapse: httpx.AsyncClient = None,
279278
requests_session_storage: httpx.Client = None,
280279
asyncio_event_loop: asyncio.AbstractEventLoop = None,
280+
cache_client: bool = True,
281281
) -> "Synapse":
282282
"""
283283
Initialize Synapse object
@@ -301,6 +301,9 @@ def __init__(
301301
asyncio_event_loop: The event loop that is going to be used while executing
302302
this code. This is optional and only used when you are manually
303303
specifying an async HTTPX client.
304+
cache_client: Whether to cache the Synapse client object in the Synapse module. Defaults to True.
305+
When set to True anywhere a `Synapse` object is optional you do not need to pass an
306+
instance of `Synapse` to that function, method, or class.
304307
305308
Raises:
306309
ValueError: Warn for non-boolean debug value.
@@ -412,6 +415,8 @@ def log_response(response: httpx.Response) -> None:
412415
self._parallel_file_transfer_semaphore = {}
413416
self.use_boto_sts_transfers = transfer_config["use_boto_sts"]
414417
self._parts_transfered_counter = 0
418+
if cache_client:
419+
Synapse.set_client(synapse_client=self)
415420

416421
def _get_requests_session_async_synapse(
417422
self, asyncio_event_loop: asyncio.AbstractEventLoop
@@ -709,7 +714,6 @@ def login(
709714
email: str = None,
710715
silent: bool = False,
711716
authToken: str = None,
712-
cache_client: bool = True,
713717
) -> None:
714718
"""
715719
Valid combinations of login() arguments:
@@ -730,9 +734,6 @@ def login(
730734
authToken: A bearer authorization token, e.g. a
731735
[personal access token](https://python-docs.synapse.org/tutorials/authentication/).
732736
silent: Defaults to False. Suppresses the "Welcome ...!" message.
733-
cache_client: Whether to cache the Synapse client object in the Synapse module. Defaults to True.
734-
When set to True anywhere a `Synapse` object is optional you do not need to pass an
735-
instance of `Synapse` to that function, method, or class.
736737
737738
Example: Logging in
738739
Using an auth token:
@@ -774,9 +775,6 @@ def login(
774775
display_name = self.credentials.displayname or self.credentials.username
775776
self.logger.info(f"Welcome, {display_name}!\n")
776777

777-
if cache_client:
778-
Synapse.set_client(self)
779-
780778
@deprecated(
781779
version="4.4.0",
782780
reason="To be removed in 5.0.0. "
@@ -1954,14 +1952,9 @@ def store(
19541952
upload_file_handle_async(
19551953
self,
19561954
parent_id_for_upload,
1957-
(
1958-
local_state["path"]
1959-
if (
1960-
synapseStore
1961-
or local_state_fh.get("externalURL") is None
1962-
)
1963-
else local_state_fh.get("externalURL")
1964-
),
1955+
local_state["path"]
1956+
if (synapseStore or local_state_fh.get("externalURL") is None)
1957+
else local_state_fh.get("externalURL"),
19651958
synapse_store=synapseStore,
19661959
md5=local_file_md5_hex or local_state_fh.get("contentMd5"),
19671960
file_size=local_state_fh.get("contentSize"),
@@ -3131,11 +3124,9 @@ def _convertProvenanceList(self, usedList: list, limitSearch: str = None) -> lis
31313124
if usedList is None:
31323125
return None
31333126
usedList = [
3134-
(
3135-
self.get(target, limitSearch=limitSearch)
3136-
if (os.path.isfile(target) if isinstance(target, str) else False)
3137-
else target
3138-
)
3127+
self.get(target, limitSearch=limitSearch)
3128+
if (os.path.isfile(target) if isinstance(target, str) else False)
3129+
else target
31393130
for target in usedList
31403131
]
31413132
return usedList
@@ -4938,6 +4929,7 @@ def getWiki(self, owner, subpageId=None, version=None):
49384929
destination=os.path.join(
49394930
cache_dir, str(wiki.markdownFileHandleId) + ".md"
49404931
),
4932+
synapse_client=self,
49414933
),
49424934
syn=self,
49434935
)
@@ -5606,6 +5598,7 @@ def _queryTableCsv(
56065598
synapse_id=extract_synapse_id_from_query(query),
56075599
entity_type="TableEntity",
56085600
destination=os.path.join(download_dir, filename),
5601+
synapse_client=self,
56095602
),
56105603
syn=self,
56115604
)

synapseclient/core/download/download_async.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,9 @@ async def download_file(self) -> None:
314314
syn=self._syn, url=url_info.url, debug=self._download_request.debug
315315
)
316316
self._progress_bar = get_or_create_download_progress_bar(
317-
file_size=file_size, postfix=self._download_request.object_id
317+
file_size=file_size,
318+
postfix=self._download_request.object_id,
319+
synapse_client=self._syn,
318320
)
319321
self._prep_file()
320322

synapseclient/core/download/download_functions.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ async def download_file_entity(
166166
synapse_id=object_id,
167167
entity_type=object_type,
168168
destination=download_path,
169+
synapse_client=client,
169170
)
170171

171172
if download_path is None or not os.path.exists(download_path):
@@ -274,6 +275,7 @@ async def download_file_entity_model(
274275
synapse_id=object_id,
275276
entity_type=object_type,
276277
destination=download_path,
278+
synapse_client=client,
277279
)
278280

279281
if download_path is None or not os.path.exists(download_path):
@@ -416,7 +418,7 @@ async def download_by_file_handle(
416418
)
417419

418420
progress_bar = get_or_create_download_progress_bar(
419-
file_size=1, postfix=synapse_id
421+
file_size=1, postfix=synapse_id, synapse_client=syn
420422
)
421423
loop = asyncio.get_running_loop()
422424
downloaded_path = await loop.run_in_executor(
@@ -440,7 +442,7 @@ async def download_by_file_handle(
440442
and concrete_type == concrete_types.S3_FILE_HANDLE
441443
):
442444
progress_bar = get_or_create_download_progress_bar(
443-
file_size=1, postfix=synapse_id
445+
file_size=1, postfix=synapse_id, synapse_client=syn
444446
)
445447

446448
def download_fn(
@@ -496,7 +498,7 @@ def download_fn(
496498
else:
497499
loop = asyncio.get_running_loop()
498500
progress_bar = get_or_create_download_progress_bar(
499-
file_size=1, postfix=synapse_id
501+
file_size=1, postfix=synapse_id, synapse_client=syn
500502
)
501503
downloaded_path = await loop.run_in_executor(
502504
syn._get_thread_pool_executor(asyncio_event_loop=loop),

synapseclient/core/transfer_bar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def shared_download_progress_bar(
8585

8686
syn = Synapse.get_client(synapse_client=synapse_client)
8787
with logging_redirect_tqdm(loggers=[syn.logger]):
88-
get_or_create_download_progress_bar(file_size=file_size)
88+
get_or_create_download_progress_bar(file_size=file_size, synapse_client=syn)
8989
try:
9090
yield
9191
finally:

tests/integration/synapseclient/integration_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ async def testCustomConfigFile(schedule_for_cleanup):
7878
shutil.copyfile(client.CONFIG_FILE, configPath)
7979
schedule_for_cleanup(configPath)
8080

81-
syn2 = Synapse(configPath=configPath)
81+
syn2 = Synapse(configPath=configPath, cache_client=False)
8282
syn2.login()
8383
else:
8484
raise ValueError(

tests/integration/synapseclient/test_command_line_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ async def test_table_query(test_state):
900900

901901

902902
async def test_login(test_state):
903-
alt_syn = Synapse()
903+
alt_syn = Synapse(cache_client=False)
904904
username = "username"
905905
auth_token = "my_auth_token"
906906
with patch.object(alt_syn, "login") as mock_login, patch.object(

tests/integration/synapseclient/test_evaluations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ async def test_teams(syn: Synapse, schedule_for_cleanup):
178178
schedule_for_cleanup(team)
179179

180180
# not logged in, teams are public
181-
anonymous_syn = Synapse()
181+
anonymous_syn = Synapse(cache_client=False)
182182

183183
found_team = anonymous_syn.getTeam(team.id)
184184
assert team == found_team

tests/unit/synapseclient/core/unit_test_download.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ async def test_mock_download(syn: Synapse) -> None:
162162
destination=temp_dir,
163163
file_handle_id=12345,
164164
expected_md5=contents_md5,
165+
synapse_client=syn,
165166
)
166167

167168
# 2. Multiple redirects
@@ -181,6 +182,7 @@ async def test_mock_download(syn: Synapse) -> None:
181182
destination=temp_dir,
182183
file_handle_id=12345,
183184
expected_md5=contents_md5,
185+
synapse_client=syn,
184186
)
185187

186188
# 3. recover from partial download
@@ -286,6 +288,7 @@ async def test_mock_download(syn: Synapse) -> None:
286288
synapse_id=objectId,
287289
entity_type=objectType,
288290
destination=temp_dir,
291+
synapse_client=syn,
289292
)
290293

291294
# 5. don't recover, a partial download that never completes
@@ -337,6 +340,7 @@ async def test_mock_download(syn: Synapse) -> None:
337340
synapse_id=objectId,
338341
entity_type=objectType,
339342
destination=temp_dir,
343+
synapse_client=syn,
340344
)
341345

342346
# 6. 206 Range header not supported, respond with 200 and full file
@@ -377,6 +381,7 @@ async def test_mock_download(syn: Synapse) -> None:
377381
synapse_id=objectId,
378382
entity_type=objectType,
379383
destination=temp_dir,
384+
synapse_client=syn,
380385
)
381386

382387
# 7. Too many redirects
@@ -408,6 +413,7 @@ async def test_mock_download(syn: Synapse) -> None:
408413
synapse_id=objectId,
409414
entity_type=objectType,
410415
destination=temp_dir,
416+
synapse_client=syn,
411417
)
412418

413419

@@ -445,6 +451,7 @@ async def test_multithread_true_s3_file_handle(self) -> None:
445451
synapse_id=456,
446452
entity_type="FileEntity",
447453
destination="/myfakepath",
454+
synapse_client=self.syn,
448455
)
449456

450457
mock_multi_thread_download.assert_called_once_with(
@@ -478,6 +485,7 @@ async def _multithread_not_applicable(self, file_handle: Dict[str, str]) -> None
478485
synapse_id=456,
479486
entity_type="FileEntity",
480487
destination="/myfakepath",
488+
synapse_client=self.syn,
481489
)
482490

483491
mock_download_from_URL.assert_called_once_with(
@@ -534,6 +542,7 @@ async def test_multithread_false_s3_file_handle(self) -> None:
534542
synapse_id=456,
535543
entity_type="FileEntity",
536544
destination="/myfakepath",
545+
synapse_client=self.syn,
537546
)
538547

539548
mock_download_from_URL.assert_called_once_with(
@@ -674,7 +683,7 @@ async def test_download_end_early_retry(syn: Synapse) -> None:
674683
shutil, "move"
675684
) as mocked_move:
676685
# function under test
677-
download_from_url(url=url, destination=destination)
686+
download_from_url(url=url, destination=destination, synapse_client=syn)
678687

679688
# assert temp_download_filename() called 2 times with same parameters
680689
assert [
@@ -742,7 +751,10 @@ async def test_download_md5_mismatch__not_local_file(syn: Synapse) -> None:
742751
# function under test
743752
with pytest.raises(SynapseMd5MismatchError):
744753
await download_from_url(
745-
url=url, destination=destination, expected_md5="fake md5 is fake"
754+
url=url,
755+
destination=destination,
756+
expected_md5="fake md5 is fake",
757+
synapse_client=syn,
746758
)
747759

748760
# assert temp_download_filename() called once

tests/unit/synapseclient/core/unit_test_sts_transfer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ def synGET(uri):
366366
@mock.patch("synapseclient.core.sts_transfer.StsTokenStore._fetch_token")
367367
def test_synapse_client__discrete_sts_token_stores(self, mock_fetch_token):
368368
"""Verify that two Synapse objects will not share the same cached tokens"""
369-
syn1 = Synapse(skip_checks=True)
370-
syn2 = Synapse(skip_checks=True)
369+
syn1 = Synapse(skip_checks=True, cache_client=False)
370+
syn2 = Synapse(skip_checks=True, cache_client=False)
371371

372372
expected_token = {
373373
"awsAccessKeyId": "ABC",

tests/unit/synapseclient/core/upload/unit_test_multipart_upload.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,15 +727,19 @@ def test_multipart_upload_file(self):
727727
)
728728

729729
# Test when call the multipart_upload_file, md5_for_file pass in the correct callback function
730-
syn_with_silent_mode = Synapse(silent=True, skip_checks=True)
730+
syn_with_silent_mode = Synapse(
731+
silent=True, skip_checks=True, cache_client=False
732+
)
731733
multipart_upload_file(
732734
syn_with_silent_mode,
733735
file_path,
734736
storage_location_id=storage_location_id,
735737
)
736738
md5_for_file.assert_called_with(file_path, callback=None)
737739

738-
syn_with_no_silent_mode = Synapse(debug=False, skip_checks=True)
740+
syn_with_no_silent_mode = Synapse(
741+
debug=False, skip_checks=True, cache_client=False
742+
)
739743
multipart_upload_file(
740744
syn_with_no_silent_mode,
741745
file_path,

0 commit comments

Comments
 (0)