Exemple #1
0
class Role(BaseModel):
    __tablename__ = 'role'

    id = Column(String, primary_key=True)
    proj_id = Column(String, ForeignKey('proj.id', ondelete='CASCADE'))
    dep = Column(DEP, index=True)
    name = Column(String, unique=True)
    note = Column(Text, nullable=True)
    taken = Column(Boolean, default=False)

    proj = relationship('Proj', back_populates='roles')
    pits = relationship('Pit',
                        back_populates='role',
                        lazy='dynamic',
                        passive_deletes=True)
    __table_args__ = (UniqueConstraint('proj_id',
                                       'dep',
                                       'name',
                                       name='_role_uc'), )
    __id_len__ = 12

    @property
    def pit(self):
        return self.pits.filter(Pit.status.in_({Pit.S.fin, Pit.S.fin_p})).one()

    def __json__(self):
        return {
            'id': self.id,
            'dep': self.dep,
            'name': self.name,
            'note': self.note,
        }
Exemple #2
0
class Chat(BaseModel):
    __tablename__ = 'chat'

    id = Column(String, primary_key=True)
    order = Column(Integer)
    proj_id = Column(String, ForeignKey('proj.id', ondelete='CASCADE'))
    pink_id = Column(String, ForeignKey('pink.id', ondelete='SET NULL'))
    reply_to_id = Column(String,
                         ForeignKey('chat.id', ondelete='CASCADE'),
                         nullable=True)
    deleted = Column(Boolean, default=False)

    ver = Column(Integer, default=0)
    reply_to_ver = Column(Integer, nullable=True)
    content = Column(Text)
    at = Column(DateTime)

    history = Column(JSONB, default=dict)

    proj = relationship('Proj', back_populates='chats')
    reply_to = relationship('Chat', remote_side=[id], back_populates='replies')
    replies = relationship('Chat',
                           remote_side=[id],
                           order_by='Chat.order',
                           back_populates='reply_to',
                           lazy='dynamic')
    __id_len__ = 14

    def update(self, now, content):
        if self.ver > 0:
            self.history[self.ver] = {
                'reply_to_ver': self.reply_to_ver,
                'content': self.content,
                'at': self.at.timestamp(),
            }
        self.ver += 1
        if self.reply_to_id:
            self.reply_to_ver = self.reply_to.ver
        self.content = content
        self.at = now

    def set_order(self, proj_timestamp, now):
        self.order = (now.timestamp() - proj_timestamp.timestamp()) * 10

    def __json__(self):
        return {
            'id': self.id,
            'order': self.order,
            'deps': self.deps,
            'pink_id': self.pink_id,
            'reply_to_id': self.reply_to_id,
            'ver': self.ver,
            'content': self.content,
            'at': self.at
        }
Exemple #3
0
class Pink(BaseModel):
    __tablename__ = 'pink'

    id = Column(String, primary_key=True)
    name = Column(String, unique=True, index=True)
    email = Column(String, unique=True)
    qq = Column(String, nullable=True)
    other = Column(String, nullable=True)
    deps = Column(ARRAY(DEP))
    _pwd = Column(String)
    active = Column(Boolean, default=True)

    pits = relationship('Pit', back_populates='pink', lazy='dynamic', passive_deletes=True)
    ducks = relationship('Duck', back_populates='pink', lazy='dynamic', passive_deletes=True)
    lemons = relationship('Lemon', back_populates='pink', lazy='dynamic', passive_deletes=True)
    __id_len__ = 9

    @property
    def pwd(self):
        raise AttributeError('SHOLD NOT READ PWD')

    @pwd.setter
    def pwd(self, new_pwd):
        self._pwd = pwd_hasher.hash(new_pwd)

    def check_pwd(self, pwd):
        return pwd_hasher.verify(self._pwd, pwd)

    def __json__(self):
        return {
            'id': self.id,
            'name': self.name,
            'qq': self.qq,
            'other': self.other,
            'deps': self.deps
        }
Exemple #4
0
class Lemon(BaseModel):
    __tablename__ = 'lemon'

    id = Column(String, primary_key=True)
    key = Column(String)
    pink_id = Column(String, ForeignKey('pink.id', ondelete='CASCADE'))
    ip = Column(String)
    device_id = Column(UUID)
    expiration = Column(DateTime)
    timestamp = Column(DateTime)

    pink = relationship('Pink', back_populates='lemons')
    __table_args__ = (UniqueConstraint('pink_id',
                                       'device_id',
                                       name='_lemon_uc'), )
    __id_len__ = 10

    def __json__(self):
        return {'id': self.id, 'ip': self.ip, 'exp': self.expiration}
Exemple #5
0
class Mango(BaseModel):
    __tablename__ = 'mango'

    id = Column(String, primary_key=True)
    pit_id = Column(String, ForeignKey('pit.id', ondelete='CASCADE'))
    ver = Column(Integer, default=1)
    mime = Column(String)
    sha1 = Column(String, unique=True)
    modified_at = Column(DateTime)
    timestamp = Column(DateTime)

    metainfo = Column(JSONB)

    pit = relationship('Pit', back_populates='mangos')
    __table_args__ = (UniqueConstraint('pit_id', 'ver', name='_mango_uc'), )

    @property
    def mtype(self):
        return self.mime.split('/')[0]
