@staticmethod<EOL><INDENT>def TableDescriptionParser(table_description, depth=<NUM_LIT:0>):<DEDENT>
<EOL>if isinstance(table_description, (six.string_types, tuple)):<EOL><INDENT>parsed_col = DataTable.ColumnTypeParser(table_description)<EOL>parsed_col["<STR_LIT>"] = depth<EOL>parsed_col["<STR_LIT>"] = "<STR_LIT>"<EOL>return [parsed_col]<EOL><DEDENT>if not hasattr(table_description, "<STR_LIT>"):<EOL><INDENT>raise DataTableException("<STR_LIT>" %<EOL>type(table_description))<EOL><DEDENT>if not isinstance(table_description, dict):<EOL><INDENT>columns = []<EOL>for desc in table_description:<EOL><INDENT>parsed_col = DataTable.ColumnTypeParser(desc)<EOL>parsed_col["<STR_LIT>"] = depth<EOL>parsed_col["<STR_LIT>"] = "<STR_LIT>"<EOL>columns.append(parsed_col)<EOL><DEDENT>if not columns:<EOL><INDENT>raise DataTableException("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>return columns<EOL><DEDENT>if not table_description:<EOL><INDENT>raise DataTableException("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>if (len(table_description) != <NUM_LIT:1> or<EOL>(isinstance(next(six.iterkeys(table_description)), six.string_types) and<EOL>isinstance(next(six.itervalues(table_description)), tuple) and<EOL>len(next(six.itervalues(table_description))) < <NUM_LIT:4>)):<EOL><INDENT>columns = []<EOL>for key, value in sorted(table_description.items()):<EOL><INDENT>if isinstance(value, tuple):<EOL><INDENT>parsed_col = DataTable.ColumnTypeParser((key,) + value)<EOL><DEDENT>else:<EOL><INDENT>parsed_col = DataTable.ColumnTypeParser((key, value))<EOL><DEDENT>parsed_col["<STR_LIT>"] = depth<EOL>parsed_col["<STR_LIT>"] = "<STR_LIT>"<EOL>columns.append(parsed_col)<EOL><DEDENT>return columns<EOL><DEDENT>parsed_col = DataTable.ColumnTypeParser(sorted(table_description.keys())[<NUM_LIT:0>])<EOL>parsed_col["<STR_LIT>"] = depth<EOL>parsed_col["<STR_LIT>"] = "<STR_LIT>"<EOL>return ([parsed_col] + DataTable.TableDescriptionParser(<EOL>sorted(table_description.values())[<NUM_LIT:0>], depth=depth + <NUM_LIT:1>))<EOL>
Parses the table_description object for internal use.

        Parses the user-submitted table description into an internal format used
        by the Python DataTable class. Returns the flat list of parsed columns.

        Args:
          table_description: A description of the table which should comply
                             with one of the formats described below.
          depth: Optional. The depth of the first level in the current description.
                 Used by recursive calls to this function.

        Returns:
          List of columns, where each column represented by a dictionary with the
          keys: id, label, type, depth, container which means the following:
          - id: the id of the column
          - name: The name of the column
          - type: The datatype of the elements in this column. Allowed types are
                  described in ColumnTypeParser().
          - depth: The depth of this column in the table description
          - container: 'dict', 'iter' or 'scalar' for parsing the format easily.
          - custom_properties: The custom properties for this column.
          The returned description is flattened regardless of how it was given.

        Raises:
          DataTableException: Error in a column description or in the description
                              structure.

        Examples:
          A column description can be of the following forms:
           'id'
           ('id',)
           ('id', 'type')
           ('id', 'type', 'label')
           ('id', 'type', 'label', {'custom_prop1': 'custom_val1'})
           or as a dictionary:
           'id': 'type'
           'id': ('type',)
           'id': ('type', 'label')
           'id': ('type', 'label', {'custom_prop1': 'custom_val1'})
          If the type is not specified, we treat it as string.
          If no specific label is given, the label is simply the id.
          If no custom properties are given, we use an empty dictionary.

          input: [('a', 'date'), ('b', 'timeofday', 'b', {'foo': 'bar'})]
          output: [{'id': 'a', 'label': 'a', 'type': 'date',
                    'depth': 0, 'container': 'iter', 'custom_properties': {}},
                   {'id': 'b', 'label': 'b', 'type': 'timeofday',
                    'depth': 0, 'container': 'iter',
                    'custom_properties': {'foo': 'bar'}}]

          input: {'a': [('b', 'number'), ('c', 'string', 'column c')]}
          output: [{'id': 'a', 'label': 'a', 'type': 'string',
                    'depth': 0, 'container': 'dict', 'custom_properties': {}},
                   {'id': 'b', 'label': 'b', 'type': 'number',
                    'depth': 1, 'container': 'iter', 'custom_properties': {}},
                   {'id': 'c', 'label': 'column c', 'type': 'string',
                    'depth': 1, 'container': 'iter', 'custom_properties': {}}]

          input:  {('a', 'number', 'column a'): { 'b': 'number', 'c': 'string'}}
          output: [{'id': 'a', 'label': 'column a', 'type': 'number',
                    'depth': 0, 'container': 'dict', 'custom_properties': {}},
                   {'id': 'b', 'label': 'b', 'type': 'number',
                    'depth': 1, 'container': 'dict', 'custom_properties': {}},
                   {'id': 'c', 'label': 'c', 'type': 'string',
                    'depth': 1, 'container': 'dict', 'custom_properties': {}}]

          input: { ('w', 'string', 'word'): ('c', 'number', 'count') }
          output: [{'id': 'w', 'label': 'word', 'type': 'string',
                    'depth': 0, 'container': 'dict', 'custom_properties': {}},
                   {'id': 'c', 'label': 'count', 'type': 'number',
                    'depth': 1, 'container': 'scalar', 'custom_properties': {}}]

          input: {'a': ('number', 'column a'), 'b': ('string', 'column b')}
          output: [{'id': 'a', 'label': 'column a', 'type': 'number', 'depth': 0,
                   'container': 'dict', 'custom_properties': {}},
                   {'id': 'b', 'label': 'column b', 'type': 'string', 'depth': 0,
                   'container': 'dict', 'custom_properties': {}}

          NOTE: there might be ambiguity in the case of a dictionary representation
          of a single column. For example, the following description can be parsed
          in 2 different ways: {'a': ('b', 'c')} can be thought of a single column
          with the id 'a', of type 'b' and the label 'c', or as 2 columns: one named
          'a', and the other named 'b' of type 'c'. We choose the first option by
          default, and in case the second option is the right one, it is possible to
          make the key into a tuple (i.e. {('a',): ('b', 'c')}) or add more info
          into the tuple, thus making it look like this: {'a': ('b', 'c', 'b', {})}
          -- second 'b' is the label, and {} is the custom properties field.