code: def __construct_metadata(
      self, exclude_features_sources: Optional[List[str]] = None
  ) -> FileMetadata:
      # self.logger.info("Constructing dataset metadata")
      columns = []
      for index, (column_name, column_type) in enumerate(
          zip(self.data.columns, self.data.dtypes)
      ):
          if column_name not in self.ignore_columns:
              if column_name in self.meaning_types_checked:
                  meaning_type = self.meaning_types_checked[column_name]
                  # Temporary workaround while backend doesn't support datetime
                  if meaning_type == FileColumnMeaningType.DATETIME:
                      meaning_type = FileColumnMeaningType.DATE
              else:
                  meaning_type = FileColumnMeaningType.FEATURE
              if meaning_type in {
                  FileColumnMeaningType.DATE,
                  FileColumnMeaningType.DATETIME,
                  # FileColumnMeaningType.IP_ADDRESS,
              }:
                  min_max_values = NumericInterval(
                      minValue=self.data[column_name]
                      .astype("Int64")
                      .min(),
                      maxValue=self.data[column_name]
                      .astype("Int64")
                      .max(),
                  )
              else:
                  min_max_values = None
              column_meta = FileColumnMetadata(
                  index=index,
                  name=column_name,
                  originalName=self.columns_renaming.get(column_name)
                  or column_name,
                  dataType=self.__get_data_type(
                      column_type, column_name
                  ),
                  meaningType=meaning_type,
                  minMaxValues=min_max_values,
              )
  
              columns.append(column_meta)
  
      return FileMetadata(
          name=self.dataset_name,
          description=self.description,
          columns=columns,
          searchKeys=self.search_keys,
          excludeFeaturesSources=exclude_features_sources,
          hierarchicalGroupKeys=self.hierarchical_group_keys,
          hierarchicalSubgroupKeys=self.hierarchical_subgroup_keys,
          taskType=self.task_type,
      )
  
imports: import csv
  import hashlib
  import logging
  import tempfile
  import time
  from ipaddress import IPv4Address, IPv6Address, _BaseAddress, ip_address
  from pathlib import Path
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import numpy
  import pandas
  from pandas.api.types import is_bool_dtype
  from pandas.api.types import is_datetime64_any_dtype
  from pandas.api.types import is_float_dtype, is_integer_dtype, is_numeric_dtype, is_string_dtype
  from pandas.core.dtypes.common import is_period_dtype
  from upgini.errors import ValidationError
  from upgini.http import ProgressStage, SearchProgress, get_rest_client
  from upgini.metadata import EVAL_SET_INDEX, SYSTEM_COLUMNS, SYSTEM_RECORD_ID, TARGET, DataType, FeaturesFilter, FileColumnMeaningType, FileColumnMetadata, FileMetadata, FileMetrics, ModelTaskType, NumericInterval, RuntimeParameters, SearchCustomization
  from upgini.normalizer.phone_normalizer import PhoneNormalizer
  from upgini.resource_bundle import bundle
  from upgini.sampler.random_under_sampler import RandomUnderSampler
  from upgini.search_task import SearchTask
  from upgini.utils import combine_search_keys
  from upgini.utils.email_utils import EmailSearchKeyConverter
  from upgini.utils.warning_counter import WarningCounter
label_desc: Use image node_id 38 for calling the Dataset obj's underlying member method code with example usage: obj.__construct_metadata(exclude_features_sources) and returns: FileMetadata