#
# Autogenerated by Thrift Compiler (0.13.0)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
#  options string: py
#

from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
from thrift.protocol.TProtocol import TProtocolException
from thrift.TRecursive import fix_spec

import sys

from thrift.transport import TTransport
all_structs = []


class Operation(object):
    MIN = 0
    MAX = 1
    FIRST = 2
    LAST = 3
    UNIQUE_COUNT = 4
    APPROX_UNIQUE_COUNT = 5
    COUNT = 6
    SUM = 7
    AVERAGE = 8
    VARIANCE = 9
    SKEW = 10
    KURTOSIS = 11
    APPROX_PERCENTILE = 12
    LAST_K = 13
    FIRST_K = 14
    TOP_K = 15
    BOTTOM_K = 16
    HISTOGRAM = 17

    _VALUES_TO_NAMES = {
        0: "MIN",
        1: "MAX",
        2: "FIRST",
        3: "LAST",
        4: "UNIQUE_COUNT",
        5: "APPROX_UNIQUE_COUNT",
        6: "COUNT",
        7: "SUM",
        8: "AVERAGE",
        9: "VARIANCE",
        10: "SKEW",
        11: "KURTOSIS",
        12: "APPROX_PERCENTILE",
        13: "LAST_K",
        14: "FIRST_K",
        15: "TOP_K",
        16: "BOTTOM_K",
        17: "HISTOGRAM",
    }

    _NAMES_TO_VALUES = {
        "MIN": 0,
        "MAX": 1,
        "FIRST": 2,
        "LAST": 3,
        "UNIQUE_COUNT": 4,
        "APPROX_UNIQUE_COUNT": 5,
        "COUNT": 6,
        "SUM": 7,
        "AVERAGE": 8,
        "VARIANCE": 9,
        "SKEW": 10,
        "KURTOSIS": 11,
        "APPROX_PERCENTILE": 12,
        "LAST_K": 13,
        "FIRST_K": 14,
        "TOP_K": 15,
        "BOTTOM_K": 16,
        "HISTOGRAM": 17,
    }


class TimeUnit(object):
    HOURS = 0
    DAYS = 1

    _VALUES_TO_NAMES = {
        0: "HOURS",
        1: "DAYS",
    }

    _NAMES_TO_VALUES = {
        "HOURS": 0,
        "DAYS": 1,
    }


class Accuracy(object):
    TEMPORAL = 0
    SNAPSHOT = 1

    _VALUES_TO_NAMES = {
        0: "TEMPORAL",
        1: "SNAPSHOT",
    }

    _NAMES_TO_VALUES = {
        "TEMPORAL": 0,
        "SNAPSHOT": 1,
    }


class DataKind(object):
    BOOLEAN = 0
    BYTE = 1
    SHORT = 2
    INT = 3
    LONG = 4
    FLOAT = 5
    DOUBLE = 6
    STRING = 7
    BINARY = 8
    DATE = 9
    TIMESTAMP = 10
    MAP = 11
    LIST = 12
    STRUCT = 13

    _VALUES_TO_NAMES = {
        0: "BOOLEAN",
        1: "BYTE",
        2: "SHORT",
        3: "INT",
        4: "LONG",
        5: "FLOAT",
        6: "DOUBLE",
        7: "STRING",
        8: "BINARY",
        9: "DATE",
        10: "TIMESTAMP",
        11: "MAP",
        12: "LIST",
        13: "STRUCT",
    }

    _NAMES_TO_VALUES = {
        "BOOLEAN": 0,
        "BYTE": 1,
        "SHORT": 2,
        "INT": 3,
        "LONG": 4,
        "FLOAT": 5,
        "DOUBLE": 6,
        "STRING": 7,
        "BINARY": 8,
        "DATE": 9,
        "TIMESTAMP": 10,
        "MAP": 11,
        "LIST": 12,
        "STRUCT": 13,
    }


