(self)
return _propagate_and_normalize_case_properties(
            case_properties_by_case_type,
            parent_type_map=self.get_parent_type_map(case_types=None),
            include_parent_properties=self.include_parent_properties
        )
Get all possible properties for each case type

        Data sources for this are (limited to):
        - the app given
        - all other case sharing apps if app.case_sharing
        - the Data Dictionary case properties if toggles.DATA_DICTIONARY
        - the `defaults` passed in to the class
        - the `per_type_defaults` for usercases and call center cases, if applicable

        Notably, it propagates parent/<property> on a child up to the <property> on the parent,
        and, only if `include_parent_properties` was not passed in as False to the class,
        also propagates <property> on the parent down to parent/<property> on the child.
        This propagation is (conceptually) recursive, going all the way up (and down) the chain.
        (In actuality, the implementation is iterative,
        for ease of reasoning and pobably also efficiency.)

        :return: {<case_type>: set([<property>])} for all case types found
Get all possible properties for each case type
Get all possible properties for each case type
def get_properties_by_case_type(self):
        """
        Get all possible properties for each case type

        Data sources for this are (limited to):
        - the app given
        - all other case sharing apps if app.case_sharing
        - the Data Dictionary case properties if toggles.DATA_DICTIONARY
        - the `defaults` passed in to the class
        - the `per_type_defaults` for usercases and call center cases, if applicable

        Notably, it propagates parent/<property> on a child up to the <property> on the parent,
        and, only if `include_parent_properties` was not passed in as False to the class,
        also propagates <property> on the parent down to parent/<property> on the child.
        This propagation is (conceptually) recursive, going all the way up (and down) the chain.
        (In actuality, the implementation is iterative,
        for ease of reasoning and pobably also efficiency.)

        :return: {<case_type>: set([<property>])} for all case types found
        """
        from corehq.apps.data_dictionary.util import get_data_dict_props_by_case_type
        case_properties_by_case_type = defaultdict(set)

        _zip_update(case_properties_by_case_type, self._get_all_case_updates())

        _zip_update(case_properties_by_case_type, get_per_type_defaults(self.domain))

        if toggles.DATA_DICTIONARY.enabled(self.domain):
            _zip_update(case_properties_by_case_type,
                        get_data_dict_props_by_case_type(self.domain, self.exclude_deprecated_properties))

        for case_properties in case_properties_by_case_type.values():
            case_properties.update(self.defaults)

        if self.exclude_invalid_properties:
            from corehq.apps.app_manager.helpers.validators import validate_property
            for case_type, case_properties in case_properties_by_case_type.items():
                to_remove = []
                for prop in case_properties:
                    try:
                        validate_property(prop)
                    except ValueError:
                        to_remove.append(prop)
                for prop in to_remove:
                    case_properties_by_case_type[case_type].remove(prop)

        # this is where all the sweet, sweet child-parent property propagation happens
        return _propagate_and_normalize_case_properties(
            case_properties_by_case_type,
            parent_type_map=self.get_parent_type_map(case_types=None),
            include_parent_properties=self.include_parent_properties
        )
def get_properties_by_case_type ( self ) : from corehq . apps . data_dictionary . util import get_data_dict_props_by_case_type case_properties_by_case_type = defaultdict ( set ) _zip_update ( case_properties_by_case_type , self . _get_all_case_updates ( ) ) _zip_update ( case_properties_by_case_type , get_per_type_defaults ( self . domain ) ) if toggles . DATA_DICTIONARY . enabled ( self . domain ) : _zip_update ( case_properties_by_case_type , get_data_dict_props_by_case_type ( self . domain , self . exclude_deprecated_properties ) ) for case_properties in case_properties_by_case_type . values ( ) : case_properties . update ( self . defaults ) if self . exclude_invalid_properties : from corehq . apps . app_manager . helpers . validators import validate_property for case_type , case_properties in case_properties_by_case_type . items ( ) : to_remove = [ ] for prop in case_properties : try : validate_property ( prop ) except ValueError : to_remove . append ( prop ) for prop in to_remove : case_properties_by_case_type [ case_type ] . remove ( prop ) # this is where all the sweet, sweet child-parent property propagation happens return _propagate_and_normalize_case_properties ( case_properties_by_case_type , parent_type_map = self . get_parent_type_map ( case_types = None ) , include_parent_properties = self . include_parent_properties )