#
# 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.

    Attributes:
     - metaData: Contains name, team, output_namespace, execution parameters etc. Things that don't change the semantics of the computation itself.

     - query: Arbitrary spark query that should be written with `{{ start_date }}`, `{{ end_date }}` and `{{ latest_date }}` templates
         - `{{ start_date }}` will be set to this user provided start date, future incremental runs will set it to the latest existing partition + 1 day.
         - `{{ end_date }}` is the end partition of the computing range.
         - `{{ latest_date }}` is the end partition independent of the computing range (meant for cumulative sources).

     - startPartition: on the first run, `{{ start_date }}` will be set to this user provided start date, future incremental runs will set it to the latest existing partition + 1 day.

     - setups: Spark SQL setup statements. Used typically to register UDFs.


    """


    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):
    """
    Attributes:
     - 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

     - topic: Topic is a kafka table. The table contains all the events historically came through this topic.

     - query: The logic used to scan both the table and the topic. Contains row level transformations and filtering expressed as Spark SQL statements.

     - 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.


    """


    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.

    Attributes:
     - snapshotTable: Snapshot table currently needs to be a 'ds' (date string - yyyy-MM-dd) partitioned hive table.
     - mutationTable: Topic is a kafka table. The table contains all the events that historically came through this topic.
     - mutationTopic: The logic used to scan both the table and the topic. Contains row level transformations and filtering expressed as Spark SQL statements.
     - query: 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.

    """


    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.

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

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

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

     - 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
     - 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
     - consistencySamplePercent

    """


    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, consistencySamplePercent=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
        self.consistencySamplePercent = consistencySamplePercent

    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)
            elif fid == 13:
                if ftype == TType.DOUBLE:
                    self.consistencySamplePercent = iprot.readDouble()
                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()
        if self.consistencySamplePercent is not None:
            oprot.writeFieldBegin('consistencySamplePercent', TType.DOUBLE, 13)
            oprot.writeDouble(self.consistencySamplePercent)
            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 JoinPart(object):
    """
    Attributes:
     - groupBy
     - keyMapping
     - prefix

    """


    def __init__(self, groupBy=None, keyMapping=None, prefix=None,):
        self.groupBy = groupBy
        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.groupBy = GroupBy()
                    self.groupBy.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.MAP:
                    self.keyMapping = {}
                    (_ktype118, _vtype119, _size117) = iprot.readMapBegin()
                    for _i121 in range(_size117):
                        _key122 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val123 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyMapping[_key122] = _val123
                    iprot.readMapEnd()
                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 kiter124, viter125 in self.keyMapping.items():
                oprot.writeString(kiter124.encode('utf-8') if sys.version_info[0] == 2 else kiter124)
                oprot.writeString(viter125.encode('utf-8') if sys.version_info[0] == 2 else viter125)
            oprot.writeMapEnd()
            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 = {}
                    (_ktype127, _vtype128, _size126) = iprot.readMapBegin()
                    for _i130 in range(_size126):
                        _key131 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val132 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyMapping[_key131] = _val132
                    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 kiter133, viter134 in self.keyMapping.items():
                oprot.writeString(kiter133.encode('utf-8') if sys.version_info[0] == 2 else kiter133)
                oprot.writeString(viter134.encode('utf-8') if sys.version_info[0] == 2 else viter134)
            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 Derivation(object):
    """
    Attributes:
     - name
     - expression

    """


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

    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.STRING:
                    self.expression = 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('Derivation')
        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.expression is not None:
            oprot.writeFieldBegin('expression', TType.STRING, 2)
            oprot.writeString(self.expression.encode('utf-8') if sys.version_info[0] == 2 else self.expression)
            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
     - bootstrapParts
     - rowIds
     - derivations: List of a derived column names to the expression based on joinPart / externalPart columns
    The expression can be any valid Spark SQL select clause without aggregation functions.

    joinPart column names are automatically constructed according to the below convention
     `{join_part_prefix}_{group_by_name}_{input_column_name}_{aggregation_operation}_{window}_{by_bucket}`
     prefix, window and bucket are optional. You can find the type information of columns using the analyzer tool.

    externalPart column names are automatically constructed according to the below convention
     `ext_{external_source_name}_{value_column}`
    Types are defined along with the schema by users for external sources.

    Including a column with key "*" and value "*", means that every raw column will be included along with the derived
    columns.


    """


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

    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 = []
                    (_etype138, _size135) = iprot.readListBegin()
                    for _i139 in range(_size135):
                        _elem140 = JoinPart()
                        _elem140.read(iprot)
                        self.joinParts.append(_elem140)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.MAP:
                    self.skewKeys = {}
                    (_ktype142, _vtype143, _size141) = iprot.readMapBegin()
                    for _i145 in range(_size141):
                        _key146 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        _val147 = []
                        (_etype151, _size148) = iprot.readListBegin()
                        for _i152 in range(_size148):
                            _elem153 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                            _val147.append(_elem153)
                        iprot.readListEnd()
                        self.skewKeys[_key146] = _val147
                    iprot.readMapEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.LIST:
                    self.onlineExternalParts = []
                    (_etype157, _size154) = iprot.readListBegin()
                    for _i158 in range(_size154):
                        _elem159 = ExternalPart()
                        _elem159.read(iprot)
                        self.onlineExternalParts.append(_elem159)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.STRUCT:
                    self.labelPart = LabelPart()
                    self.labelPart.read(iprot)
                else:
                    iprot.skip(ftype)
            elif fid == 7:
                if ftype == TType.LIST:
                    self.bootstrapParts = []
                    (_etype163, _size160) = iprot.readListBegin()
                    for _i164 in range(_size160):
                        _elem165 = BootstrapPart()
                        _elem165.read(iprot)
                        self.bootstrapParts.append(_elem165)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 8:
                if ftype == TType.LIST:
                    self.rowIds = []
                    (_etype169, _size166) = iprot.readListBegin()
                    for _i170 in range(_size166):
                        _elem171 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.rowIds.append(_elem171)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 9:
                if ftype == TType.LIST:
                    self.derivations = []
                    (_etype175, _size172) = iprot.readListBegin()
                    for _i176 in range(_size172):
                        _elem177 = Derivation()
                        _elem177.read(iprot)
                        self.derivations.append(_elem177)
                    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('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 iter178 in self.joinParts:
                iter178.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 kiter179, viter180 in self.skewKeys.items():
                oprot.writeString(kiter179.encode('utf-8') if sys.version_info[0] == 2 else kiter179)
                oprot.writeListBegin(TType.STRING, len(viter180))
                for iter181 in viter180:
                    oprot.writeString(iter181.encode('utf-8') if sys.version_info[0] == 2 else iter181)
                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 iter182 in self.onlineExternalParts:
                iter182.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.labelPart is not None:
            oprot.writeFieldBegin('labelPart', TType.STRUCT, 6)
            self.labelPart.write(oprot)
            oprot.writeFieldEnd()
        if self.bootstrapParts is not None:
            oprot.writeFieldBegin('bootstrapParts', TType.LIST, 7)
            oprot.writeListBegin(TType.STRUCT, len(self.bootstrapParts))
            for iter183 in self.bootstrapParts:
                iter183.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.rowIds is not None:
            oprot.writeFieldBegin('rowIds', TType.LIST, 8)
            oprot.writeListBegin(TType.STRING, len(self.rowIds))
            for iter184 in self.rowIds:
                oprot.writeString(iter184.encode('utf-8') if sys.version_info[0] == 2 else iter184)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.derivations is not None:
            oprot.writeFieldBegin('derivations', TType.LIST, 9)
            oprot.writeListBegin(TType.STRUCT, len(self.derivations))
            for iter185 in self.derivations:
                iter185.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 BootstrapPart(object):
    """
    Attributes:
     - metaData
     - table
     - query
     - keyColumns

    """


    def __init__(self, metaData=None, table=None, query=None, keyColumns=None,):
        self.metaData = metaData
        self.table = table
        self.query = query
        self.keyColumns = keyColumns

    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.table = 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.LIST:
                    self.keyColumns = []
                    (_etype189, _size186) = iprot.readListBegin()
                    for _i190 in range(_size186):
                        _elem191 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                        self.keyColumns.append(_elem191)
                    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('BootstrapPart')
        if self.metaData is not None:
            oprot.writeFieldBegin('metaData', TType.STRUCT, 1)
            self.metaData.write(oprot)
            oprot.writeFieldEnd()
        if self.table is not None:
            oprot.writeFieldBegin('table', TType.STRING, 2)
            oprot.writeString(self.table.encode('utf-8') if sys.version_info[0] == 2 else self.table)
            oprot.writeFieldEnd()
        if self.query is not None:
            oprot.writeFieldBegin('query', TType.STRUCT, 3)
            self.query.write(oprot)
            oprot.writeFieldEnd()
        if self.keyColumns is not None:
            oprot.writeFieldBegin('keyColumns', TType.LIST, 4)
            oprot.writeListBegin(TType.STRING, len(self.keyColumns))
            for iter192 in self.keyColumns:
                oprot.writeString(iter192.encode('utf-8') if sys.version_info[0] == 2 else iter192)
            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 LabelPart(object):
    """
    Attributes:
     - labels
     - leftStartOffset
     - leftEndOffset
     - metaData

    """


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

    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 = []
                    (_etype196, _size193) = iprot.readListBegin()
                    for _i197 in range(_size193):
                        _elem198 = JoinPart()
                        _elem198.read(iprot)
                        self.labels.append(_elem198)
                    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)
            elif fid == 4:
                if ftype == TType.STRUCT:
                    self.metaData = MetaData()
                    self.metaData.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('LabelPart')
        if self.labels is not None:
            oprot.writeFieldBegin('labels', TType.LIST, 1)
            oprot.writeListBegin(TType.STRUCT, len(self.labels))
            for iter199 in self.labels:
                iter199.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()
        if self.metaData is not None:
            oprot.writeFieldBegin('metaData', TType.STRUCT, 4)
            self.metaData.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 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 = []
                    (_etype203, _size200) = iprot.readListBegin()
                    for _i204 in range(_size200):
                        _elem205 = DataField()
                        _elem205.read(iprot)
                        self.params.append(_elem205)
                    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 iter206 in self.params:
                iter206.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
    (13, TType.DOUBLE, 'consistencySamplePercent', None, None, ),  # 13
)
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(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
    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(Derivation)
Derivation.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'name', 'UTF8', None, ),  # 1
    (2, TType.STRING, 'expression', 'UTF8', None, ),  # 2
)
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
    (7, TType.LIST, 'bootstrapParts', (TType.STRUCT, [BootstrapPart, None], False), None, ),  # 7
    (8, TType.LIST, 'rowIds', (TType.STRING, 'UTF8', False), None, ),  # 8
    (9, TType.LIST, 'derivations', (TType.STRUCT, [Derivation, None], False), None, ),  # 9
)
all_structs.append(BootstrapPart)
BootstrapPart.thrift_spec = (
    None,  # 0
    (1, TType.STRUCT, 'metaData', [MetaData, None], None, ),  # 1
    (2, TType.STRING, 'table', 'UTF8', None, ),  # 2
    (3, TType.STRUCT, 'query', [Query, None], None, ),  # 3
    (4, TType.LIST, 'keyColumns', (TType.STRING, 'UTF8', False), None, ),  # 4
)
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
    (4, TType.STRUCT, 'metaData', [MetaData, None], None, ),  # 4
)
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
