FireO
FireO copied to clipboard
[code included] Support for Field(default_factory=)
I have a PR but the repo is closed and I do not seem to have permissions to push a branch and create a PR
In essence, it is desirable to be able to dynamically set a default value (i.e. pass a callable and have it execute later during parsing).
diff --git a/src/fireo/fields/field_attribute.py b/src/fireo/fields/field_attribute.py
index dbd50db..65b0512 100644
--- a/src/fireo/fields/field_attribute.py
+++ b/src/fireo/fields/field_attribute.py
@@ -22,6 +22,9 @@ class FieldAttribute:
default:
if no value is define then default value is set for field
+ default_factory:
+ if no value is defined then default_factory is called and set for field
+
required:
Required field if no value or default set raise an Error
@@ -56,7 +59,7 @@ class FieldAttribute:
AttributeMethodNotDefined:
if any custom field not define the method for `allowed_attributes`
"""
- allowed_attributes = ['default', 'required', 'column_name', 'validator', 'validator_kwargs']
+ allowed_attributes = ['default', 'default_factory', 'required', 'column_name', 'validator', 'validator_kwargs']
def __init__(self, field, attributes):
self.field = field
@@ -77,10 +80,19 @@ class FieldAttribute:
# return the value back
return value
+ if self.default is not None and self.default_factory is not None:
+ raise AttributeError('default and default_factory are mutually exclusive')
+
# check default value if set for field
if self.default is not None and value is None and not ignore_default:
value = self.default
+ if self.default_factory is not None:
+ if not callable(self.default_factory):
+ raise AttributeError('default_factory must be a callable')
+
+ value = self.default_factory()
+
# check this field is required or not
if self.required and value is None and not ignore_required:
raise RequiredField(f'"{self.field.__class__.__name__}" is required for model {self.field.model_cls} '
@@ -200,6 +212,11 @@ class FieldAttribute:
"""if no value is define then default value is set for field"""
return self.attributes.get('default')
+ @property
+ def default_factory(self):
+ """if no value is defined then default_factory is called and set for field"""
+ return self.attributes.get('default_factory')
+
@property
def required(self):
"""Required field if no value or default set raise an Error"""
diff --git a/src/tests/v150/test_field_default_factory.py b/src/tests/v150/test_field_default_factory.py
new file mode 100644
index 0000000..e4ac908
--- /dev/null
+++ b/src/tests/v150/test_field_default_factory.py
@@ -0,0 +1,42 @@
+from fireo.fields import TextField
+from fireo.fields.errors import AttributeTypeError
+from fireo.models import Model
+import pytest
+
+
+def test_create_field_with_valid_default_factory():
+ def my_dynamic_default_value():
+ # or uuid.uuid4 or ...
+ return 'random_string'
+
+ class TextFieldDefaultFactory(Model):
+ name = TextField(default_factory=my_dynamic_default_value)
+
+ model = TextFieldDefaultFactory()
+ model.save()
+
+ assert model.name == 'random_string'
+
+
+def test_create_field_with_uncallable_default_factory():
+ class TextFieldDefaultFactory(Model):
+ name = TextField(default_factory='random string')
+
+ model = TextFieldDefaultFactory()
+
+ with pytest.raises(AttributeTypeError):
+ model.save()
+
+
+def test_create_field_with_default_and_default_factory():
+ def my_dynamic_default_value():
+ # or uuid.uuid4 or ...
+ return 'random_string'
+
+ class TextFieldDefaultFactory(Model):
+ name = TextField(default='test', default_factory=my_dynamic_default_value)
+
+ model = TextFieldDefaultFactory()
+
+ with pytest.raises(AttributeTypeError):
+ model.save()
Repo is open for any PR I don't know why you are not able to send PR can you please check it on your end and send PR or if you see any error please let me know, Thanks for your contribution!