class_docstr: Helps to populate things derived from BaseTable from maps, tuples, etc.
  
  A table of lifecycle callbacks may be provided to add logic beyond what is possible
  based on otData info for the target class. See BuildCallbacks.
class_docstr_tok: ["Helps","to","populate","things","derived","from","BaseTable","from","maps",",","tuples",",","etc",".","A","table","of","lifecycle","callbacks","may","be","provided","to","add","logic","beyond","what","is","possible","based","on","otData","info","for","the","target","class",".","See","BuildCallbacks","."]
code: def build(self, cls, source):
      assert issubclass(cls, BaseTable)
  
      if isinstance(source, cls):
          return source
  
      callbackKey = (cls,)
      fmt = None
      if issubclass(cls, FormatSwitchingBaseTable):
          fmt, source = _split_format(cls, source)
          callbackKey = (cls, fmt)
  
      dest = self._callbackTable.get(
          (BuildCallback.CREATE_DEFAULT,) + callbackKey, lambda: cls()
      )()
      assert isinstance(dest, cls)
  
      convByName = _assignable(cls.convertersByName)
      skippedFields = set()
  
      # For format switchers we need to resolve converters based on format
      if issubclass(cls, FormatSwitchingBaseTable):
          dest.Format = fmt
          convByName = _assignable(convByName[dest.Format])
          skippedFields.add("Format")
  
      # Convert sequence => mapping so before thunk only has to handle one format
      if _isNonStrSequence(source):
          # Sequence (typically list or tuple) assumed to match fields in declaration order
          assert len(source) <= len(
              convByName
          ), f"Sequence of {len(source)} too long for {cls}; expected <= {len(convByName)} values"
          source = dict(zip(convByName.keys(), source))
  
      dest, source = self._callbackTable.get(
          (BuildCallback.BEFORE_BUILD,) + callbackKey,
          lambda d, s: (d, s),
      )(dest, source)
  
      if isinstance(source, collections.abc.Mapping):
          for field, value in source.items():
              if field in skippedFields:
                  continue
              converter = convByName.get(field, None)
              if not converter:
                  raise ValueError(
                      f"Unrecognized field {field} for {cls}; expected one of {sorted(convByName.keys())}"
                  )
              self._convert(dest, field, converter, value)
      else:
          # let's try as a 1-tuple
          dest = self.build(cls, (source,))
  
      for field, conv in convByName.items():
          if not hasattr(dest, field) and isinstance(
              conv, OptionalValue
          ):
              setattr(dest, field, conv.DEFAULT)
  
      dest = self._callbackTable.get(
          (BuildCallback.AFTER_BUILD,) + callbackKey, lambda d: d
      )(dest)
  
      return dest
  
file_path: catboost/contrib/python/fonttools/fontTools/colorLib/table_builder.py
imports: import collections
  import enum
  from fontTools.ttLib.tables.otBase import BaseTable, FormatSwitchingBaseTable, UInt8FormatSwitchingBaseTable
  from fontTools.ttLib.tables.otConverters import ComputedInt, SimpleValue, Struct, Short, UInt8, UShort, IntValue, FloatValue, OptionalValue
  from fontTools.misc.roundTools import otRound
label_desc: Use image node_id 3 for calling the TableBuilder obj's underlying member method code with example usage: obj.build(cls, source) and returns: dest, source