def _get_parsing_plan_for_multifile_children(
            self, obj_on_fs: PersistedObject, desired_type: Type[Any],
            logger: Logger) -> Dict[str, Any]:
        """
        Simply inspects the required type to find the names and types of its constructor arguments.
        Then relies on the inner ParserFinder to parse each of them.

        :param obj_on_fs:
        :param desired_type:
        :param logger:
        :return:
        """

        if is_collection(desired_type, strict=True):
            # if the destination type is 'strictly a collection' (not a subclass of a collection) we know that we can't
            # handle it here, the constructor is not pep484-typed
            raise TypeError(
                'Desired object type \'' + get_pretty_type_str(desired_type) +
                '\' is a collection, '
                'so it cannot be parsed with this default object parser')

        else:
            # First get the file children
            children_on_fs = obj_on_fs.get_multifile_children()

            # Try the type itself
            # try:
            return self.__get_parsing_plan_for_multifile_children(
                obj_on_fs, desired_type, children_on_fs, logger=logger)
Пример #2
0
    def _get_parsing_plan_for_multifile_children(self, obj_on_fs: PersistedObject, desired_type: Type[Any],
                                                 logger: Logger) -> Dict[str, Any]:
        """
        Simply simply inspects the required type to find the names and types of its constructor arguments.
        Then relies on the inner ParserFinder to parse each of them.

        :param obj_on_fs:
        :param desired_type:
        :param logger:
        :return:
        """

        if is_collection(desired_type, strict=True):
            raise TypeError('Desired object type \'' + get_pretty_type_str(desired_type)+ '\' is a collection, '
                            'so it cannot be parsed with this default object parser')

        # First get the file children
        children_on_fs = obj_on_fs.get_multifile_children()

        # -- (a) extract the schema from the class constructor
        constructor_args_types_and_opt = get_constructor_attributes_types(desired_type)

        # -- (b) plan to parse each attribute required by the constructor
        children_plan = dict()  # results will be put in this object

        # --use sorting in order to lead to reproducible results in case of multiple errors
        for attribute_name, att_desc in sorted(constructor_args_types_and_opt.items()):
            attribute_is_mandatory = att_desc[1]
            attribute_type = att_desc[0]

            # get the child
            if attribute_name in children_on_fs.keys():
                child_on_fs = children_on_fs[attribute_name]

                # find a parser
                parser_found = self.parser_finder.build_parser_for_fileobject_and_desiredtype(child_on_fs,
                                                                                              attribute_type,
                                                                                              logger=logger)
                # create a parsing plan
                children_plan[attribute_name] = parser_found.create_parsing_plan(attribute_type, child_on_fs,
                                                                                logger=logger)
            else:
                if attribute_is_mandatory:
                    raise MissingMandatoryAttributeFiles.create(obj_on_fs, desired_type, attribute_name)
                else:
                    # we don't care : optional attribute
                    # dont use warning since it does not show up nicely
                    #print('----- WARNING: Attribute ' + attribute_name + ' was not found on file system. However '
                    #      'it is not mandatory for the constructor of type ' + get_pretty_type_str(desired_type)
                    #      + ', so we\'ll build the object without it...')
                    logger.warning('----- Attribute ' + attribute_name + ' was not found on file system. However '
                                   'it is not mandatory for the constructor of type ' + get_pretty_type_str(desired_type)
                                   + ', so we\'ll build the object without it...')
                    pass
        return children_plan
Пример #3
0
    def _get_parsing_plan_for_multifile_children(
            self, obj_on_fs: PersistedObject, desired_type: Type[Any],
            logger: Logger) -> Dict[str, Any]:
        """
        Simply inspects the required type to find the base type expected for items of the collection,
        and relies on the ParserFinder to find the parsing plan

        :param obj_on_fs:
        :param desired_type:
        :param logger:
        :return:
        """
        # nb of file children
        n_children = len(obj_on_fs.get_multifile_children())

        # first extract base collection type
        subtypes, key_type = _extract_collection_base_type(desired_type)

        if isinstance(subtypes, tuple):
            # -- check the tuple length
            if n_children != len(subtypes):
                raise FolderAndFilesStructureError.create_for_multifile_tuple(
                    obj_on_fs, len(subtypes),
                    len(obj_on_fs.get_multifile_children()))
        else:
            # -- repeat the subtype n times
            subtypes = [subtypes] * n_children

        # -- for each child create a plan with the appropriate parser
        children_plan = OrderedDict()
        # use sorting for reproducible results in case of multiple errors
        for (child_name, child_fileobject), child_typ in zip(
                sorted(obj_on_fs.get_multifile_children().items()), subtypes):
            # -- use the parserfinder to find the plan
            t, child_parser = self.parser_finder.build_parser_for_fileobject_and_desiredtype(
                child_fileobject, child_typ, logger)
            children_plan[child_name] = child_parser.create_parsing_plan(
                t, child_fileobject, logger, _main_call=False)

        return children_plan