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
@@ -946,8 +947,12 @@ def should_set_none_value(cls, field_meta: FieldMeta) -> bool:
946947 :returns: A boolean determining whether 'None' should be set for the given field_meta.
947948
948949 """
950+ field_value = hasattr (cls , field_meta .name ) and getattr (cls , field_meta .name )
951+ never_none = field_value and isinstance (field_value , NeverNone )
952+
949953 return (
950954 cls .__allow_none_optionals__
955+ and not never_none
951956 and is_optional (field_meta .annotation )
952957 and create_random_boolean (random = cls .__random__ )
953958 )
@@ -1021,13 +1026,15 @@ def _check_declared_fields_exist_in_model(cls) -> None:
10211026 f"{ field_name } is declared on the factory { cls .__name__ } "
10221027 f" but it is not part of the model { cls .__model__ .__name__ } "
10231028 )
1024- if isinstance (field_value , (Use , PostGenerated , Ignore , Require )):
1029+ if isinstance (field_value , (Use , PostGenerated , Ignore , Require , NeverNone )):
10251030 raise ConfigurationException (error_message )
10261031
10271032 @classmethod
10281033 def process_kwargs (cls , ** kwargs : Any ) -> dict [str , Any ]:
10291034 """Process the given kwargs and generate values for the factory's model.
10301035
1036+ If you need to deeply customize field values, you'll want to override this method.
1037+
10311038 :param kwargs: Any build kwargs.
10321039
10331040 :returns: A dictionary of build results.
@@ -1038,8 +1045,11 @@ def process_kwargs(cls, **kwargs: Any) -> dict[str, Any]:
10381045 for field_meta in cls .get_model_fields ():
10391046 field_build_parameters = cls .extract_field_build_parameters (field_meta = field_meta , build_args = kwargs )
10401047 if cls .should_set_field_value (field_meta , ** kwargs ) and not cls .should_use_default_value (field_meta ):
1041- if hasattr (cls , field_meta .name ) and not hasattr (BaseFactory , field_meta .name ):
1042- field_value = getattr (cls , field_meta .name )
1048+ field_value = getattr (cls , field_meta .name , None )
1049+
1050+ # TODO why do we need the BaseFactory check here, only dunder methods which are ignored would trigger this?
1051+ # NeverNone should be treated as a normally-generated field
1052+ if field_value and not hasattr (BaseFactory , field_meta .name ) and not isinstance (field_value , NeverNone ):
10431053 if isinstance (field_value , Ignore ):
10441054 continue
10451055
0 commit comments