Skip to content

Commit

Permalink
Refactor id_of() to validate IDs of all kinds of entities
Browse files Browse the repository at this point in the history
  • Loading branch information
jaymedina committed Sep 25, 2024
1 parent 857154e commit 29a72b9
Showing 1 changed file with 37 additions and 19 deletions.
56 changes: 37 additions & 19 deletions synapseclient/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,35 +211,53 @@ def _get_from_members_items_or_properties(obj, key):


# TODO: what does this do on an unsaved Synapse Entity object?
def id_of(obj: typing.Union[str, collections.abc.Mapping, numbers.Number]) -> str:
def id_of(obj: typing.Union[str, collections.abc.Mapping, numbers.Number], id_type: str = None) -> str:
"""
Try to figure out the Synapse ID of the given object.
Try to figure out the Synapse ID of the given object and ensure it is a valid ID.
File entity IDs can have decimals; other types of IDs must be whole numbers.
Arguments:
obj: May be a string, Entity object, or dictionary
obj: May be a string, Entity object, or dictionary.
id_type: The type of entity for which this ID represents. Used to differentiate between File entity IDs and other types.
This is done to allow for handling entities that support decimal IDs (Files) and ones that cannot.
Returns:
The ID
The ID as a string.
Raises:
ValueError: if the object doesn't have an ID
ValueError: If the object doesn't have a valid ID or if non-File IDs contain decimals.
"""
# If obj is a string, check if it's a valid ID
if isinstance(obj, str):
return str(obj)
# Only File synapse IDs can have decimals (to denote File versions)
if id_type == 'File' or "." not in obj:
return obj
else:
raise ValueError(f"Invalid ID: {obj}. Decimals not supported for non-File entity IDs.")

# If obj is a number, allow decimals only for File IDs
if isinstance(obj, numbers.Number):
return str(obj)

id_attr_names = [
"id",
"ownerId",
"tableId",
] # possible attribute names for a synapse Id
for attribute_name in id_attr_names:
syn_id = _get_from_members_items_or_properties(obj, attribute_name)
if syn_id is not None:
return str(syn_id)

raise ValueError("Invalid parameters: couldn't find id of " + str(obj))
if id_type == 'File':
return str(obj) # Allow decimal numbers for File entity IDs
elif obj == int(obj): # Ensure whole numbers for non-File IDs
return str(int(obj))
else:
raise ValueError(f"Invalid ID: {obj}. Must be a whole number.")

if isinstance(obj, collections.abc.Mapping):
id_attr_names = [
"id",
"ownerId",
"tableId",
]
for attribute_name in id_attr_names:
syn_id = _get_from_members_items_or_properties(obj, attribute_name)
if syn_id is not None:
return id_of(syn_id)

# Raise an error if the object does not have a valid ID
raise ValueError("Invalid parameters: couldn't find ID of " + str(obj))


def concrete_type_of(obj: collections.abc.Mapping):
Expand Down

0 comments on commit 29a72b9

Please sign in to comment.