Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Merge branch 'linglp/synpy-967-linglp' to develop" #982

Merged
merged 1 commit into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions synapseclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
id_of,
get_properties,
MB,
memoize,
is_json,
extract_synapse_id_from_query,
find_data_file_handle,
Expand Down Expand Up @@ -497,7 +498,7 @@ def login(
cached_sessions.set_most_recent_user(self.credentials.username)

if not silent:
profile = self.getUserProfile()
profile = self.getUserProfile(refresh=True)
# TODO-PY3: in Python2, do we need to ensure that this is encoded in utf-8
self.logger.info(
"Welcome, %s!\n"
Expand Down Expand Up @@ -611,23 +612,26 @@ def invalidateAPIKey(self):
if self._is_logged_in():
self.restDELETE("/secretKey", endpoint=self.authEndpoint)

@functools.lru_cache()
@memoize
def getUserProfile(
self,
id: Union[str, int, UserProfile, TeamMember] = None,
sessionToken: str = None,
refresh: bool = False,
) -> UserProfile:
"""
Get the details about a Synapse user.
Retrieves information on the current user if 'id' is omitted.
:param id: The 'userId' (aka 'ownerId') of a user or the userName
:param sessionToken: The session token to use to find the user profile
:param refresh: If set to True will always fetch the data from Synape otherwise will use cached information
:returns: The user profile for the user of interest.

Example::
my_profile = syn.getUserProfile()
freds_profile = syn.getUserProfile('fredcommo')
"""

try:
# if id is unset or a userID, this will succeed
id = "" if id is None else int(id)
Expand All @@ -648,6 +652,7 @@ def getUserProfile(
else: # no break
raise ValueError('Can\'t find user "%s": ' % id)
uri = "/userProfile/%s" % id

return UserProfile(
**self.restGET(
uri, headers={"sessionToken": sessionToken} if sessionToken else None
Expand Down Expand Up @@ -2644,7 +2649,7 @@ def _download_from_URL(
else:
mode = "wb"
previouslyTransferred = 0
sig = hashlib.new("md5", usedforsecurity=False)
sig = hashlib.md5()

try:
with open(temp_destination, mode) as fd:
Expand Down Expand Up @@ -4766,6 +4771,7 @@ def _generate_headers(self, headers=None):

if headers is None:
headers = dict(self.default_headers)

headers.update(synapseclient.USER_AGENT)

return headers
Expand Down Expand Up @@ -4801,7 +4807,6 @@ def _rest_call(
uri, headers = self._build_uri_and_headers(
uri, endpoint=endpoint, headers=headers
)

retryPolicy = self._build_retry_policy(retryPolicy)
requests_session = requests_session or self._requests_session

Expand All @@ -4818,7 +4823,6 @@ def _rest_call(
verbose=self.debug,
**retryPolicy,
)

self._handle_synapse_http_error(response)
return response

Expand Down
18 changes: 17 additions & 1 deletion synapseclient/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import collections.abc
import datetime
import errno
import functools
import hashlib
import importlib
import inspect
Expand Down Expand Up @@ -45,7 +46,7 @@ def md5_for_file(filename, block_size=2 * MB, callback=None):
:returns: The MD5
"""

md5 = hashlib.new("md5", usedforsecurity=False)
md5 = hashlib.md5()
with open(filename, "rb") as f:
while True:
if callback:
Expand Down Expand Up @@ -638,6 +639,21 @@ def extract_synapse_id_from_query(query):
raise ValueError('Couldn\'t extract synapse ID from query: "%s"' % query)


# Derived from https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
def memoize(obj):
cache = obj._memoize_cache = {}

@functools.wraps(obj)
def memoizer(*args, **kwargs):
refresh = kwargs.pop("refresh", False)
key = str(args) + str(kwargs)
if refresh or key not in cache:
cache[key] = obj(*args, **kwargs)
return cache[key]

return memoizer


def printTransferProgress(
transferred,
toBeTransferred,
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/synapseclient/core/unit_test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def test_md5_for_file(mock_hashlib):
file_name = "/home/foo/bar/test.txt"
mock_callback = Mock()
mock_md5 = Mock()
mock_hashlib.new.return_value = mock_md5
mock_hashlib.md5.return_value = mock_md5
with patch.object(utils, "open", mock_open(), create=True) as mocked_open:
mocked_open.return_value.read.side_effect = ["data1", "data2", None]
utils.md5_for_file(file_name, callback=mock_callback)
Expand Down
1 change: 1 addition & 0 deletions tests/unit/synapseclient/unit_test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def test_login__silentIsFalse(self):
# method under test
self.syn.login(silent=False, **self.login_args)

mocked_get_user_profile.assert_called_once_with(refresh=True)
mocked_logger.info.assert_called_once()

def test_login__rememberMeIsTrue(self, mocker):
Expand Down
Loading