Esempio n. 1
0
def get_rows(select):
    # type: (cgtwq.Selection) -> List[Dict]

    histories = select.history.get(
        cgtwq.Field('status').in_(['Retake', 'Approve']))

    tasks = set([i.task_id for i in histories])
    tasks = select.module.select(*tasks)
    tasks = tasks.get_fields("id", "shot.entity", "pipeline", "artist")
    tasks = {i[0]: dict(shot=i[1], pipeline=i[2], artist=i[3]) for i in tasks}
    ret = []
    history_by_task = {}
    for i in histories:
        history_by_task.setdefault(i.task_id, []).append(i)
    history_by_task = {
        k: sorted(v, reverse=True, key=lambda x: x.time)
        for k, v in history_by_task.iteritems()
    }
    for i in histories:  # type: cgtwq.model.HistoryInfo
        task = tasks[i.task_id]
        row = dict(task)
        row.update(html=i.text,
                   created_by=i.create_by,
                   time=i.time,
                   status=tr("status." + i.status),
                   step=i.step,
                   order=history_by_task[i.task_id].index(i) + 1)
        ret.append(row)

    return sorted(ret, key=lambda x: (x['shot'], x['pipeline'], x['order']))
Esempio n. 2
0
def test_module_field(module):
    field_sign = "python_test_{}".format(
        "".join(
            [
                random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
                for i in range(20)
            ]
        )
    )
    module.field.create(sign=field_sign, type_="int")
    field = module.database.field.filter_one(
        cgtwq.Field("sign")
        == (cgtwq.Field(field_sign).in_namespace(module.default_field_namespace))
    )
    assert "python_test_" in field.sign
    module.field.delete(field.id)
Esempio n. 3
0
def get_filebox_meta(select):
    """Get filebox for final files.  """

    assert isinstance(select, cgtwq.Selection), type(select)
    pipelines = select.pipeline.all()
    assert pipelines
    fileboxes = select.module.database.filebox.filter(
        cgtwq.Field('title').has('最终'),
        cgtwq.Field('#pipeline_id').in_([i.id for i in pipelines]))
    if not fileboxes:
        raise RuntimeError('No matched fileboxes')
    elif len(fileboxes) != 1:
        raise RuntimeError('Multiple matched filebox', fileboxes)
    ret = fileboxes[0]
    assert isinstance(ret, cgtwq.model.FileBoxMeta)
    return ret
Esempio n. 4
0
def _apply_on_selection(select, data):
    def _check_alias(value, alias, name, label):
        if value not in alias:
            LOGGER.error('不能识别表格中给出的任务%s: 行=%s, 值=%s, 支持的值有: %s',
                         label, data.index, value,
                         ', '.join(i for j in [alias.keys()] + alias.values() for i in j))
            raise ValueError('Can not recognize {}.'.format(name), value)

    assert isinstance(data, RowData)
    assert isinstance(select, cgtwq.Selection)
    status = data.status
    field = _convert_from_alias(data.phase, FIELD_ALIAS)
    _check_alias(field, FIELD_ALIAS, 'phase', '阶段')
    if field not in FIELD_ALIAS:
        LOGGER.error('不能识别表格中给出的任务阶段: 行=%s, 值=%s, 支持的值有: %s', data.index, field,
                     ', '.join(i for j in [FIELD_ALIAS.keys()] + FIELD_ALIAS.values() for i in j))
        raise ValueError('Can not recognize field.', field)

    entries = select.to_entries()
    if len(entries) != 1:
        LOGGER.warning('发现%s个名为%s的%s任务, 都将被修改',
                       len(entries), data.shot, data.pipeline)

    for entry in entries:
        assert isinstance(entry, cgtwq.Entry)

        message = cgtwq.Message(_convert_note(data.note))
        if message:
            _message = message.dumps()
            if entry.history.get(
                    (cgtwq.Field('status') == status)
                    & (cgtwq.Field('text') == _message)):
                LOGGER.info('此条已导入, 跳过: 行=%s', data.index)
                continue
        else:
            if entry['status'] == status:
                LOGGER.info('此条已导入, 跳过: 行=%s', data.index)
                continue

        try:
            entry.flow.update(field, status, message=message)
            LOGGER.info('成功导入: 行=%s, 镜头=%s, 流程=%s, 阶段=%s, 状态=%s, 备注=%s',
                        data.index, data.shot, data.pipeline, data.phase, data.status, message)
        except cgtwq.PermissionError:
            LOGGER.error('当前用户无权限: 行=%s, 阶段=%s', data.index, data.phase)
        except ValueError as ex:
            LOGGER.error('错误: 行=%s, %s', data.index, ex)
