class_docstr: Vocabulary class that handles parsing and printing composite values such as
  compositional XPOS and universal morphological features (UFeats).
  
  Two key options are `keyed` and `sep`. `sep` specifies the separator used between
  different parts of the composite values, which is `|` for UFeats, for example.
  If `keyed` is `True`, then the incoming value is treated similarly to UFeats, where
  each part is a key/value pair separated by an equal sign (`=`). There are no inherit
  order to the keys, and we sort them alphabetically for serialization and deserialization.
  Whenever a part is absent, its internal value is a special `<EMPTY>` symbol that will
  be treated accordingly when generating the output. If `keyed` is `False`, then the parts
  are treated as positioned values, and `<EMPTY>` is used to pad parts at the end when the
  incoming value is not long enough.
code: def unit2parts(self, unit):
      # unpack parts of a unit
      if not self.sep:
          parts = [x for x in unit]
      else:
          parts = unit.split(self.sep)
      if self.keyed:
          if len(parts) == 1 and parts[0] == "_":
              return dict()
          parts = [x.split("=") for x in parts]
          if any(len(x) != 2 for x in parts):
              raise ValueError(
                  'Received "%s" for a dictionary which is supposed to be keyed, eg the entries should all be of the form key=value and separated by %s'
                  % (unit, self.sep)
              )
  
          # Just treat multi-valued properties values as one possible value
          parts = dict(parts)
      elif unit == "_":
          parts = []
      return parts
  
imports: from copy import copy
  from collections import Counter, OrderedDict
  from collections.abc import Iterable
  import os
  import pickle
label_desc: Use image node_id 2 for calling the CompositeVocab obj's underlying member method code with example usage: obj.unit2parts(unit) and returns: parts, dict