class Query(object):
    """
    Attributes:
     - selects
     - wheres
     - startPartition
     - endPartition
     - timeColumn
     - setups
     - mutationTimeColumn
     - reversalColumn

    """


    def __init__(self, selects=None, wheres=None, startPartition=None, endPartition=None, timeColumn=None, setups=[
    ], mutationTimeColumn=None, reversalColumn=None,):
        self.selects = selects
        self.wheres = wheres
        self.startPartition = startPartition
        self.endPartition = endPartition
        self.timeColumn = timeColumn
        if setups is self.thrift_spec[6][4]:
            setups = [
            ]
        self.setups = setups
        self.mutationTimeColumn = mutationTimeColumn
        self.reversalColumn = reversalColumn

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.MAP:
                    self.selects = {}
                    (_ktype1, _vtype2, _size0) = iprot.readMapBegin()
                    for _i4 in range(_size0):
                        _key5 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val6 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.selects[_key5] = _val6
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.LIST:
                    self.wheres = []
                    (_etype10, _size7) = iprot.readListBegin()
                    for _i11 in range(_size7):
                        _elem12 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.wheres.append(_elem12)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.startPartition = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRING:
                    self.endPartition = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.STRING:
                    self.timeColumn = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.LIST:
                    self.setups = []
                    (_etype16, _size13) = iprot.readListBegin()
                    for _i17 in range(_size13):
                        _elem18 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.setups.append(_elem18)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 7:
                if ftype == TType.STRING:
                    self.mutationTimeColumn = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 8:
                if ftype == TType.STRING:
                    self.reversalColumn = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('Query')
        if self.selects is not None:
            oprot.writeFieldBegin('selects', TType.MAP, 1)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.selects))
            for kiter19, viter20 in self.selects.items():
                oprot.writeString(kiter19.encode('utf-8') if sys.version_info[0] == 2 else kiter19)
                oprot.writeString(viter20.encode('utf-8') if sys.version_info[0] == 2 else viter20)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.wheres is not None:
            oprot.writeFieldBegin('wheres', TType.LIST, 2)
            oprot.writeListBegin(TType.STRING, len(self.wheres))
            for iter21 in self.wheres:
                oprot.writeString(iter21.encode('utf-8') if sys.version_info[0] == 2 else iter21)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.startPartition is not None:
            oprot.writeFieldBegin('startPartition', TType.STRING, 3)
            oprot.writeString(self.startPartition.encode('utf-8') if sys.version_info[0] == 2 else self.startPartition)
            oprot.writeFieldEnd()
        if self.endPartition is not None:
            oprot.writeFieldBegin('endPartition', TType.STRING, 4)
            oprot.writeString(self.endPartition.encode('utf-8') if sys.version_info[0] == 2 else self.endPartition)
            oprot.writeFieldEnd()
        if self.timeColumn is not None:
            oprot.writeFieldBegin('timeColumn', TType.STRING, 5)
            oprot.writeString(self.timeColumn.encode('utf-8') if sys.version_info[0] == 2 else self.timeColumn)
            oprot.writeFieldEnd()
        if self.setups is not None:
            oprot.writeFieldBegin('setups', TType.LIST, 6)
            oprot.writeListBegin(TType.STRING, len(self.setups))
            for iter22 in self.setups:
                oprot.writeString(iter22.encode('utf-8') if sys.version_info[0] == 2 else iter22)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.mutationTimeColumn is not None:
            oprot.writeFieldBegin('mutationTimeColumn', TType.STRING, 7)
            oprot.writeString(self.mutationTimeColumn.encode('utf-8') if sys.version_info[0] == 2 else self.mutationTimeColumn)
            oprot.writeFieldEnd()
        if self.reversalColumn is not None:
            oprot.writeFieldBegin('reversalColumn', TType.STRING, 8)
            oprot.writeString(self.reversalColumn.encode('utf-8') if sys.version_info[0] == 2 else self.reversalColumn)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class StagingQuery(object):
    """
    Staging Query encapsulates arbitrary spark computation. One key feature is that the computation follows a
    "fill-what's-missing" pattern. Basically instead of explicitly specifying dates you specify two macros.
    `{{ start_date }}` and `{{end_date}}`. Chronon will pass in earliest-missing-partition for `start_date` and
    execution-date / today for `end_date`. So the query will compute multiple partitions at once.

    :param metaData: Contains name, team, output_namespace, execution parameters etc. Things that don't change the
                     semantics of the computation itself.
    :param query: The spark sql query with date templates.
    :param startPartition: This is where start_date will be applied from. We expect the query to also produce output
                           hive tables partitioned data starting from startPartition.
    :param setups: Spark SQL setup statements. Used typically to register UDFs.

    Attributes:
     - metaData
     - query
     - startPartition
     - setups

    """


    def __init__(self, metaData=None, query=None, startPartition=None, setups=None,):
        self.metaData = metaData
        self.query = query
        self.startPartition = startPartition
        self.setups = setups

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.metaData = MetaData()
                    self.metaData.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRING:
                    self.query = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.startPartition = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.LIST:
                    self.setups = []
                    (_etype26, _size23) = iprot.readListBegin()
                    for _i27 in range(_size23):
                        _elem28 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.setups.append(_elem28)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('StagingQuery')
        if self.metaData is not None:
            oprot.writeFieldBegin('metaData', TType.STRUCT, 1)
            self.metaData.write(oprot)
            oprot.writeFieldEnd()
        if self.query is not None:
            oprot.writeFieldBegin('query', TType.STRING, 2)
            oprot.writeString(self.query.encode('utf-8') if sys.version_info[0] == 2 else self.query)
            oprot.writeFieldEnd()
        if self.startPartition is not None:
            oprot.writeFieldBegin('startPartition', TType.STRING, 3)
            oprot.writeString(self.startPartition.encode('utf-8') if sys.version_info[0] == 2 else self.startPartition)
            oprot.writeFieldEnd()
        if self.setups is not None:
            oprot.writeFieldBegin('setups', TType.LIST, 4)
            oprot.writeListBegin(TType.STRING, len(self.setups))
            for iter29 in self.setups:
                oprot.writeString(iter29.encode('utf-8') if sys.version_info[0] == 2 else iter29)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class EventSource(object):
    """
    Event source captures data that is essentially immutable - like user clicks, impressions etc.
    It has two parts, an offline table and an online topic. The term `fact` table from star-schema also maps to this
    concepts. But lacks a notion of topic.

    :param table: Table currently needs to be a 'ds' (date string - yyyy-MM-dd) partitioned hive table.
                  Table names can contain subpartition specs, example db.table/system=mobile/currency=USD
    :param topic: Topic is a kafka table. The table contains all the events historically came through this topic.
    :param query: The logic used to scan both the table and the topic. Contains row level transformations and filtering
                  expressed as Spark SQL statements.
    :param isCumulative: If each new hive partition contains not just the current day's events but the entire set of
                         events since the begininng. The key property is that the events are not mutated across partitions.

    Attributes:
     - table
     - topic
     - query
     - isCumulative

    """


    def __init__(self, table=None, topic=None, query=None, isCumulative=None,):
        self.table = table
        self.topic = topic
        self.query = query
        self.isCumulative = isCumulative

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.table = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRING:
                    self.topic = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRUCT:
                    self.query = Query()
                    self.query.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.BOOL:
                    self.isCumulative = iprot.readBool()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('EventSource')
        if self.table is not None:
            oprot.writeFieldBegin('table', TType.STRING, 1)
            oprot.writeString(self.table.encode('utf-8') if sys.version_info[0] == 2 else self.table)
            oprot.writeFieldEnd()
        if self.topic is not None:
            oprot.writeFieldBegin('topic', TType.STRING, 2)
            oprot.writeString(self.topic.encode('utf-8') if sys.version_info[0] == 2 else self.topic)
            oprot.writeFieldEnd()
        if self.query is not None:
            oprot.writeFieldBegin('query', TType.STRUCT, 3)
            self.query.write(oprot)
            oprot.writeFieldEnd()
        if self.isCumulative is not None:
            oprot.writeFieldBegin('isCumulative', TType.BOOL, 4)
            oprot.writeBool(self.isCumulative)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class EntitySource(object):
    """
    Entity Sources represent data that gets mutated over-time - at row-level. This is a group of three data elements.
    snapshotTable, mutationTable and mutationTopic. mutationTable and mutationTopic are only necessary if we are trying
    to create realtime or point-in-time aggregations over these sources. Entity sources usually map 1:1 with a database
    tables in your OLTP store that typically serves live application traffic. When mutation data is absent they map 1:1
    to `dim` tables in star schema.

    :param snapshotTable: Table currently needs to be a 'ds' (date string - yyyy-MM-dd) partitioned hive table.
    :param mutationTable: Topic is a kafka table. The table contains all the events historically came through this topic.
    :param mutationTopic: The logic used to scan both the table and the topic. Contains row level transformations and filtering
                  expressed as Spark SQL statements.
    :param isCumulative: If each new hive partition contains not just the current day's events but the entire set of
                         events since the begininng. The key property is that the events are not mutated across partitions.

    Attributes:
     - snapshotTable
     - mutationTable
     - mutationTopic
     - query

    """


    def __init__(self, snapshotTable=None, mutationTable=None, mutationTopic=None, query=None,):
        self.snapshotTable = snapshotTable
        self.mutationTable = mutationTable
        self.mutationTopic = mutationTopic
        self.query = query

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.snapshotTable = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRING:
                    self.mutationTable = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.mutationTopic = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRUCT:
                    self.query = Query()
                    self.query.read(iprot)
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('EntitySource')
        if self.snapshotTable is not None:
            oprot.writeFieldBegin('snapshotTable', TType.STRING, 1)
            oprot.writeString(self.snapshotTable.encode('utf-8') if sys.version_info[0] == 2 else self.snapshotTable)
            oprot.writeFieldEnd()
        if self.mutationTable is not None:
            oprot.writeFieldBegin('mutationTable', TType.STRING, 2)
            oprot.writeString(self.mutationTable.encode('utf-8') if sys.version_info[0] == 2 else self.mutationTable)
            oprot.writeFieldEnd()
        if self.mutationTopic is not None:
            oprot.writeFieldBegin('mutationTopic', TType.STRING, 3)
            oprot.writeString(self.mutationTopic.encode('utf-8') if sys.version_info[0] == 2 else self.mutationTopic)
            oprot.writeFieldEnd()
        if self.query is not None:
            oprot.writeFieldBegin('query', TType.STRUCT, 4)
            self.query.write(oprot)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class ExternalSource(object):
    """
    Attributes:
     - metadata
     - keySchema
     - valueSchema

    """


    def __init__(self, metadata=None, keySchema=None, valueSchema=None,):
        self.metadata = metadata
        self.keySchema = keySchema
        self.valueSchema = valueSchema

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.metadata = MetaData()
                    self.metadata.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRUCT:
                    self.keySchema = TDataType()
                    self.keySchema.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRUCT:
                    self.valueSchema = TDataType()
                    self.valueSchema.read(iprot)
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('ExternalSource')
        if self.metadata is not None:
            oprot.writeFieldBegin('metadata', TType.STRUCT, 1)
            self.metadata.write(oprot)
            oprot.writeFieldEnd()
        if self.keySchema is not None:
            oprot.writeFieldBegin('keySchema', TType.STRUCT, 2)
            self.keySchema.write(oprot)
            oprot.writeFieldEnd()
        if self.valueSchema is not None:
            oprot.writeFieldBegin('valueSchema', TType.STRUCT, 3)
            self.valueSchema.write(oprot)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class Source(object):
    """
    Attributes:
     - events
     - entities

    """


    def __init__(self, events=None, entities=None,):
        self.events = events
        self.entities = entities

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.events = EventSource()
                    self.events.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRUCT:
                    self.entities = EntitySource()
                    self.entities.read(iprot)
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('Source')
        if self.events is not None:
            oprot.writeFieldBegin('events', TType.STRUCT, 1)
            self.events.write(oprot)
            oprot.writeFieldEnd()
        if self.entities is not None:
            oprot.writeFieldBegin('entities', TType.STRUCT, 2)
            self.entities.write(oprot)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class Window(object):
    """
    Attributes:
     - length
     - timeUnit

    """


    def __init__(self, length=None, timeUnit=None,):
        self.length = length
        self.timeUnit = timeUnit

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.I32:
                    self.length = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.I32:
                    self.timeUnit = iprot.readI32()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('Window')
        if self.length is not None:
            oprot.writeFieldBegin('length', TType.I32, 1)
            oprot.writeI32(self.length)
            oprot.writeFieldEnd()
        if self.timeUnit is not None:
            oprot.writeFieldBegin('timeUnit', TType.I32, 2)
            oprot.writeI32(self.timeUnit)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class Aggregation(object):
    """
    Chronon provides a powerful aggregations primitive - that takes the familiar aggregation operation, via groupBy in
    SQL and extends it with three things - windowing, bucketing and auto-explode.

    :param inputColumn:
        The column as specified in source.query.selects - on which we need to aggregate with.

    :param operation:
        The type of aggregation that needs to be performed on the inputColumn.

    :param argMap:
        Extra arguments that needs to be passed to some of the operations like LAST_K, APPROX_PERCENTILE.

    :param windows:
        For TEMPORAL case windows are sawtooth. Meaning head slides ahead continuously in time, whereas,
        the tail only hops ahead, at discrete points in time. Hop is determined by the window size automatically.
        The maximum hop size is 1/12 of window size. You can specify multiple such windows at once.

            Window > 12 days  -> Hop Size = 1 day

            Window > 12 hours -> Hop Size = 1 hr

            Window > 1hr      -> Hop Size = 5 minutes

    :param buckets:
        This is an additional layer of aggregation. You can key a group_by by user, and bucket a "item_view"
        count by "item_category". This will produce one row per user, with column containing map of "item_category"
        to "view_count". You can specify multiple such buckets at once.

    Attributes:
     - inputColumn
     - operation
     - argMap
     - windows
     - buckets: This is an additional layer of aggregation. You can key a group_by by user, and bucket a “item_view” count by “item_category”. This will produce one row per user, with column containing map of “item_category” to “view_count”. You can specify multiple such buckets at once


    """


    def __init__(self, inputColumn=None, operation=None, argMap=None, windows=None, buckets=None,):
        self.inputColumn = inputColumn
        self.operation = operation
        self.argMap = argMap
        self.windows = windows
        self.buckets = buckets

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.inputColumn = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.I32:
                    self.operation = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.MAP:
                    self.argMap = {}
                    (_ktype31, _vtype32, _size30) = iprot.readMapBegin()
                    for _i34 in range(_size30):
                        _key35 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val36 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.argMap[_key35] = _val36
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.LIST:
                    self.windows = []
                    (_etype40, _size37) = iprot.readListBegin()
                    for _i41 in range(_size37):
                        _elem42 = Window()
                        _elem42.read(iprot)
                        self.windows.append(_elem42)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.LIST:
                    self.buckets = []
                    (_etype46, _size43) = iprot.readListBegin()
                    for _i47 in range(_size43):
                        _elem48 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.buckets.append(_elem48)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('Aggregation')
        if self.inputColumn is not None:
            oprot.writeFieldBegin('inputColumn', TType.STRING, 1)
            oprot.writeString(self.inputColumn.encode('utf-8') if sys.version_info[0] == 2 else self.inputColumn)
            oprot.writeFieldEnd()
        if self.operation is not None:
            oprot.writeFieldBegin('operation', TType.I32, 2)
            oprot.writeI32(self.operation)
            oprot.writeFieldEnd()
        if self.argMap is not None:
            oprot.writeFieldBegin('argMap', TType.MAP, 3)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.argMap))
            for kiter49, viter50 in self.argMap.items():
                oprot.writeString(kiter49.encode('utf-8') if sys.version_info[0] == 2 else kiter49)
                oprot.writeString(viter50.encode('utf-8') if sys.version_info[0] == 2 else viter50)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.windows is not None:
            oprot.writeFieldBegin('windows', TType.LIST, 4)
            oprot.writeListBegin(TType.STRUCT, len(self.windows))
            for iter51 in self.windows:
                iter51.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.buckets is not None:
            oprot.writeFieldBegin('buckets', TType.LIST, 5)
            oprot.writeListBegin(TType.STRING, len(self.buckets))
            for iter52 in self.buckets:
                oprot.writeString(iter52.encode('utf-8') if sys.version_info[0] == 2 else iter52)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class AggregationPart(object):
    """
    Attributes:
     - inputColumn
     - operation
     - argMap
     - window
     - bucket

    """


    def __init__(self, inputColumn=None, operation=None, argMap=None, window=None, bucket=None,):
        self.inputColumn = inputColumn
        self.operation = operation
        self.argMap = argMap
        self.window = window
        self.bucket = bucket

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.inputColumn = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.I32:
                    self.operation = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.MAP:
                    self.argMap = {}
                    (_ktype54, _vtype55, _size53) = iprot.readMapBegin()
                    for _i57 in range(_size53):
                        _key58 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val59 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.argMap[_key58] = _val59
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRUCT:
                    self.window = Window()
                    self.window.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.STRING:
                    self.bucket = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('AggregationPart')
        if self.inputColumn is not None:
            oprot.writeFieldBegin('inputColumn', TType.STRING, 1)
            oprot.writeString(self.inputColumn.encode('utf-8') if sys.version_info[0] == 2 else self.inputColumn)
            oprot.writeFieldEnd()
        if self.operation is not None:
            oprot.writeFieldBegin('operation', TType.I32, 2)
            oprot.writeI32(self.operation)
            oprot.writeFieldEnd()
        if self.argMap is not None:
            oprot.writeFieldBegin('argMap', TType.MAP, 3)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.argMap))
            for kiter60, viter61 in self.argMap.items():
                oprot.writeString(kiter60.encode('utf-8') if sys.version_info[0] == 2 else kiter60)
                oprot.writeString(viter61.encode('utf-8') if sys.version_info[0] == 2 else viter61)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.window is not None:
            oprot.writeFieldBegin('window', TType.STRUCT, 4)
            self.window.write(oprot)
            oprot.writeFieldEnd()
        if self.bucket is not None:
            oprot.writeFieldBegin('bucket', TType.STRING, 5)
            oprot.writeString(self.bucket.encode('utf-8') if sys.version_info[0] == 2 else self.bucket)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class MetaData(object):
    """
    Attributes:
     - name
     - online
     - production
     - customJson
     - dependencies
     - tableProperties
     - outputNamespace
     - team
     - modeToEnvMap
     - consistencyCheck
     - samplePercent
     - offlineSchedule

    """


    def __init__(self, name=None, online=None, production=None, customJson=None, dependencies=None, tableProperties=None, outputNamespace=None, team=None, modeToEnvMap=None, consistencyCheck=None, samplePercent=None, offlineSchedule=None,):
        self.name = name
        self.online = online
        self.production = production
        self.customJson = customJson
        self.dependencies = dependencies
        self.tableProperties = tableProperties
        self.outputNamespace = outputNamespace
        self.team = team
        self.modeToEnvMap = modeToEnvMap
        self.consistencyCheck = consistencyCheck
        self.samplePercent = samplePercent
        self.offlineSchedule = offlineSchedule

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.name = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.BOOL:
                    self.online = iprot.readBool()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.BOOL:
                    self.production = iprot.readBool()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRING:
                    self.customJson = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.LIST:
                    self.dependencies = []
                    (_etype65, _size62) = iprot.readListBegin()
                    for _i66 in range(_size62):
                        _elem67 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.dependencies.append(_elem67)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.MAP:
                    self.tableProperties = {}
                    (_ktype69, _vtype70, _size68) = iprot.readMapBegin()
                    for _i72 in range(_size68):
                        _key73 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val74 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.tableProperties[_key73] = _val74
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 7:
                if ftype == TType.STRING:
                    self.outputNamespace = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 8:
                if ftype == TType.STRING:
                    self.team = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 9:
                if ftype == TType.MAP:
                    self.modeToEnvMap = {}
                    (_ktype76, _vtype77, _size75) = iprot.readMapBegin()
                    for _i79 in range(_size75):
                        _key80 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val81 = {}
                        (_ktype83, _vtype84, _size82) = iprot.readMapBegin()
                        for _i86 in range(_size82):
                            _key87 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                            _val88 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                            _val81[_key87] = _val88
                        iprot.readMapEnd()
                        self.modeToEnvMap[_key80] = _val81
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 10:
                if ftype == TType.BOOL:
                    self.consistencyCheck = iprot.readBool()
                else:
                    iprot.skip(ftype)
            elif fid == 11:
                if ftype == TType.DOUBLE:
                    self.samplePercent = iprot.readDouble()
                else:
                    iprot.skip(ftype)
            elif fid == 12:
                if ftype == TType.STRING:
                    self.offlineSchedule = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('MetaData')
        if self.name is not None:
            oprot.writeFieldBegin('name', TType.STRING, 1)
            oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name)
            oprot.writeFieldEnd()
        if self.online is not None:
            oprot.writeFieldBegin('online', TType.BOOL, 2)
            oprot.writeBool(self.online)
            oprot.writeFieldEnd()
        if self.production is not None:
            oprot.writeFieldBegin('production', TType.BOOL, 3)
            oprot.writeBool(self.production)
            oprot.writeFieldEnd()
        if self.customJson is not None:
            oprot.writeFieldBegin('customJson', TType.STRING, 4)
            oprot.writeString(self.customJson.encode('utf-8') if sys.version_info[0] == 2 else self.customJson)
            oprot.writeFieldEnd()
        if self.dependencies is not None:
            oprot.writeFieldBegin('dependencies', TType.LIST, 5)
            oprot.writeListBegin(TType.STRING, len(self.dependencies))
            for iter89 in self.dependencies:
                oprot.writeString(iter89.encode('utf-8') if sys.version_info[0] == 2 else iter89)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.tableProperties is not None:
            oprot.writeFieldBegin('tableProperties', TType.MAP, 6)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.tableProperties))
            for kiter90, viter91 in self.tableProperties.items():
                oprot.writeString(kiter90.encode('utf-8') if sys.version_info[0] == 2 else kiter90)
                oprot.writeString(viter91.encode('utf-8') if sys.version_info[0] == 2 else viter91)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.outputNamespace is not None:
            oprot.writeFieldBegin('outputNamespace', TType.STRING, 7)
            oprot.writeString(self.outputNamespace.encode('utf-8') if sys.version_info[0] == 2 else self.outputNamespace)
            oprot.writeFieldEnd()
        if self.team is not None:
            oprot.writeFieldBegin('team', TType.STRING, 8)
            oprot.writeString(self.team.encode('utf-8') if sys.version_info[0] == 2 else self.team)
            oprot.writeFieldEnd()
        if self.modeToEnvMap is not None:
            oprot.writeFieldBegin('modeToEnvMap', TType.MAP, 9)
            oprot.writeMapBegin(TType.STRING, TType.MAP, len(self.modeToEnvMap))
            for kiter92, viter93 in self.modeToEnvMap.items():
                oprot.writeString(kiter92.encode('utf-8') if sys.version_info[0] == 2 else kiter92)
                oprot.writeMapBegin(TType.STRING, TType.STRING, len(viter93))
                for kiter94, viter95 in viter93.items():
                    oprot.writeString(kiter94.encode('utf-8') if sys.version_info[0] == 2 else kiter94)
                    oprot.writeString(viter95.encode('utf-8') if sys.version_info[0] == 2 else viter95)
                oprot.writeMapEnd()
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.consistencyCheck is not None:
            oprot.writeFieldBegin('consistencyCheck', TType.BOOL, 10)
            oprot.writeBool(self.consistencyCheck)
            oprot.writeFieldEnd()
        if self.samplePercent is not None:
            oprot.writeFieldBegin('samplePercent', TType.DOUBLE, 11)
            oprot.writeDouble(self.samplePercent)
            oprot.writeFieldEnd()
        if self.offlineSchedule is not None:
            oprot.writeFieldBegin('offlineSchedule', TType.STRING, 12)
            oprot.writeString(self.offlineSchedule.encode('utf-8') if sys.version_info[0] == 2 else self.offlineSchedule)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class GroupBy(object):
    """
    Attributes:
     - metaData
     - sources
     - keyColumns
     - aggregations
     - accuracy
     - backfillStartDate

    """


    def __init__(self, metaData=None, sources=None, keyColumns=None, aggregations=None, accuracy=None, backfillStartDate=None,):
        self.metaData = metaData
        self.sources = sources
        self.keyColumns = keyColumns
        self.aggregations = aggregations
        self.accuracy = accuracy
        self.backfillStartDate = backfillStartDate

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.metaData = MetaData()
                    self.metaData.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.LIST:
                    self.sources = []
                    (_etype99, _size96) = iprot.readListBegin()
                    for _i100 in range(_size96):
                        _elem101 = Source()
                        _elem101.read(iprot)
                        self.sources.append(_elem101)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.LIST:
                    self.keyColumns = []
                    (_etype105, _size102) = iprot.readListBegin()
                    for _i106 in range(_size102):
                        _elem107 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyColumns.append(_elem107)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.LIST:
                    self.aggregations = []
                    (_etype111, _size108) = iprot.readListBegin()
                    for _i112 in range(_size108):
                        _elem113 = Aggregation()
                        _elem113.read(iprot)
                        self.aggregations.append(_elem113)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.I32:
                    self.accuracy = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.STRING:
                    self.backfillStartDate = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('GroupBy')
        if self.metaData is not None:
            oprot.writeFieldBegin('metaData', TType.STRUCT, 1)
            self.metaData.write(oprot)
            oprot.writeFieldEnd()
        if self.sources is not None:
            oprot.writeFieldBegin('sources', TType.LIST, 2)
            oprot.writeListBegin(TType.STRUCT, len(self.sources))
            for iter114 in self.sources:
                iter114.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.keyColumns is not None:
            oprot.writeFieldBegin('keyColumns', TType.LIST, 3)
            oprot.writeListBegin(TType.STRING, len(self.keyColumns))
            for iter115 in self.keyColumns:
                oprot.writeString(iter115.encode('utf-8') if sys.version_info[0] == 2 else iter115)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.aggregations is not None:
            oprot.writeFieldBegin('aggregations', TType.LIST, 4)
            oprot.writeListBegin(TType.STRUCT, len(self.aggregations))
            for iter116 in self.aggregations:
                iter116.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.accuracy is not None:
            oprot.writeFieldBegin('accuracy', TType.I32, 5)
            oprot.writeI32(self.accuracy)
            oprot.writeFieldEnd()
        if self.backfillStartDate is not None:
            oprot.writeFieldBegin('backfillStartDate', TType.STRING, 6)
            oprot.writeString(self.backfillStartDate.encode('utf-8') if sys.version_info[0] == 2 else self.backfillStartDate)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class AggregationSelector(object):
    """
    Attributes:
     - name
     - windows

    """


    def __init__(self, name=None, windows=None,):
        self.name = name
        self.windows = windows

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.name = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.LIST:
                    self.windows = []
                    (_etype120, _size117) = iprot.readListBegin()
                    for _i121 in range(_size117):
                        _elem122 = Window()
                        _elem122.read(iprot)
                        self.windows.append(_elem122)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('AggregationSelector')
        if self.name is not None:
            oprot.writeFieldBegin('name', TType.STRING, 1)
            oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name)
            oprot.writeFieldEnd()
        if self.windows is not None:
            oprot.writeFieldBegin('windows', TType.LIST, 2)
            oprot.writeListBegin(TType.STRUCT, len(self.windows))
            for iter123 in self.windows:
                iter123.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class JoinPart(object):
    """
    Attributes:
     - groupBy
     - keyMapping
     - selectors
     - prefix

    """


    def __init__(self, groupBy=None, keyMapping=None, selectors=None, prefix=None,):
        self.groupBy = groupBy
        self.keyMapping = keyMapping
        self.selectors = selectors
        self.prefix = prefix

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.groupBy = GroupBy()
                    self.groupBy.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.MAP:
                    self.keyMapping = {}
                    (_ktype125, _vtype126, _size124) = iprot.readMapBegin()
                    for _i128 in range(_size124):
                        _key129 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val130 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyMapping[_key129] = _val130
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.LIST:
                    self.selectors = []
                    (_etype134, _size131) = iprot.readListBegin()
                    for _i135 in range(_size131):
                        _elem136 = AggregationSelector()
                        _elem136.read(iprot)
                        self.selectors.append(_elem136)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRING:
                    self.prefix = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('JoinPart')
        if self.groupBy is not None:
            oprot.writeFieldBegin('groupBy', TType.STRUCT, 1)
            self.groupBy.write(oprot)
            oprot.writeFieldEnd()
        if self.keyMapping is not None:
            oprot.writeFieldBegin('keyMapping', TType.MAP, 2)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.keyMapping))
            for kiter137, viter138 in self.keyMapping.items():
                oprot.writeString(kiter137.encode('utf-8') if sys.version_info[0] == 2 else kiter137)
                oprot.writeString(viter138.encode('utf-8') if sys.version_info[0] == 2 else viter138)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.selectors is not None:
            oprot.writeFieldBegin('selectors', TType.LIST, 3)
            oprot.writeListBegin(TType.STRUCT, len(self.selectors))
            for iter139 in self.selectors:
                iter139.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.prefix is not None:
            oprot.writeFieldBegin('prefix', TType.STRING, 4)
            oprot.writeString(self.prefix.encode('utf-8') if sys.version_info[0] == 2 else self.prefix)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class ExternalPart(object):
    """
    Attributes:
     - source
     - keyMapping
     - prefix

    """


    def __init__(self, source=None, keyMapping=None, prefix=None,):
        self.source = source
        self.keyMapping = keyMapping
        self.prefix = prefix

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.source = ExternalSource()
                    self.source.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.MAP:
                    self.keyMapping = {}
                    (_ktype141, _vtype142, _size140) = iprot.readMapBegin()
                    for _i144 in range(_size140):
                        _key145 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val146 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyMapping[_key145] = _val146
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.prefix = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('ExternalPart')
        if self.source is not None:
            oprot.writeFieldBegin('source', TType.STRUCT, 1)
            self.source.write(oprot)
            oprot.writeFieldEnd()
        if self.keyMapping is not None:
            oprot.writeFieldBegin('keyMapping', TType.MAP, 2)
            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.keyMapping))
            for kiter147, viter148 in self.keyMapping.items():
                oprot.writeString(kiter147.encode('utf-8') if sys.version_info[0] == 2 else kiter147)
                oprot.writeString(viter148.encode('utf-8') if sys.version_info[0] == 2 else viter148)
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.prefix is not None:
            oprot.writeFieldBegin('prefix', TType.STRING, 3)
            oprot.writeString(self.prefix.encode('utf-8') if sys.version_info[0] == 2 else self.prefix)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class Join(object):
    """
    Attributes:
     - metaData
     - left
     - joinParts
     - skewKeys
     - onlineExternalParts
     - labelPart

    """


    def __init__(self, metaData=None, left=None, joinParts=None, skewKeys=None, onlineExternalParts=None, labelPart=None,):
        self.metaData = metaData
        self.left = left
        self.joinParts = joinParts
        self.skewKeys = skewKeys
        self.onlineExternalParts = onlineExternalParts
        self.labelPart = labelPart

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.metaData = MetaData()
                    self.metaData.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRUCT:
                    self.left = Source()
                    self.left.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.LIST:
                    self.joinParts = []
                    (_etype152, _size149) = iprot.readListBegin()
                    for _i153 in range(_size149):
                        _elem154 = JoinPart()
                        _elem154.read(iprot)
                        self.joinParts.append(_elem154)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.MAP:
                    self.skewKeys = {}
                    (_ktype156, _vtype157, _size155) = iprot.readMapBegin()
                    for _i159 in range(_size155):
                        _key160 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val161 = []
                        (_etype165, _size162) = iprot.readListBegin()
                        for _i166 in range(_size162):
                            _elem167 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                            _val161.append(_elem167)
                        iprot.readListEnd()
                        self.skewKeys[_key160] = _val161
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.LIST:
                    self.onlineExternalParts = []
                    (_etype171, _size168) = iprot.readListBegin()
                    for _i172 in range(_size168):
                        _elem173 = ExternalPart()
                        _elem173.read(iprot)
                        self.onlineExternalParts.append(_elem173)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.STRUCT:
                    self.labelPart = LabelPart()
                    self.labelPart.read(iprot)
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('Join')
        if self.metaData is not None:
            oprot.writeFieldBegin('metaData', TType.STRUCT, 1)
            self.metaData.write(oprot)
            oprot.writeFieldEnd()
        if self.left is not None:
            oprot.writeFieldBegin('left', TType.STRUCT, 2)
            self.left.write(oprot)
            oprot.writeFieldEnd()
        if self.joinParts is not None:
            oprot.writeFieldBegin('joinParts', TType.LIST, 3)
            oprot.writeListBegin(TType.STRUCT, len(self.joinParts))
            for iter174 in self.joinParts:
                iter174.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.skewKeys is not None:
            oprot.writeFieldBegin('skewKeys', TType.MAP, 4)
            oprot.writeMapBegin(TType.STRING, TType.LIST, len(self.skewKeys))
            for kiter175, viter176 in self.skewKeys.items():
                oprot.writeString(kiter175.encode('utf-8') if sys.version_info[0] == 2 else kiter175)
                oprot.writeListBegin(TType.STRING, len(viter176))
                for iter177 in viter176:
                    oprot.writeString(iter177.encode('utf-8') if sys.version_info[0] == 2 else iter177)
                oprot.writeListEnd()
            oprot.writeMapEnd()
            oprot.writeFieldEnd()
        if self.onlineExternalParts is not None:
            oprot.writeFieldBegin('onlineExternalParts', TType.LIST, 5)
            oprot.writeListBegin(TType.STRUCT, len(self.onlineExternalParts))
            for iter178 in self.onlineExternalParts:
                iter178.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.labelPart is not None:
            oprot.writeFieldBegin('labelPart', TType.STRUCT, 6)
            self.labelPart.write(oprot)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class LabelPart(object):
    """
    Attributes:
     - labels
     - leftStartOffset
     - leftEndOffset

    """


    def __init__(self, labels=None, leftStartOffset=None, leftEndOffset=None,):
        self.labels = labels
        self.leftStartOffset = leftStartOffset
        self.leftEndOffset = leftEndOffset

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.LIST:
                    self.labels = []
                    (_etype182, _size179) = iprot.readListBegin()
                    for _i183 in range(_size179):
                        _elem184 = JoinPart()
                        _elem184.read(iprot)
                        self.labels.append(_elem184)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.I32:
                    self.leftStartOffset = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.I32:
                    self.leftEndOffset = iprot.readI32()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('LabelPart')
        if self.labels is not None:
            oprot.writeFieldBegin('labels', TType.LIST, 1)
            oprot.writeListBegin(TType.STRUCT, len(self.labels))
            for iter185 in self.labels:
                iter185.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.leftStartOffset is not None:
            oprot.writeFieldBegin('leftStartOffset', TType.I32, 2)
            oprot.writeI32(self.leftStartOffset)
            oprot.writeFieldEnd()
        if self.leftEndOffset is not None:
            oprot.writeFieldBegin('leftEndOffset', TType.I32, 3)
            oprot.writeI32(self.leftEndOffset)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class GroupByServingInfo(object):
    """
    Attributes:
     - groupBy
     - inputAvroSchema
     - selectedAvroSchema
     - keyAvroSchema
     - batchEndDate

    """


    def __init__(self, groupBy=None, inputAvroSchema=None, selectedAvroSchema=None, keyAvroSchema=None, batchEndDate=None,):
        self.groupBy = groupBy
        self.inputAvroSchema = inputAvroSchema
        self.selectedAvroSchema = selectedAvroSchema
        self.keyAvroSchema = keyAvroSchema
        self.batchEndDate = batchEndDate

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRUCT:
                    self.groupBy = GroupBy()
                    self.groupBy.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRING:
                    self.inputAvroSchema = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.selectedAvroSchema = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.STRING:
                    self.keyAvroSchema = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.STRING:
                    self.batchEndDate = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('GroupByServingInfo')
        if self.groupBy is not None:
            oprot.writeFieldBegin('groupBy', TType.STRUCT, 1)
            self.groupBy.write(oprot)
            oprot.writeFieldEnd()
        if self.inputAvroSchema is not None:
            oprot.writeFieldBegin('inputAvroSchema', TType.STRING, 2)
            oprot.writeString(self.inputAvroSchema.encode('utf-8') if sys.version_info[0] == 2 else self.inputAvroSchema)
            oprot.writeFieldEnd()
        if self.selectedAvroSchema is not None:
            oprot.writeFieldBegin('selectedAvroSchema', TType.STRING, 3)
            oprot.writeString(self.selectedAvroSchema.encode('utf-8') if sys.version_info[0] == 2 else self.selectedAvroSchema)
            oprot.writeFieldEnd()
        if self.keyAvroSchema is not None:
            oprot.writeFieldBegin('keyAvroSchema', TType.STRING, 4)
            oprot.writeString(self.keyAvroSchema.encode('utf-8') if sys.version_info[0] == 2 else self.keyAvroSchema)
            oprot.writeFieldEnd()
        if self.batchEndDate is not None:
            oprot.writeFieldBegin('batchEndDate', TType.STRING, 5)
            oprot.writeString(self.batchEndDate.encode('utf-8') if sys.version_info[0] == 2 else self.batchEndDate)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class DataField(object):
    """
    Attributes:
     - name
     - dataType

    """


    def __init__(self, name=None, dataType=None,):
        self.name = name
        self.dataType = dataType

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.name = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRUCT:
                    self.dataType = TDataType()
                    self.dataType.read(iprot)
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('DataField')
        if self.name is not None:
            oprot.writeFieldBegin('name', TType.STRING, 1)
            oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name)
            oprot.writeFieldEnd()
        if self.dataType is not None:
            oprot.writeFieldBegin('dataType', TType.STRUCT, 2)
            self.dataType.write(oprot)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)


