Initial commit

This commit is contained in:
Tools
2024-05-04 16:18:49 +02:00
commit 332bbe2c86
32 changed files with 1876 additions and 0 deletions
View File
+21
View File
@@ -0,0 +1,21 @@
import json
import os
from pathlib import Path
from .forge import get_release_file
def get_b3d_addon_dependency(archive: list):
"""From json resources, get all blender dependency and download-it"""
dependency = Path(os.getcwd(), "tests", "dependency.json")
with open(dependency) as f:
data = json.load(f)
b3d_dependency = data['blender']
for key, value in b3d_dependency.items():
if 'prerelease' in value:
prerelease = True
else:
prerelease = False
get_release_file(value[0], value[1], prerelease=prerelease)
archive.append(value[0])
+58
View File
@@ -0,0 +1,58 @@
import os
import bpy
import pathlib
import json
import shutil
def b3d_install_addon():
"""Function to install addon with the blender locally set"""
env_name = 'FOLDER_TEST'
dependency = pathlib.Path(os.environ[env_name], "tests", "dependency.json")
with open(dependency) as f:
data = json.load(f)
b3d_dependency = data['blender']
try:
if not os.environ.get(env_name):
raise KeyError
env_path = pathlib.Path(os.environ[env_name])
if not env_path.exists():
raise FileNotFoundError
for key, value in b3d_dependency.items():
bpy.ops.preferences.addon_install(filepath=f'{env_path}/{value[0]}')
bpy.ops.preferences.addon_enable(module=key)
bpy.ops.wm.save_userpref()
except KeyError:
print(f'Env. "{env_name}" doesn\'t exist')
exit(1)
except FileNotFoundError:
print('Wrong path to execute this Unit Test')
exit(1)
def b3d_install_preset():
"""If the folder preset exist, add all preset inside the moderlab dedicated folder"""
env_name = 'FOLDER_TEST'
try:
if not os.environ.get(env_name):
raise KeyError
path_preset = pathlib.Path(bpy.utils.preset_paths("")[0])
path_locally = pathlib.Path(os.environ.get(env_name), "presets")
if path_locally.exists():
shutil.copytree(path_locally, path_preset.joinpath("moderlab", "props"))
except KeyError:
print(f'Env. "{env_name}" doesn\'t exist')
exit(1)
if __name__ == '__main__':
b3d_install_addon()
b3d_install_preset()
+75
View File
@@ -0,0 +1,75 @@
import docker
import os
import sys
from pathlib import PurePosixPath
from docker.errors import DockerException
from .issue import ContainerErrorTest
from .properties import ContainerObject
class VirtualMachine:
def __init__(self, container: ContainerObject):
self.client = self.start_docker()
self.container = container
self.base_command = self.container.commands
self.clear_containers()
@staticmethod
def start_docker():
"""Generate docker client information"""
try:
client = docker.from_env()
return client
except DockerException:
print('Docker isn\'t start or installed')
exit(1)
def clear_containers(self):
"""Look all docker containers, and remove-it if the task are used with the unit test."""
containers = self.client.containers.list(all=True)
for container in containers:
image_tag = container.image.tags[0]
status = container.status
if image_tag in self.container.ref and status in 'exited':
container.remove()
@staticmethod
def workspace():
"""Define the workspace folder"""
if os.environ.get('GITHUB_WORKSPACE'):
return os.environ['GITHUB_WORKSPACE']
else:
return os.getcwd()
def launch_unit_test(self, tests: list[str]):
"""Execute a docker container to start unit test dedicated"""
if tests is None:
unit_test = os.listdir(self.workspace())
else:
if type(tests) is not list:
tests = [tests]
unit_test = tests
try:
for test in unit_test:
print(f'Launch unit test "{test}"')
cmds = self.base_command + [f'{PurePosixPath(self.container.local_folder, "tests", "unit_test", test)}']
docker_test = self.client.containers.run(self.container.ref, command=cmds,
volumes=self.container.volumes, privileged=True,
environment=self.container.environments, detach=True,
name=test, tty=True)
exit_docker = docker_test.wait()
if exit_docker['StatusCode'] != 0:
print(f'Container error "{exit_docker["StatusCode"]}".\n\t'
f'Show log : \n\t'
f'{docker_test.logs()}')
raise ContainerErrorTest
except ContainerErrorTest as exception:
print(f'{exception.__doc__}')
sys.exit(1)
+51
View File
@@ -0,0 +1,51 @@
import os
import requests
from pathlib import Path
from github import Github
def read_token():
token_file = Path(os.getcwd(), 'tests', 'token.txt')
if token_file.exists():
with open(token_file, 'r') as f:
token = f.read()
else:
token = os.environ.get('token')
return token
def get_release_file(filename: str, repo: str, prerelease: bool = False):
"""Download from Github the latest release files"""
g = Github(read_token())
repository = g.get_repo(repo)
all_releases = repository.get_releases()
assets_release = None
for release in all_releases:
print(f'Get "{filename}", with a prerelease value to "{prerelease}" ')
if release.prerelease is prerelease:
assets_release = release.get_assets()
break
else:
assets_release = release.get_assets()
break
for file in assets_release:
if file.name == filename:
dl_file(file.url, file.name)
def dl_file(url: str, filename: str):
"""From specific asset, download it"""
headers = {
'Authorization': f'token {read_token()}',
'Accept': 'application/octet-stream'
}
session = requests.Session()
link = session.get(url, stream=True, headers=headers)
with open(filename, 'wb') as f:
for chunk in link.iter_content(1024*1024):
f.write(chunk)
+12
View File
@@ -0,0 +1,12 @@
class Archive(Exception):
def __init__(self, source):
self.source = source
class ArchiveFolderSourceNotFound(Archive):
def __str__(self):
return f'Can\'t find the folder source "{self.source}".'
class ContainerErrorTest(Exception):
""" Failed to generate the test """
+47
View File
@@ -0,0 +1,47 @@
import os
import pathlib
import sys
import zipfile
from .issue import ArchiveFolderSourceNotFound
def generate_archive(list_clean: list, name: str):
"""From the plugin folder, generate an archive to test his code"""
archive_path_source = pathlib.Path(os.getcwd(), name)
archive_filename = pathlib.Path(os.getcwd(), f"{name}.zip")
archive_file_generate = zipfile.ZipFile(archive_filename, 'w')
try:
# Check if all default folder are present.
if not archive_path_source.exists():
raise ArchiveFolderSourceNotFound(source=name)
for directory, subdir, files in os.walk(archive_path_source):
if '__pycache__' not in directory:
for file in files:
append_file = pathlib.Path(directory, file)
included_file = pathlib.Path(os.path.relpath(append_file))
archive_file_generate.write(append_file, included_file)
archive_file_generate.close()
list_clean.append(archive_filename)
except BaseException as e:
print(f'Generate Archive error : \n\t{e}')
sys.exit(1)
def ordering_test_file():
unit_test_folder = pathlib.Path(os.getcwd(), "tests", "unit_test")
unit_test = os.listdir(unit_test_folder)
unit_test_b3d = []
unit_test_ue = []
for test in unit_test:
if '_ue_' in test:
unit_test_ue.append(test)
elif '_b3d_' in test:
unit_test_b3d.append(test)
return {'blender': unit_test_b3d, 'unreal': unit_test_ue}
+69
View File
@@ -0,0 +1,69 @@
import os
from pathlib import PurePosixPath
class ContainerObject(object):
"""All data request to launch one dedicated container"""
def __init__(self, name: str, image: str, tag: str = None):
self.label: str = name.lower()
self.image: str = image
self.tag: str = self.set_tag(tag)
self.local_folder: str = ''
self.volumes: list[str] = self.set_volumes()
self.environments: list[str] = self.set_environments()
self.commands: list[str] = self.set_commands()
self.ref = f'{self.image}:{self.tag}'
def set_tag(self, tag):
"""Determine the tag use with the docker image call"""
if 'blender' in self.label:
if tag is not None:
return tag
else:
return 'latest'
elif 'unreal' in self.label:
if tag is not None:
return tag
else:
return 'dev-slim-4.27.2'
else:
return None
def set_volumes(self):
"""Define folder/path with mount with each docker container"""
if 'blender' in self.label:
self.local_folder = '/addon_moderlab'
elif 'unreal' in self.label:
self.local_folder = '/project'
else:
return None
return [f'{self.workspace()}:{self.local_folder}']
def set_environments(self):
"""Add environment variable start with the docker container"""
if 'blender' in self.label:
return [f'FOLDER_TEST={self.local_folder}']
else:
return []
def set_commands(self):
"""Write all commands execute on the docker container start"""
cmds = ['/bin/sh']
if 'blender' in self.label:
cmds.append(str(PurePosixPath(self.local_folder, "tests", "launch_test_b3d.sh")))
else:
cmds.append(str(PurePosixPath(self.local_folder, "tests", "launch_test_ue.sh")))
cmds.append(str(PurePosixPath(self.local_folder, "tests", "unreal_sample", "empty_project",
"EmptyProject.uproject")))
return cmds
@staticmethod
def workspace():
"""Define the workspace folder"""
if os.environ.get('GITHUB_WORKSPACE'):
return os.environ['GITHUB_WORKSPACE']
else:
return os.getcwd()