Skip to content

Commit

Permalink
feat: Improve handling of UUID fields
Browse files Browse the repository at this point in the history
  • Loading branch information
mLupine committed Oct 5, 2023
1 parent e74f1cf commit 280cc07
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ or extend custom Schema classes. To use it, just inherit from `JitSchemaMixin`.
Let's take a look at the following example:

```python
from marshmallow import fields

class ClockSchema(MyAwesomeBaseSchema):
time = fields.DateTime(data_key="Time")
```
Expand Down
26 changes: 24 additions & 2 deletions deepfriedmarshmallow/jit.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class FieldInliner:

@abstractmethod
def inline(self, field, context):
# type: (marshmallow.fields.Field, JitContext) -> Optional[str]
# type: (marshmallow.fields.Field, JitContext) -> Optional[Union[str, tuple]]
pass # pragma: no cover


Expand Down Expand Up @@ -258,6 +258,21 @@ def inline(self, field, context):
return result


class UUIDInliner(FieldInliner):
def inline(self, field, context):
# type: (marshmallow.fields.Field, JitContext) -> Optional[tuple]

"""Generates a template for inlining UUID serialization."""
if is_overridden(field._serialize, marshmallow.fields.UUID._serialize):
return None
result = "uuid.UUID({0})"
result += " if {0} is not None and isinstance({0}, str) else "
result += "({0} if {0} is not None and isinstance({0}, uuid.UUID) else None)"
if not context.is_serializing:
result = f"({result})" + " if (isinstance({0}, (uuid.UUID, str)) or {0} is None) else dict()['error']"
return result, "uuid"


class BooleanInliner(FieldInliner):
def inline(self, field, context):
# type: (marshmallow.fields.Field, JitContext) -> Optional[str]
Expand Down Expand Up @@ -395,6 +410,7 @@ def generate_transform_method_body(schema, on_field, context):
"""Generates the method body for a schema and a given field serialization
strategy.
"""
required_imports = set()
body = IndentedString()
body += f"def {on_field.__class__.__name__}(obj):"
with body.indent():
Expand Down Expand Up @@ -431,8 +447,11 @@ def generate_transform_method_body(schema, on_field, context):
# Attempt to see if this field type can be inlined.
inliner = inliner_for_field(context, field_obj)

if inliner:
if inliner and isinstance(inliner, str):
assignment_template += _generate_inlined_access_template(inliner, result_key, no_callable_fields)
elif inliner and isinstance(inliner, tuple):
assignment_template += _generate_inlined_access_template(inliner[0], result_key, no_callable_fields)
required_imports.update(inliner[1] if isinstance(inliner[1], (list, set, tuple)) else [inliner[1]])

else:
assignment_template += _generate_fallback_access_template(
Expand Down Expand Up @@ -495,6 +514,8 @@ def generate_transform_method_body(schema, on_field, context):
body += f'{field_symbol}__validate(res["{result_key}"])'

body += "return res"
if required_imports:
body = IndentedString("\n".join([f"import {x}" for x in required_imports]) + "\n" + str(body))
return body


Expand Down Expand Up @@ -542,6 +563,7 @@ def _generate_inlined_access_template(inliner, key, no_callable_fields):
def inliner_for_field(context, field_obj):
# type: (JitContext, marshmallow.fields.Field) -> Optional[str]
inliners = {
marshmallow.fields.UUID: UUIDInliner(),
marshmallow.fields.String: StringInliner(),
marshmallow.fields.Number: NumberInliner(),
marshmallow.fields.Boolean: BooleanInliner(),
Expand Down

0 comments on commit 280cc07

Please sign in to comment.