Exemple #6
0
class Duck(BaseModel):
    __tablename__ = 'duck'

    pink_id = Column(String,
                     ForeignKey('pink.id', ondelete='CASCADE'),
                     primary_key=True)
    node = Column(String, primary_key=True)
    allow = Column(Boolean)
    scopes = Column(ARRAY(String))

    pink = relationship('Pink', back_populates='lemons')
    __table_args__ = (UniqueConstraint('pink_id', 'node', name='_duck_uc'), )

    def __json__(self):
        return {
            'pink_id': self.pink_id,
            'node': self.node,
            'allow': self.allow,
            'scopes': self.scopes
        }
Exemple #7
0
class Pit(BaseModel):
    __tablename__ = 'pit'

    # Status
    class S(ZEnum):
        init = 'I'
        pending = 'P'
        working = 'w'
        delayed = 'd'
        past_due = 'p'
        auditing = 'a'
        fin = 'F'
        fin_p = 'Fp'
        dropped = 'D'

    id = Column(String, primary_key=True)
    role_id = Column(String, ForeignKey('role.id', ondelete='CASCADE'))
    pink_id = Column(String, ForeignKey('pink.id', ondelete='SET NULL'))
    status = Column(Enum(S, name='pit_status'), default=S.init, index=True)
    start_at = Column(DateTime, nullable=True)
    finish_at = Column(DateTime, nullable=True)
    due = Column(DateTime, nullable=True)
    timestamp = Column(DateTime)

    track = Column(ARRAY(String), default=list)

    pink = relationship('Pink', back_populates='pits')
    role = relationship('Role', back_populates='pits')
    mangos = relationship('Mango',
                          back_populates='pit',
                          order_by='Mango.ver.desc()',
                          lazy='dynamic',
                          passive_deletes=True)
    __id_len__ = 13

    @property
    def mango(self):
        return self.mangos.order_by(Mango.ver.desc()).first()

    # Trace
    class T(ZEnum):
        pick_f = 'P'
        drop = 'd'
        shift = '<-'
        cascade = '->'
        past_due = '<>'
        fake_past_due = '><'
        submit = 's'
        submit_f = 'S'
        redo = 'r'
        check_pass = '******'
        check_fail = 'x'
        extend = '+'

    def add_track(self, info: 'T', now, by=''):
        base = f'{info.value} - {now}'
        if info in (Pit.T.past_due, Pit.T.pick_f, Pit.T.submit_f,
                    Pit.T.check_fail, Pit.T.check_pass):
            self.track.append(f'{base} by:{by}')
        elif info in (Pit.T.shift, Pit.T.cascade):
            self.track.append(f'{base} by:{by} from:{self.due}')
        elif info == Pit.T.extend:
            self.track.append(f'{base} from:{self.due}')
        else:
            self.track.append(base)

    def __json__(self):
        return {
            'id': self.id,
            'role_id': self.role_id,
            'dep': self.role.dep,
            'role': self.role.name,
            'pink_id': self.pink_id,
            'status': self.status,
            'start_at': self.start_at,
            'finish_at': self.finish_at,
            'due': self.due
        }
Exemple #8
0
class Proj(BaseModel):
    __tablename__ = 'proj'

    # Status
    class S(ZEnum):
        pre = 'p'
        freezed = 'FF'
        working = 'w'
        upload = 'u'
        fin = 'F'

    # Category
    class C(ZEnum):
        doc = 'documentary'
        sub = 'sub-content'
        ani = 'animation'

    id = Column(String, primary_key=True)
    title = Column(String, index=True)
    source = Column(String)
    cat = Column(Enum(C, name='proj_cat'))
    suff = Column(String)
    status = Column(Enum(S, name='proj_status'), default=S.pre)
    leader_id = Column(String, ForeignKey('pink.id', ondelete='SET NULL'))
    word_count = Column(Integer)
    start_at = Column(DateTime, nullable=True)
    finish_at = Column(DateTime, nullable=True)
    url = Column(String, nullable=True)
    timestamp = Column(DateTime)

    track = Column(ARRAY(String), default=list)

    roles = relationship('Role', back_populates='proj', lazy='dynamic', passive_deletes=True)
    chats = relationship('Chat', back_populates='proj', lazy='dynamic', passive_deletes=True)
    __table_args__ = (UniqueConstraint('source', 'cat', 'suff', name='_proj_uc'), )
    __id_len__ = 11

    @hybrid_property
    def display_title(self):
        return f'{self.title}({self.suff})' if self.suff else self.title

    # Trace
    class T(ZEnum):
        re_open = 'r'
        freeze = 'F'
        upload = 'U'
        start = 's'

    def add_track(self, info: 'Proj.T', now, by=''):
        base = f'{info.value} - {now}'
        if info == Proj.T.re_open:
            self.track.append(f'{base} by:{by}')
        else:
            self.track.append(base)

    def __json__(self):
        return {
            'id': self.id,
            'title': self.display_title,
            'source': self.source,
            'cat': self.cat,
            'status': self.status,
            'leader_id': self.leader_id,
            'word_count': self.word_count,
            'start_at': self.start_at
        }