diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3bd4a12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Byte-compiled / optimized / DLL files +*.py[cod] +*.pyd[cod] +*.so[cod] + + +# PyCharm project files +.idea/ + +# Vim / Notepad++ temp files +*~ +.*/ +*.egg-info +# PyInstaller output +build/ +dist/ +*.spec + +# PyBuilder output +.build/ +result/ + +# Coverage output +.coverage +/venv/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..84f5c70 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +rayvision_blender +================== + +[![](https://img.shields.io/badge/pypi%20package-1.0.0-green)](https://pypi.org/project/rayvision-katana/) +[![](https://img.shields.io/badge/docs--%E4%B8%AD%E6%96%87%E7%AE%80%E4%BD%93-latest-green)](https://renderbus.readthedocs.io/zh/latest) +[![](https://img.shields.io/badge/docs--English-latest-green)](https://renderbus.readthedocs.io/en/latest) +[![](https://img.shields.io/badge/license-Apache%202-blue)](http://www.apache.org/licenses/LICENSE-2.0.txt) +![](https://img.shields.io/badge/python-2.7.10+%20%7C%203.6%20%7C%203.7-blue) +![](https://img.shields.io/badge/platform-windows-lightgrey) \ No newline at end of file diff --git a/help/examples/blender_demo.py b/help/examples/blender_demo.py new file mode 100644 index 0000000..b8c3300 --- /dev/null +++ b/help/examples/blender_demo.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +"""blender render demo.""" + +from rayvision_api.core import RayvisionAPI +from rayvision_api.task.check import RayvisionCheck +from rayvision_api.utils import update_task_info, append_to_task, append_to_upload +from rayvision_blender.analyze_blender import AnalyzeBlender +from rayvision_sync.download import RayvisionDownload +from rayvision_sync.upload import RayvisionUpload + +# API Parameter +render_para = { + "domain": "task.renderbus.com", + "platform": "2", + "access_id": "xxxx", + "access_key": "xxxx", +} + +api = RayvisionAPI(access_id=render_para['access_id'], + access_key=render_para['access_key'], + domain=render_para['domain'], + platform=render_para['platform']) + +# Step1:Analyze CG File +analyze_info = { + "cg_file": r"D:\houdini\cg_file\PRAM RENDER 1.blend", + "workspace": "c:/workspace", + "software_version": "2.81", + "project_name": "Project1", + "plugin_config": {} +} +analyze_obj = AnalyzeBlender(**analyze_info) +analyze_obj.analyse(exe_path=r"C:\Program Files (x86)\Blender Foundation\Blender\blender.exe") + +# step2:Add some custom parameters, or update the original parameter value +update_task = { + "pre_frames": "100", + "stop_after_test": "1", + "hardwareConfigId": "5", +} +update_task_info(update_task, analyze_obj.task_json) + +custom_info_to_task = {} +append_to_task(custom_info_to_task, analyze_obj.task_json) + +# User-defined UPLOAD.JSON file path +upload_json_path = r"D:\blender\upload.json" + +custom_info_to_upload = [ + r"D:\houdini\cg_file\PRAM RENDER 1.blend" +] + +append_to_upload(custom_info_to_upload, upload_json_path) + +# step3:Check json files +check_obj = RayvisionCheck(api, analyze_obj) +task_id = check_obj.execute(analyze_obj.task_json, analyze_obj.upload_json) + +# Step4:Transmission +""" +There are two ways to upload the transmission: +Upload_method: 1:upload four json files and upload the resource file according to upload.json; + 2:json files and resources are uploaded separately; +""" +CONFIG_PATH = { + "tips_json_path": analyze_obj.tips_json, + "task_json_path": analyze_obj.task_json, + "asset_json_path": analyze_obj.asset_json, +} +upload_obj = RayvisionUpload(api, automatic_line=True) +""" +The default of the test demo is to upload json and resource files at the same time, +and users can choose their own upload method according to the actual situation. +""" +upload_obj.upload_asset(upload_json_path=upload_json_path) +upload_obj.upload_config(str(task_id), list(CONFIG_PATH.values())) + +# Step5:Submit Task +api.submit(int(task_id)) + +# Step6:Download +download = RayvisionDownload(api) +# All complete before the automatic start of uniform download. +# download.auto_download_after_task_completed([task_id]) +# Poll download (automatic download for each completed frame) +download.auto_download([int(task_id)]) diff --git a/help/examples/only_analyze_demo.py b/help/examples/only_analyze_demo.py new file mode 100644 index 0000000..4d5b9c6 --- /dev/null +++ b/help/examples/only_analyze_demo.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +"""only analyze blender""" + +from rayvision_blender.analyze_blender import AnalyzeBlender + +analyze_info = { + "cg_file": r"D:\houdini\cg_file\PRAM RENDER 1.blend", + "workspace": "c:/workspace", + "software_version": "2.78", + "project_name": "Project1", + "plugin_config": {} +} + +AnalyzeBlender(**analyze_info).analyse(exe_path=r"C:\Program Files (x86)\Blender Foundation\Blender\blender.exe") \ No newline at end of file diff --git a/init_pycharm_setup.cmd b/init_pycharm_setup.cmd new file mode 100644 index 0000000..2ae8a8a --- /dev/null +++ b/init_pycharm_setup.cmd @@ -0,0 +1,9 @@ +::We need to initialize all the environments when we start the new project. +@echo off +set INDEX_URL=https://mirrors.aliyun.com/pypi/simple +set URL_HOST=mirrors.aliyun.com +call %~dp0venv\Scripts\activate.bat +call easy_install -i %INDEX_URL% --upgrade pip +call pip install -i %INDEX_URL% --trusted-host %URL_HOST% tox pre-commit +call pre-commit install +call pip install -i %INDEX_URL% %URL_HOST% -r %~dp0requirements.txt -r %~dp0dev_requirements.txt diff --git a/rayvision_blender/__init__.py b/rayvision_blender/__init__.py new file mode 100644 index 0000000..a9a1b37 --- /dev/null +++ b/rayvision_blender/__init__.py @@ -0,0 +1,16 @@ +"""A Python-based API for Using Renderbus cloud rendering houdini service.""" + +# pylint: disable=import-error +from pkg_resources import DistributionNotFound, get_distribution + +from rayvision_blender.constants import PACKAGE_NAME +from rayvision_log import init_logger + +# Initialize the logger. +init_logger(PACKAGE_NAME) + +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + # Package is not installed. + __version__ = '0.0.0-dev.1' diff --git a/rayvision_blender/analyze_blender.py b/rayvision_blender/analyze_blender.py new file mode 100644 index 0000000..c20c968 --- /dev/null +++ b/rayvision_blender/analyze_blender.py @@ -0,0 +1,234 @@ +# -*- coding: utf-8 -*- +"""A interface for blender.""" + +# Import built-in models +from __future__ import print_function +from __future__ import unicode_literals + +import logging +import os +import sys +import time +from builtins import str + +from rayvision_blender.constants import PACKAGE_NAME +from rayvision_log import init_logger +from rayvision_utils import constants +from rayvision_utils import utils +from rayvision_utils.cmd import Cmd +from rayvision_utils.exception import tips_code +from rayvision_utils.exception.exception import AnalyseFailError, CGFileNotExistsError + +VERSION = sys.version_info[0] + + +class AnalyzeBlender(object): + def __init__(self, cg_file, software_version, project_name, + plugin_config, render_software="Blender", render_layer_type="0", + input_project_path=None, local_os=None, workspace=None, + custom_exe_path=None, + platform="2", + logger=None, + log_folder=None, + log_name=None, + log_level="DEBUG" + ): + """Initialize and examine the analysis information. + + Args: + cg_file (str): Scene file path. + software_version (str): Software version. + project_name (str): The project name. + plugin_config (dict): Plugin information. + render_software (str): Software name, CINEMA 4D by default. + render_layer_type (str): 0 is render layer, 1 is render setup. + input_project_path (str): The working path of the scenario. + local_os (str): System name, linux or windows. + workspace (str): Analysis out of the result file storage path. + custom_exe_path (str): Customize the exe path for the analysis. + platform (str): Platform num. + logger (object, optional): Custom log object. + log_folder (str, optional): Custom log save location. + log_name (str, optional): Custom log file name. + log_level (string): Set log level, example: "DEBUG","INFO","WARNING","ERROR". + """ + self.logger = logger + if not self.logger: + init_logger(PACKAGE_NAME, log_folder, log_name) + self.logger = logging.getLogger(__name__) + self.logger.setLevel(level=log_level.upper()) + + self.check_path(cg_file) + self.cg_file = cg_file + + self.render_software = render_software + self.input_project_path = input_project_path or "" + self.render_layer_type = render_layer_type + self.software_version = software_version + self.project_name = project_name + self.plugin_config = plugin_config + + self.local_os = local_os if local_os else self.check_local_os() + self.tmp_mark = str(int(time.time())) + workspace = os.path.join(self.check_workspace(workspace), + self.tmp_mark) + if not os.path.exists(workspace): + os.makedirs(workspace) + self.workspace = workspace + + if custom_exe_path: + self.check_path(custom_exe_path) + self.custom_exe_path = custom_exe_path + + self.analyze_script_path = os.path.normpath(os.path.join( + os.path.dirname(__file__).replace("\\", "/"), + "tool", "check.py")) + + self.check_path(self.analyze_script_path) + + self.platform = platform + + self.task_json = os.path.join(workspace, "task.json") + self.tips_json = os.path.join(workspace, "tips.json") + self.asset_json = os.path.join(workspace, "asset.json") + self.upload_json = os.path.join(workspace, "upload.json") + self.analyse_log_path = os.path.join(workspace, "analyze.log") + self.tips_info = {} + self.task_info = {} + self.asset_info = {} + self.upload_info = {} + + @staticmethod + def check_path(tmp_path): + """Check if the path exists.""" + if not os.path.exists(tmp_path): + raise CGFileNotExistsError("{} is not found".format(tmp_path)) + + def add_tip(self, code, info): + """Add error message. + + Args: + code (str): error code. + info (str or list): Error message description. + + """ + if isinstance(info, str): + self.tips_info[code] = [info] + elif isinstance(info, list): + self.tips_info[code] = info + else: + raise Exception("info must a list or str.") + + def save_tips(self): + """Write the error message to tips.json.""" + utils.json_save(self.tips_json, self.tips_info, ensure_ascii=False) + + @staticmethod + def check_local_os(): + """Check the system name. + + Args: + local_os (str): System name. + + Returns: + str + + """ + if "win" in sys.platform.lower(): + local_os = "windows" + else: + local_os = "linux" + + return local_os + + def check_workspace(self, workspace): + """Check the working environment. + + Args: + workspace (str): Workspace path. + + Returns: + str: Workspace path. + + """ + if not workspace: + if self.local_os == "windows": + workspace = os.path.join(os.environ["USERPROFILE"], "renderfarm_sdk") + else: + workspace = os.path.join(os.environ["HOME"], "renderfarm_sdk") + else: + self.check_path(workspace) + + return workspace + + def write_task_json(self): + """The initialization task.json.""" + constants.TASK_INFO["task_info"]["input_cg_file"] = self.cg_file.replace("\\", "/") + constants.TASK_INFO["task_info"]["input_project_path"] = self.input_project_path.replace("\\", "/") + constants.TASK_INFO["task_info"]["render_layer_type"] = self.render_layer_type + constants.TASK_INFO["task_info"]["project_name"] = self.project_name + constants.TASK_INFO["task_info"]["cg_id"] = "2007" + constants.TASK_INFO["task_info"]["os_name"] = "1" if self.local_os == "windows" else "0" + constants.TASK_INFO["task_info"]["platform"] = self.platform + constants.TASK_INFO["software_config"] = { + "plugins": self.plugin_config, + "cg_version": self.software_version, + "cg_name": self.render_software + } + utils.json_save(self.task_json, constants.TASK_INFO) + + def check_result(self): + """Check that the analysis results file exists.""" + for json_path in [self.task_json, self.asset_json, + self.tips_json]: + if not os.path.exists(json_path): + msg = "Json file is not generated: {0}".format(json_path) + return False, msg + return True, None + + def analyse(self, exe_path): + """Build a cmd command to perform an analysis scenario. + + Args: + exe_path (bool): Do you not generate an upload,json file. + + Raises: + AnalyseFailError: Analysis scenario failed. + + """ + if not os.path.exists(exe_path): + self.logger.error("Please enter the blender software absolute path") + raise AnalyseFailError + + self.write_task_json() + + if self.local_os == 'windows': + cmd = '"{exe_path}" -b "{cg_file}" -P "{run_py}" -- "{task_json}" "{tips_json}" "{asset_json}"'.format( + exe_path=exe_path, + cg_file=self.cg_file, + run_py=self.analyze_script_path, + task_json=self.task_json, + tips_json=self.tips_json, + asset_json=self.asset_json, + ) + else: + self.logger.error("blender does not support linux rendering") + + self.logger.debug(cmd) + code, _, _ = Cmd.run(cmd, shell=True) + if code not in [0, 1]: + self.add_tip(tips_code.UNKNOW_ERR, "") + self.save_tips() + raise AnalyseFailError + + # Determine whether the analysis is successful by + # determining whether a json file is generated. + status, msg = self.check_result() + if status is False: + self.add_tip(tips_code.UNKNOW_ERR, msg) + self.save_tips() + raise AnalyseFailError(msg) + + self.tips_info = utils.json_load(self.tips_json) + self.asset_info = utils.json_load(self.asset_json) + self.task_info = utils.json_load(self.task_json) diff --git a/rayvision_blender/constants.py b/rayvision_blender/constants.py new file mode 100644 index 0000000..a608350 --- /dev/null +++ b/rayvision_blender/constants.py @@ -0,0 +1,2 @@ +"""Constant information about the Blender.""" +PACKAGE_NAME = 'rayvision_blender' diff --git a/rayvision_blender/tests/__init__.py b/rayvision_blender/tests/__init__.py new file mode 100644 index 0000000..732a2de --- /dev/null +++ b/rayvision_blender/tests/__init__.py @@ -0,0 +1 @@ +"""Test.""" diff --git a/rayvision_blender/tests/conftest.py b/rayvision_blender/tests/conftest.py new file mode 100644 index 0000000..df02419 --- /dev/null +++ b/rayvision_blender/tests/conftest.py @@ -0,0 +1,66 @@ +"""The plugin of the pytest. + +The pytest plugin hooks do not need to be imported into any test code, it will +load automatically when running pytest. + +References: + https://docs.pytest.org/en/2.7.3/plugins.html + +""" + +# pylint: disable=import-error +import os +import sys + +import pytest + +from rayvision_utils.cmd import Cmd + + +@pytest.fixture() +def user_info(): + """Get user info.""" + return { + "domain": "task.renderbus.com", + "platform": "2", + "access_id": "df6d1d6s3dc56ds6", + "access_key": "fa5sd565as2fd65", + "local_os": 'windows', + "workspace": "c:/workspace", + "render_software": "Blender", + "software_version": "2.78", + "project_name": "Project1", + "plugin_config": {}, + } + + +@pytest.fixture() +def cg_file_c(tmpdir): + """Get render cg file.""" + return { + 'cg_file': str(tmpdir.join('ybt.blender')) + } + + +@pytest.fixture() +def handle_cmd(): + """Get a Cmd object.""" + return Cmd() + + +@pytest.fixture() +def check(task): + """Create an RayvisionCheck object.""" + from rayvision_api.task.check import RayvisionCheck + return RayvisionCheck(task) + + +@pytest.fixture() +def blender(tmpdir): + """Create an blender object.""" + from rayvision_blender.analyze_blender import AnalyzeBlender + if "win" in sys.platform.lower(): + os.environ["USERPROFILE"] = str(tmpdir) + else: + os.environ["HOME"] = str(tmpdir) + return AnalyzeBlender(str(tmpdir), "2.78", "Project1", {}) diff --git a/rayvision_blender/tests/test_analyse.py b/rayvision_blender/tests/test_analyse.py new file mode 100644 index 0000000..6d669e4 --- /dev/null +++ b/rayvision_blender/tests/test_analyse.py @@ -0,0 +1,10 @@ +"""Test rayvision_blender.analyse_blender model.""" +from unittest import mock + + +def test_check_local_os(blender): + """Test print_info this interface.""" + mock_return = "win" + blender.check_local_os = mock.Mock(return_value=mock_return) + result = blender.check_local_os() + assert result == "win" diff --git a/rayvision_blender/tests/test_utils.py b/rayvision_blender/tests/test_utils.py new file mode 100644 index 0000000..b2c20a6 --- /dev/null +++ b/rayvision_blender/tests/test_utils.py @@ -0,0 +1,62 @@ +# -*- coding:utf-8 -*- +"""Test rayvision_blender.utils functions.""" + +# pylint: disable=import-error +import pytest + +from rayvision_blender import utils + + +@pytest.mark.parametrize("message, py_version", [ + ("test to encode", 3), +]) +def test_get_encode(message, py_version): + """Test get_encode, we can get a expected result.""" + assert utils.get_encode(message, py_version) == "unicode" + + +@pytest.mark.parametrize("message, py_version", [ + ("test str to unicode", 3), +]) +def test_str_to_unicode(message, py_version): + """Test str_to_unicode, we can get a expected type.""" + result = utils.str_to_unicode(message, py_version) + assert isinstance(result, str) + + +@pytest.mark.parametrize("str1, py_version", [ + ("test unicode to str", 3), +]) +def test_unicode_to_str(str1, py_version): + """Test str_to_unicode, we can get a expected type.""" + result = utils.unicode_to_str(str1, py_version=py_version) + assert isinstance(result, str) + + +@pytest.mark.parametrize("str1, py_version, str_decode", [ + (b"test unicode to str", 3, 'utf-8'), +]) +def test_bytes_to_str(str1, py_version, str_decode): + """Test str_to_unicode, we can get a expected type.""" + result = utils.bytes_to_str(str1, py_version=py_version, + str_decode=str_decode) + assert isinstance(result, str) + + +@pytest.mark.parametrize("encode_str, py_version", [ + ("to gbk", 3), +]) +def test_to_gbk(encode_str, py_version): + """Test str_to_unicode, we can get a expected type.""" + result = utils.to_gbk(encode_str, py_version) + assert isinstance(result, str) + + +@pytest.mark.parametrize("path", [ + "D:/work/render/19183793/max/d/Work/c05.txt", + "D:\\work/render/19183793\\max/d/Work/c05.txt" +]) +def test_convert_path(path): + """Test get_encode, we can get a expected result.""" + result_path = utils.convert_path(path) + assert result_path == r"/D/work/render/19183793/max/d/Work/c05.txt" diff --git a/rayvision_blender/tool/check.py b/rayvision_blender/tool/check.py new file mode 100644 index 0000000..aa41e06 --- /dev/null +++ b/rayvision_blender/tool/check.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- coding=utf-8 -*- +#.A ---- customer cannot assign folder +#.B ---- customer can assign folder +#.d ---- the item is a folder +#.f ---- the item is a file + +import bpy, os, sys, json, socket + +def abc(filepath,tips_json,asset_json): + if not os.path.exists(filepath): + return False + + #output scnens info + for scene in bpy.data.scenes: + start = bpy.context.scene.frame_start + print('frame_start:'+ str(start)) + end = bpy.context.scene.frame_end + print('frame_end:'+ str(end)) + frame_step = bpy.context.scene.frame_step + print('frame_step:'+ str(frame_step)) + width = bpy.context.scene.render.resolution_x + print('width:'+ str(width)) + + height = bpy.context.scene.render.resolution_y + print('height:'+ str(height)) + Format = bpy.context.scene.render.image_settings.file_format + print('Format:'+ str(Format)) + scene_name = bpy.data.scenes.keys() + print('scene_name:'+ str(scene_name)) + + camera_name = bpy.context.scene.camera + print('camera_name:'+ str(camera_name)) + + Output_path = bpy.context.scene.render.filepath + print('Output_path:'+ str(Output_path)) + common_dict={} + common_dict['frames']=str(start)+'-'+str(end)+'['+str(frame_step)+']' + common_dict['width']=str(width) + common_dict['height']=str(height) + common_dict['Render_Format']=str(Format) + common_dict['scene_name']=scene_name + common_dict['camera_name']=str(camera_name) + common_dict['Output_path']=str(Output_path) + break + + with open(filepath, 'r') as json_file: + #if 'common' not in task_json_dict['scene_info']: + #task_json_dict['scene_info']['common'] = {} + task_json_dict = json.load(json_file) + if 'scene_info' not in task_json_dict: + task_json_dict['scene_info'] = {} + + if 'common' not in task_json_dict['scene_info']: + task_json_dict['scene_info']['common'] = {} + + task_json_dict['scene_info']['common'] = common_dict + with open(filepath, 'w') as json_file: + json.dump(task_json_dict, json_file, indent=4, ensure_ascii=False) + with open(tips_json, 'w') as tips_json_temp: + tips_json_dict={} + json.dump(tips_json_dict, tips_json_temp, indent=4, ensure_ascii=False) + with open(asset_json, 'w') as asset_json_temp: + asset_json_dict={} + json.dump(asset_json_dict, asset_json_temp, indent=4, ensure_ascii=False) + + #output_Movie_error + Movie = {'AVI_JPEG','AVI_RAW','FRAMESERVER','FFMPEG','H264','THEORA','XVID'} + if str(Format) in Movie: + print("Format:" + str(Format)) + with open(tips_json, 'w') as tips_json_temp: + if 'error_info' not in tips_json_dict: + error_dict = {} + tips_json_dict['46000'] =[] + json.dump(tips_json_dict, tips_json_temp, indent=4, ensure_ascii=False) + return + #frame_step_!=1_warning + if str(frame_step) != ('1'): + with open(tips_json, 'w') as tips_json_temp: + if 'error_info' not in tips_json_dict: + error_dict = {} + tips_json_dict['46001'] =[] + json.dump(tips_json_dict, tips_json_temp, indent=4, ensure_ascii=False) + return + #Eevee_render_error + myname = socket.getfqdn(socket.gethostname( )) + myaddr = socket.gethostbyname(myname) + if myname.startswith('GPU'): + pass + else: + for scene in bpy.data.scenes: + if scene.render.engine == ('BLENDER_EEVEE'): + with open(tips_json, 'w') as tips_json_temp: + if 'error_info' not in tips_json_dict: + error_dict = {} + tips_json_dict['46002'] =[] + json.dump(tips_json_dict, tips_json_temp, indent=4, ensure_ascii=False) + return + #No_Camera_error + if str(camera_name) == 'None': + with open(tips_json, 'w') as tips_json_temp: + if 'error_info' not in tips_json_dict: + error_dict = {} + tips_json_dict['46003'] =[] + json.dump(tips_json_dict, tips_json_temp, indent=4, ensure_ascii=False) + return + +print("-------------.." +sys.argv[6]) +print("-------------.." +sys.argv[7]) +print("-------------.." +sys.argv[8]) +abc(sys.argv[6],sys.argv[7],sys.argv[8]) + +base_path = os.path.split(sys.argv[6])[0] +analyze_flag_file = os.path.join(base_path, "analyze_sucess") +with open(analyze_flag_file, "w"): + pass diff --git a/rayvision_blender/utils.py b/rayvision_blender/utils.py new file mode 100644 index 0000000..e367e57 --- /dev/null +++ b/rayvision_blender/utils.py @@ -0,0 +1,140 @@ +"""Common method for rayvision_blender API.""" + +import sys + + +def get_encode(encode_str, py_version=3): + """Get the encoding of the string decoding. + + Args: + encode_str (str, unicode): String. + py_version (int): Python version, default is 3. + + Returns: + str: Coding. + + """ + if ((py_version == 2 and isinstance(encode_str, str)) or ( + py_version == 3 and isinstance(encode_str, str))): + encode = "unicode" + else: + for code in ["utf-8", sys.getfilesystemencoding(), "gb18030", + "ascii", "gbk", "gb2312"]: + try: + encode_str.decode(code, 'ignore') + return code + except UnicodeDecodeError: + pass + encode = 'utf-8' + return encode + + +def str_to_unicode(encode_str, py_version=3): + """Get the encoding of the string decoding. + + Args: + encode_str (str, unicode): String. + py_version (int): Python version, default is 3. + + Returns: + str: String. + + """ + if (encode_str is None or encode_str == "" or encode_str == 'Null' or + encode_str == 'null'): + encode_str = "" + elif ((py_version == 2 and isinstance(encode_str, str)) or ( + py_version == 3 and isinstance(encode_str, str))): + pass + else: + code = get_encode(encode_str) + encode_str = encode_str.decode(code, 'ignore') + return encode_str + + +def unicode_to_str(str1, logger=None, str_encode='system', py_version=3): + """Unicode encoded string converted to str.""" + if str1 is None or str1 == "" or str1 == 'Null' or str1 == 'null': + str1 = "" + elif ((py_version == 2 and isinstance(str1, str)) or ( + py_version == 3 and isinstance(str1, str))): + try: + if str_encode.lower() == 'system': + str1 = str1.encode(sys.getfilesystemencoding(), 'ignore') + elif str_encode.lower() == 'utf-8': + str1 = str1.encode('utf-8', 'ignore') + elif str_encode.lower() == 'gbk': + str1 = str1.encode('gbk', 'ignore') + else: + str1 = str1.encode(str_encode, 'ignore') + except UnicodeDecodeError as err_message: + if logger: + logger.info('[err]unicode_to_str:encode %s to %s failed', + str1, str_encode) + logger.info(str(err_message)) + elif ((py_version == 2 and isinstance(str1, str)) or ( + py_version == 3 and isinstance(str1, bytes))): + pass + else: + if logger: + logger.info('%s is not unicode ', str1) + return str(str1) + + +def bytes_to_str(str1, logger=None, str_decode='default', py_version=3): + """Bytes encoded string converted to str.""" + if not ((py_version == 2 and isinstance(str1, str)) or + (py_version == 3 and isinstance(str1, str))): + try: + if str_decode != 'default': + str1 = str1.decode(str_decode.lower(), 'ignore') + else: + try: + str1 = str1.decode('utf-8', 'ignore') + except UnicodeDecodeError: + try: + str1 = str1.decode('gbk', 'ignore') + except UnicodeDecodeError: + str1 = str1.decode(sys.getfilesystemencoding(), + 'ignore') + except UnicodeDecodeError as err_message: + if logger: + logger.info('[err]bytes_to_str:decode %s to str failed', str1) + logger.info(str(err_message)) + return str1 + + +def to_gbk(encode_str, py_version): + """Convert string to gbk code.""" + if ((py_version == 2 and isinstance(encode_str, str + )) or (py_version == 3 and + isinstance(encode_str, str))): + pass + else: + code = get_encode(encode_str) + encode_str = encode_str.decode(code).encode('GBK', 'ignore') + return encode_str + + +def convert_path(path): + """Convert to the path the server will accept. + + Args: + path (str): Local file path. + e.g.: + "D:/work/render/19183793/max/d/Work/c05/112132P-embery.jpg" + + Returns: + str: Path to the server. + e.g.: + "/D/work/render/19183793/max/d/Work/c05/112132P-embery.jpg" + + """ + lower_path = path.replace('\\', '/') + if lower_path[1] == ":": + path_lower = lower_path.replace(":", "") + path_server = "/" + path_lower + else: + path_server = lower_path[1:] + + return path_server diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..957ae09 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +rayvision_log>=0.3.3 +rayvision_utils>=1.0.1 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..3c6e79c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..8c5297d --- /dev/null +++ b/setup.py @@ -0,0 +1,35 @@ +"""Describe our module distribution to Distutils.""" + +# Import third-party modules +from setuptools import find_packages +from setuptools import setup + + +def parse_requirements(filename): + with open(filename, 'r') as f: + for line in f: + yield line.strip() + + +setup( + name='rayvision_blender', + author='Shenzhen Rayvision Technology Co., Ltd', + author_email='developer@rayvision.com', + url='https://github.com/renderbus/rayvision_blender', + package_dir={'': '.'}, + packages=find_packages('.'), + description='A Python-based API for Using Renderbus cloud rendering service.', + entry_points={}, + install_requires=list(parse_requirements("requirements.txt")), + package_data={ + 'rayvision_blender': ["./tool/*"], + }, + classifiers=[ + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + ], + use_scm_version=True, + setup_requires=['setuptools_scm'], +) +