5454)
5555from polyfactory .exceptions import ConfigurationException , MissingBuildKwargException , ParameterException
5656from polyfactory .field_meta import Null
57- from polyfactory .fields import Fixture , Ignore , PostGenerated , Require , Use
57+ from polyfactory .fields import Fixture , Ignore , NeverNone , PostGenerated , Require , Use
5858from polyfactory .utils .helpers import (
5959 flatten_annotation ,
6060 get_collection_type ,
@@ -334,6 +334,7 @@ def _handle_factory_field( # noqa: PLR0911
334334 if isinstance (field_value , Fixture ):
335335 return field_value .to_value ()
336336
337+ # if a raw lambda is passed, invoke it
337338 if callable (field_value ):
338339 return field_value ()
339340
@@ -942,8 +943,12 @@ def should_set_none_value(cls, field_meta: FieldMeta) -> bool:
942943 :returns: A boolean determining whether 'None' should be set for the given field_meta.
943944
944945 """
946+ field_value = hasattr (cls , field_meta .name ) and getattr (cls , field_meta .name )
947+ never_none = field_value and isinstance (field_value , NeverNone )
948+
945949 return (
946950 cls .__allow_none_optionals__
951+ and not never_none
947952 and is_optional (field_meta .annotation )
948953 and create_random_boolean (random = cls .__random__ )
949954 )
@@ -1017,13 +1022,15 @@ def _check_declared_fields_exist_in_model(cls) -> None:
10171022 f"{ field_name } is declared on the factory { cls .__name__ } "
10181023 f" but it is not part of the model { cls .__model__ .__name__ } "
10191024 )
1020- if isinstance (field_value , (Use , PostGenerated , Ignore , Require )):
1025+ if isinstance (field_value , (Use , PostGenerated , Ignore , Require , NeverNone )):
10211026 raise ConfigurationException (error_message )
10221027
10231028 @classmethod
10241029 def process_kwargs (cls , ** kwargs : Any ) -> dict [str , Any ]:
10251030 """Process the given kwargs and generate values for the factory's model.
10261031
1032+ If you need to deeply customize field values, you'll want to override this method.
1033+
10271034 :param kwargs: Any build kwargs.
10281035
10291036 :returns: A dictionary of build results.
@@ -1034,8 +1041,11 @@ def process_kwargs(cls, **kwargs: Any) -> dict[str, Any]:
10341041 for field_meta in cls .get_model_fields ():
10351042 field_build_parameters = cls .extract_field_build_parameters (field_meta = field_meta , build_args = kwargs )
10361043 if cls .should_set_field_value (field_meta , ** kwargs ) and not cls .should_use_default_value (field_meta ):
1037- if hasattr (cls , field_meta .name ) and not hasattr (BaseFactory , field_meta .name ):
1038- field_value = getattr (cls , field_meta .name )
1044+ field_value = getattr (cls , field_meta .name , None )
1045+
1046+ # TODO why do we need the BaseFactory check here, only dunder methods which are ignored would trigger this?
1047+ # NeverNone should be treated as a normally-generated field
1048+ if field_value and not hasattr (BaseFactory , field_meta .name ) and not isinstance (field_value , NeverNone ):
10391049 if isinstance (field_value , Ignore ):
10401050 continue
10411051
0 commit comments