It's not None yet though until we get past

        if isinstance(self.type, AnyType) or not isinstance(value, self.type):
            value = self._new(value)
        else:
            # a type may not share the same namespace as its container
            # so if we were given a full type, ensure it is set up
            # with the proper tag and namespace for this context
            self._set_xml_context(value)

Before that, value is an etree.Element. We could run some of the same checks we run in ComplexType.__init__ further up in __set__ (if element is empty and says nil="true", return) but it seems kind of duplicative to check in both places (though this check would be slightly different because it wouldn't care if there were attributes other than nil="true").

What do you think about removing the non_nil_attrib helper function and reverting the change to ComplexType.__init__? I've tried it and it seems to have the same effect as the current PR...