class TDataType(object):
    """
    Attributes:
     - kind
     - params
     - name

    """


    def __init__(self, kind=None, params=None, name=None,):
        self.kind = kind
        self.params = params
        self.name = name

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.I32:
                    self.kind = iprot.readI32()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.LIST:
                    self.params = []
                    (_etype189, _size186) = iprot.readListBegin()
                    for _i190 in range(_size186):
                        _elem191 = DataField()
                        _elem191.read(iprot)
                        self.params.append(_elem191)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.name = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('TDataType')
        if self.kind is not None:
            oprot.writeFieldBegin('kind', TType.I32, 1)
            oprot.writeI32(self.kind)
            oprot.writeFieldEnd()
        if self.params is not None:
            oprot.writeFieldBegin('params', TType.LIST, 2)
            oprot.writeListBegin(TType.STRUCT, len(self.params))
            for iter192 in self.params:
                iter192.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.name is not None:
            oprot.writeFieldBegin('name', TType.STRING, 3)
            oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)
all_structs.append(Query)
Query.thrift_spec = (
    None,  # 0
    (1, TType.MAP, 'selects', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 1
    (2, TType.LIST, 'wheres', (TType.STRING, 'UTF8', False), None, ),  # 2
    (3, TType.STRING, 'startPartition', 'UTF8', None, ),  # 3
    (4, TType.STRING, 'endPartition', 'UTF8', None, ),  # 4
    (5, TType.STRING, 'timeColumn', 'UTF8', None, ),  # 5
    (6, TType.LIST, 'setups', (TType.STRING, 'UTF8', False), [
    ], ),  # 6
    (7, TType.STRING, 'mutationTimeColumn', 'UTF8', None, ),  # 7
    (8, TType.STRING, 'reversalColumn', 'UTF8', None, ),  # 8
)
all_structs.append(StagingQuery)
StagingQuery.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'metaData', [MetaData, None], None, ),  # 1
    (2, TType.STRING, 'query', 'UTF8', None, ),  # 2
    (3, TType.STRING, 'startPartition', 'UTF8', None, ),  # 3
    (4, TType.LIST, 'setups', (TType.STRING, 'UTF8', False), None, ),  # 4
)
all_structs.append(EventSource)
EventSource.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'table', 'UTF8', None, ),  # 1
    (2, TType.STRING, 'topic', 'UTF8', None, ),  # 2
    (3, TType.STRUCT, 'query', [Query, None], None, ),  # 3
    (4, TType.BOOL, 'isCumulative', None, None, ),  # 4
)
all_structs.append(EntitySource)
EntitySource.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'snapshotTable', 'UTF8', None, ),  # 1
    (2, TType.STRING, 'mutationTable', 'UTF8', None, ),  # 2
    (3, TType.STRING, 'mutationTopic', 'UTF8', None, ),  # 3
    (4, TType.STRUCT, 'query', [Query, None], None, ),  # 4
)
all_structs.append(ExternalSource)
ExternalSource.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'metadata', [MetaData, None], None, ),  # 1
    (2, TType.STRUCT, 'keySchema', [TDataType, None], None, ),  # 2
    (3, TType.STRUCT, 'valueSchema', [TDataType, None], None, ),  # 3
)
all_structs.append(Source)
Source.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'events', [EventSource, None], None, ),  # 1
    (2, TType.STRUCT, 'entities', [EntitySource, None], None, ),  # 2
)
all_structs.append(Window)
Window.thrift_spec = (
    None,  # 0
    (1, TType.I32, 'length', None, None, ),  # 1
    (2, TType.I32, 'timeUnit', None, None, ),  # 2
)
all_structs.append(Aggregation)
Aggregation.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'inputColumn', 'UTF8', None, ),  # 1
    (2, TType.I32, 'operation', None, None, ),  # 2
    (3, TType.MAP, 'argMap', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 3
    (4, TType.LIST, 'windows', (TType.STRUCT, [Window, None], False), None, ),  # 4
    (5, TType.LIST, 'buckets', (TType.STRING, 'UTF8', False), None, ),  # 5
)
all_structs.append(AggregationPart)
AggregationPart.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'inputColumn', 'UTF8', None, ),  # 1
    (2, TType.I32, 'operation', None, None, ),  # 2
    (3, TType.MAP, 'argMap', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 3
    (4, TType.STRUCT, 'window', [Window, None], None, ),  # 4
    (5, TType.STRING, 'bucket', 'UTF8', None, ),  # 5
)
all_structs.append(MetaData)
MetaData.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'name', 'UTF8', None, ),  # 1
    (2, TType.BOOL, 'online', None, None, ),  # 2
    (3, TType.BOOL, 'production', None, None, ),  # 3
    (4, TType.STRING, 'customJson', 'UTF8', None, ),  # 4
    (5, TType.LIST, 'dependencies', (TType.STRING, 'UTF8', False), None, ),  # 5
    (6, TType.MAP, 'tableProperties', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 6
    (7, TType.STRING, 'outputNamespace', 'UTF8', None, ),  # 7
    (8, TType.STRING, 'team', 'UTF8', None, ),  # 8
    (9, TType.MAP, 'modeToEnvMap', (TType.STRING, 'UTF8', TType.MAP, (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), False), None, ),  # 9
    (10, TType.BOOL, 'consistencyCheck', None, None, ),  # 10
    (11, TType.DOUBLE, 'samplePercent', None, None, ),  # 11
    (12, TType.STRING, 'offlineSchedule', 'UTF8', None, ),  # 12
)
all_structs.append(GroupBy)
GroupBy.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'metaData', [MetaData, None], None, ),  # 1
    (2, TType.LIST, 'sources', (TType.STRUCT, [Source, None], False), None, ),  # 2
    (3, TType.LIST, 'keyColumns', (TType.STRING, 'UTF8', False), None, ),  # 3
    (4, TType.LIST, 'aggregations', (TType.STRUCT, [Aggregation, None], False), None, ),  # 4
    (5, TType.I32, 'accuracy', None, None, ),  # 5
    (6, TType.STRING, 'backfillStartDate', 'UTF8', None, ),  # 6
)
all_structs.append(AggregationSelector)
AggregationSelector.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'name', 'UTF8', None, ),  # 1
    (2, TType.LIST, 'windows', (TType.STRUCT, [Window, None], False), None, ),  # 2
)
all_structs.append(JoinPart)
JoinPart.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'groupBy', [GroupBy, None], None, ),  # 1
    (2, TType.MAP, 'keyMapping', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 2
    (3, TType.LIST, 'selectors', (TType.STRUCT, [AggregationSelector, None], False), None, ),  # 3
    (4, TType.STRING, 'prefix', 'UTF8', None, ),  # 4
)
all_structs.append(ExternalPart)
ExternalPart.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'source', [ExternalSource, None], None, ),  # 1
    (2, TType.MAP, 'keyMapping', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 2
    (3, TType.STRING, 'prefix', 'UTF8', None, ),  # 3
)
all_structs.append(Join)
Join.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'metaData', [MetaData, None], None, ),  # 1
    (2, TType.STRUCT, 'left', [Source, None], None, ),  # 2
    (3, TType.LIST, 'joinParts', (TType.STRUCT, [JoinPart, None], False), None, ),  # 3
    (4, TType.MAP, 'skewKeys', (TType.STRING, 'UTF8', TType.LIST, (TType.STRING, 'UTF8', False), False), None, ),  # 4
    (5, TType.LIST, 'onlineExternalParts', (TType.STRUCT, [ExternalPart, None], False), None, ),  # 5
    (6, TType.STRUCT, 'labelPart', [LabelPart, None], None, ),  # 6
)
all_structs.append(LabelPart)
LabelPart.thrift_spec = (
    None,  # 0
    (1, TType.LIST, 'labels', (TType.STRUCT, [JoinPart, None], False), None, ),  # 1
    (2, TType.I32, 'leftStartOffset', None, None, ),  # 2
    (3, TType.I32, 'leftEndOffset', None, None, ),  # 3
)
all_structs.append(GroupByServingInfo)
GroupByServingInfo.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'groupBy', [GroupBy, None], None, ),  # 1
    (2, TType.STRING, 'inputAvroSchema', 'UTF8', None, ),  # 2
    (3, TType.STRING, 'selectedAvroSchema', 'UTF8', None, ),  # 3
    (4, TType.STRING, 'keyAvroSchema', 'UTF8', None, ),  # 4
    (5, TType.STRING, 'batchEndDate', 'UTF8', None, ),  # 5
)
all_structs.append(DataField)
DataField.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'name', 'UTF8', None, ),  # 1
    (2, TType.STRUCT, 'dataType', [TDataType, None], None, ),  # 2
)
all_structs.append(TDataType)
TDataType.thrift_spec = (
    None,  # 0
    (1, TType.I32, 'kind', None, None, ),  # 1
    (2, TType.LIST, 'params', (TType.STRUCT, [DataField, None], False), None, ),  # 2
    (3, TType.STRING, 'name', 'UTF8', None, ),  # 3
)
fix_spec(all_structs)
del all_structs