Esempio n. 5
0
def test_database_fields(database):
    # Get
    assert isinstance(database, cgtwq.Database)
    result = database.field.filter()
    assert all(isinstance(i, cgtwq.model.FieldMeta) for i in result)
    result = database.field.filter_one(
        cgtwq.Field("sign") == cgtwq.compat.adapt_field_sign("shot.entity"))
    assert isinstance(result, cgtwq.model.FieldMeta)

    # Create
    field_sign = "task.python_test_{}".format("".join([
        random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
        for _ in range(20)
    ]))
    database.field.create(sign=field_sign, type_="int")

    # Delete
    field = database.field.filter_one(cgtwq.Field("sign") == field_sign)
    assert field.sign == field_sign
    database.field.delete(field.id)
Esempio n. 6
0
def test_get_database():
    project = cgtwq.PROJECT.filter(
        cgtwq.Field("entity") == "SDKTEST").to_entry()
    orig_status = project["status"]
    project["status"] = "Active"
    assert (cgtwq.helper.wlf.get_database_by_file("sdktest_example.jpg") ==
            "proj_sdktest")

    with pytest.raises(cgtwq.helper.wlf.DatabaseError):
        cgtwq.helper.wlf.CGTWQHelper.get_database("example.jpg")

    project["status"] = orig_status
Esempio n. 7
0
def import_data(data, database, module, module_type):
    """Import data to cgtw database.  """

    module = cgtwq.Database(database).module(module, module_type)
    errors = []
    for i in data:
        assert isinstance(i, RowData)
        try:
            select = module.filter(
                (cgtwq.Field('shot.entity') == i.shot)
                & (cgtwq.Field('pipeline') == i.pipeline))
        except ValueError:
            LOGGER.error('找不到对应条目: 行=%s, 数据库=%s, 镜头号=%s, 流程=%s',
                         i.index, database, i.shot, i.pipeline, )
            errors.append(NoEntry(i))
            continue

        try:
            _apply_on_selection(select, i)
        except ValueError:
            continue
    if errors:
        raise ImportError(errors)
Esempio n. 8
0
def _link(db, shot, assets):
    # type: (cgtwq.Database, Text, Tuple[Text, ...]) -> ...
    if not assets:
        return
    asset_module = db.module("asset", "info")
    shot_module = db.module("shot", "info")
    try:
        matched_assets = asset_module.filter(
            cgtwq.Field("asset.entity").in_(assets), namespace="asset"
        )
        if len(matched_assets) != len(assets):
            LOGGER.warning(
                "some asssets not found: assets=%s match=%d", assets, len(matched_assets)
            )
    except cgtwq.EmptySelection:
        LOGGER.warning("not found assets: %s", assets)
        return
    try:
        shots = shot_module.filter(cgtwq.Field("shot.entity") == shot, namespace="shot")
    except cgtwq.EmptySelection:
        LOGGER.warning("not found shot: %s", shot)
        return
    shots.link.link(*matched_assets)  # type: ignore
    LOGGER.info("link: shot=%s, assets=%s", shot, assets)
Esempio n. 9
0
def test_in_namespace():
    obj1 = cgtwq.Field("key1")
    obj2 = obj1.in_namespace("namespace1")
    assert obj1 == "key1"
    assert obj2 == "namespace1.key1"

    obj3 = cgtwq.Filter("key2", "value2")
    obj4 = obj3.in_namespace("namespace2")
    assert obj3[0] == "key2"
    assert obj4[0] == "namespace2.key2"

    obj5 = cgtwq.FilterList(obj3)
    obj6 = obj5.in_namespace("namespace3")
    assert obj5[0][0] == "key2"
    assert obj6[0][0] == "namespace3.key2"

    obj7 = cgtwq.FilterList.from_arbitrary_args(obj3, obj4)
    obj8 = obj7.in_namespace("namespace4")
    assert obj7[0][0] == "key2"
    assert obj8[0][0] == "namespace4.key2"
