@staticmethod
def _normalize_inputs(framework, data, project) ->tuple:
    """
        Normalize constructor inputs

        A :class:`ProjectFramework` is constructed against a particular framework
        and data. For convenience, these can be specified by passing in a Project
        containing the framework and data. This function takes in all of the inputs
        provided to the constructor (whether making a blank instance or reading a
        spreadsheet) and returns the framework and data. The order of precedence is

        - If separate framework or data is provided, it will be used
        - Otherwise, they will be drawn from the project

        So for example, a project and data could be provided, in which case the framework
        would come from the project and the data would come from the explicit argument
        (even if the project also contained data).

        :param framework: Optionally a :class:`ProjectFramework` instance
        :param data: Optionally a :class:`ProjectData` instance
        :param project: Optionally a :class:`Project` instance
        :return: Tuple containing ``(framework,data)``

        """
    if (framework is None and project is None or data is None and project is
        None):
        errormsg = (
            'To read in a ProgramSet, please supply one of the following sets of inputs: (a) a Framework and a ProjectData, (b) a Project.'
            )
        raise Exception(errormsg)
    if framework is None:
        if project.framework is None:
            errormsg = (
                'A Framework was not provided, and the Project has not been initialized with a Framework'
                )
            raise Exception(errormsg)
        else:
            framework = project.framework
    if data is None:
        if project.data is None:
            errormsg = 'Project data has not been loaded yet'
            raise Exception(errormsg)
        else:
            data = project.data
    return framework, data
