class_docstr: A naming scheme using the dundered name syntax.
  
  TODO: Consolidate with StructuredLinkableSpecName / DunderedNameFormatter.
class_docstr_tok: ["A","naming","scheme","using","the","dundered","name","syntax",".","TODO",":","Consolidate","with","StructuredLinkableSpecName","\/","DunderedNameFormatter","."]
code: def spec_pattern(self, input_str: str) -> EntityLinkPattern:
      if not self.input_str_follows_scheme(input_str):
          raise ValueError(
              f"{repr(input_str)} does not follow this scheme."
          )
  
      input_str = input_str.lower()
  
      input_str_parts = input_str.split(DUNDER)
      fields_to_compare: Tuple[ParameterSetField, ...] = (
          ParameterSetField.ELEMENT_NAME,
          ParameterSetField.ENTITY_LINKS,
          ParameterSetField.DATE_PART,
      )
  
      time_grain = None
  
      # No dunder, e.g. "ds"
      if len(input_str_parts) == 1:
          return EntityLinkPattern(
              parameter_set=EntityLinkPatternParameterSet.from_parameters(
                  element_name=input_str_parts[0],
                  entity_links=(),
                  time_granularity=time_grain,
                  date_part=None,
                  fields_to_compare=tuple(fields_to_compare),
              )
          )
  
      # At this point, len(input_str_parts) >= 2
      for granularity in TimeGranularity:
          if input_str_parts[-1] == granularity.value:
              time_grain = granularity
  
      # Has a time grain specified.
      if time_grain is not None:
          fields_to_compare = fields_to_compare + (
              ParameterSetField.TIME_GRANULARITY,
          )
          #  e.g. "ds__month"
          if len(input_str_parts) == 2:
              return EntityLinkPattern(
                  parameter_set=EntityLinkPatternParameterSet.from_parameters(
                      element_name=input_str_parts[0],
                      entity_links=(),
                      time_granularity=time_grain,
                      date_part=None,
                      fields_to_compare=fields_to_compare,
                  )
              )
          # e.g. "messages__ds__month"
          return EntityLinkPattern(
              parameter_set=EntityLinkPatternParameterSet.from_parameters(
                  element_name=input_str_parts[-2],
                  entity_links=tuple(
                      EntityReference(entity_name)
                      for entity_name in input_str_parts[:-2]
                  ),
                  time_granularity=time_grain,
                  date_part=None,
                  fields_to_compare=fields_to_compare,
              )
          )
  
      # e.g. "messages__ds"
      return EntityLinkPattern(
          parameter_set=EntityLinkPatternParameterSet.from_parameters(
              element_name=input_str_parts[-1],
              entity_links=tuple(
                  EntityReference(entity_name)
                  for entity_name in input_str_parts[:-1]
              ),
              time_granularity=None,
              date_part=None,
              fields_to_compare=fields_to_compare,
          )
      )
  
imports: from __future__ import annotations
  import re
  from typing import Optional, Sequence, Tuple
  from dbt_semantic_interfaces.naming.keywords import DUNDER
  from dbt_semantic_interfaces.references import EntityReference
  from dbt_semantic_interfaces.type_enums import TimeGranularity
  from dbt_semantic_interfaces.type_enums.date_part import DatePart
  from typing_extensions import override
  from metricflow.naming.naming_scheme import QueryItemNamingScheme
  from metricflow.specs.patterns.entity_link_pattern import EntityLinkPattern, EntityLinkPatternParameterSet, ParameterSetField
  from metricflow.specs.specs import InstanceSpec, InstanceSpecSet, InstanceSpecSetTransform
label_desc: Use image node_id 3 for calling the DunderNamingScheme obj's underlying member method code with example usage: obj.spec_pattern(input_str) and returns: EntityLinkPattern, EntityLinkPattern, EntityLinkPattern, EntityLinkPattern