Esempio n. 10
0
def dialog_create_dirs():
    """A dialog for create dirs from cgtwq.  """

    folder_input_name = b'输出文件夹'
    database_input_name = b'数据库'
    prefix_input_name = b'镜头名前缀限制'
    panel = nuke.Panel(b'为项目创建文件夹')
    panel.addSingleLineInput(database_input_name, 'proj_qqfc_2017')
    panel.addSingleLineInput(prefix_input_name, '')
    panel.addFilenameSearch(folder_input_name, 'E:/temp')
    confirm = panel.show()
    if not confirm:
        return

    try:
        database = panel.value(database_input_name)
        save_path = panel.value(folder_input_name)
        prefix = panel.value(prefix_input_name)

        for _ in progress(['连接CGTeamWork...', ], '创建文件夹'):
            try:
                select = cgtwq.Database(database)['shot_task'].filter(
                    cgtwq.Field('pipeline') == '合成')
            except cgtwq.IDError as ex:
                nuke.message(utf8('找不到对应条目\n{}'.format(ex)))
                return

        for name in progress(select['shot.shot'], '创建文件夹'):
            if not name or not name.startswith(prefix):
                continue
            _path = os.path.join(save_path, name)
            if not os.path.exists(_path):
                os.makedirs(_path)
        webbrowser.open(save_path)
    except CancelledError:
        LOGGER.debug('用户取消创建文件夹')
Esempio n. 11
0
def main():
    print('{:-^50s}'.format('导出历史 v{}'.format(__version__)))
    wlf.mp_logging.basic_config()
    dummy_app = QApplication(sys.argv)
    filename, _ = QFileDialog.getSaveFileName(
        None, '保存位置',
        'E:/任务历史-{}.xlsx'.format(datetime.now().strftime('%Y%m%d-%H%M')),
        '*.xlsx')
    if not filename:
        return
    client = cgtwq.DesktopClient()
    client.connect()
    pipeline = set(
        client.selection().get_fields("pipeline").column("pipeline"))
    select = client.selection().module.filter(
        cgtwq.Field("pipeline").in_(list(pipeline)), )
    try:
        rows = get_rows(select)
        wb = create_workbook(rows)
        wb.save(filename)
        webbrowser.open(os.path.dirname(filename))
    except IOError:
        LOGGER.error('不能写入文件: %s', filename)
        msgbox('不能写入文件: {}, 请检查文件占用'.format(filename))
Esempio n. 12
0
def test_list_filebox_by_pipeline():
    db = cgtwq.Database("proj_sdktest")
    (pipeline, ) = db.pipeline.filter(cgtwq.Field("entity") == "合成")
    pipeline.module
    filebox_list = db.filebox.list_by_pipeline(pipeline)
    assert filebox_list
Esempio n. 13
0
def _entry():
    return (cgtwq.Database("proj_sdktest").module("shot").filter(
        cgtwq.Field("shot.entity") == "SDKTEST_EP01_01_sc001",
        cgtwq.Field("task.pipeline") == "合成",
    ).to_entry())
Esempio n. 14
0
def test_module_count(module):
    result = module.count(cgtwq.Field("shot.entity").has("_sc001"))
    assert isinstance(result, int)
Esempio n. 15
0
def test_filter_plugin():
    result = cgtwq.PluginMeta.filter()
    for i in result:
        assert isinstance(i, cgtwq.PluginMeta)
    result = cgtwq.PluginMeta.filter(cgtwq.Field("name") == "测试")[0]
    assert isinstance(result, cgtwq.PluginMeta)
Esempio n. 16
0
def _plugin():
    return cgtwq.PluginMeta.filter(cgtwq.Field("name") == "测试")[0]
Esempio n. 17
0
def test_selection_count(select):
    result = select.count(cgtwq.Field("shot.entity").has("_sc001"))
    assert isinstance(result, int)
    assert result > 0
Esempio n. 18
0
def test_selection_distinct(select):
    result = select.distinct(cgtwq.Field("shot.entity").has("_sc001"))
    assert isinstance(result, tuple)
Esempio n. 19
0
def test_database_filebox(database):
    result = database.filebox.filter()
    assert all(isinstance(i, cgtwq.model.FileBoxMeta) for i in result)
    result = database.filebox.filter(cgtwq.Field("title") == "检查MOV")
    result = database.filebox.from_id("271")