Skip to content
Closed
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
7 changes: 6 additions & 1 deletion src/citrine/_rest/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ def build(self, data: dict):
def get(self, uid: Union[UUID, str]) -> ResourceType:
"""Get a particular element of the collection."""
if uid is None:
raise ValueError("Cannot get when uid=None. Are you using a registered resource?")
raise ValueError(
"Cannot retrieve a resource with uid=None. "
"This usually means the object has not been "
"registered with the platform yet. Call "
".register() first to obtain a server-assigned "
"UID.")
path = self._get_path(uid)
data = self.session.get_resource(path, version=self._api_version)
data = data[self._individual_key] if self._individual_key else data
Expand Down
29 changes: 22 additions & 7 deletions src/citrine/_serialization/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,13 @@ def serialize(self, value: DeserializedType,
base_class: typing.Optional[type] = None) -> SerializedType:
if not isinstance(value, self.underlying_types):
base_name = self._error_source(base_class)
value_repr = repr(value)
if len(value_repr) > 100:
value_repr = value_repr[:100] + "..."
raise ValueError(
f'{type(value)} {value} is not one of valid types: '
f'{self.underlying_types}{base_name}'
f'{type(value).__name__} is not one of valid '
f'types: {self.underlying_types}{base_name}. '
f'Value: {value_repr}'
)
return self._serialize(value)

Expand All @@ -107,9 +111,13 @@ def deserialize(self, value: SerializedType,
if isinstance(value, self.underlying_types):
return value # Don't worry if it was already deserialized
base_name = self._error_source(base_class)
value_repr = repr(value)
if len(value_repr) > 100:
value_repr = value_repr[:100] + "..."
raise ValueError(
f'{type(value)} {value} is not one of valid types: '
f'{self.serialized_types}{base_name}'
f'{type(value).__name__} is not one of valid '
f'types: {self.serialized_types}{base_name}. '
f'Value: {value_repr}'
)
return self._deserialize(value)

Expand All @@ -129,9 +137,16 @@ def deserialize_from_dict(self, data: dict) -> DeserializedType:
next_value = value.get(field)
if next_value is None:
if self.default is None and not self.optional:
msg = "Unable to deserialize {} into {}, missing a required field: {}".format(
data, self.underlying_types, field)
raise ValueError(msg)
data_preview = str(data)
if len(data_preview) > 200:
data_preview = data_preview[:200] + "..."
raise ValueError(
"Unable to deserialize into {}: "
"missing required field '{}'. "
"Data: {}".format(
self.underlying_types,
field, data_preview)
)
# This occurs if a `field` is unexpectedly not present in the data dictionary
# or if its value is null.
# Use the default value and stop traversing, even if we have not yet reached
Expand Down
17 changes: 15 additions & 2 deletions src/citrine/_utils/batcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ def batch(self, objects: Iterable[DataConcepts], batch_size) -> List[List[DataCo
for obj in objects:
if obj.to_link() in seen: # Repeat in the iterable; don't add it to the batch
if seen[obj.to_link()] != obj: # verify that it's a replicate
raise ValueError(f"Colliding objects for {obj.to_link()}")
raise ValueError(
"Colliding objects for {}: two different "
"objects share the same identifier. Ensure "
"each object has a unique UID.".format(
obj.to_link()))
else:
by_type[obj.typ].append(obj)
for scope in obj.uids:
Expand Down Expand Up @@ -80,7 +84,16 @@ def batch(self, objects: Iterable[DataConcepts], batch_size) -> List[List[DataCo
local_set = {index.get(x, x) for x in depends[obj] if index.get(x, x) in obj_set}
full_set = set(local_set)
if len(full_set) > batch_size:
raise ValueError(f"Object {obj.name} has more than {batch_size} dependencies.")
sample = [getattr(d, 'name', str(d))
for d in list(full_set)[:10]]
raise ValueError(
"Object '{}' has {} dependencies, "
"exceeding batch_size={}. First {}: {}. "
"Increase batch_size or simplify the "
"dependency graph.".format(
obj.name, len(full_set),
batch_size, len(sample), sample)
)

for subobj in local_set:
full_set.update(depends[subobj])
Expand Down
Loading