def init(root=None, host=None, extension_paths=None, logging=None): '''Initialize Construct''' global _initialized if _initialized: raise RuntimeError('Construct has already been initialized.') # Load configuration global config_file config_file = os.environ.get('CONSTRUCT_CONFIG') if config_file: with open(config_file, 'r') as f: config_data = yaml.safe_load(f.read()) config.update(config_data) # Configure logging dictConfig(logging or config.get('LOGGING', DEFAULT_LOGGING)) if config_file: _log.debug('Loaded config: %s' % config_file) else: _log.debug('Using default config') # Setup fsfs entry factory _log.debug('Configuring fsfs...') from construct.models import factory from construct.constants import FSFS_DATA_ROOT, FSFS_DATA_FILE fsfs.set_entry_factory(factory) fsfs.set_data_root(FSFS_DATA_ROOT) fsfs.set_data_file(FSFS_DATA_FILE) # Setup initial context global _context _log.debug('Setting initial context...') _context = Context.from_env() if root: _log.debug('Setting root to %s' % root) _context.root = unipath(root) elif 'CONSTRUCT_ROOT' in os.environ: _log.debug('Setting root to %s' % os.environ['CONSTRUCT_ROOT']) _context.root = unipath(os.environ['CONSTRUCT_ROOT']) else: _log.debug('Setting root to %s' % config['ROOT']) _context.root = unipath(config['ROOT']) if host: _context.host = host # Register builtins from construct.builtins import Builtins extensions.register(Builtins) # Discover extensions _log.debug('Discovering extensions...') extension_paths = extension_paths or [] extensions.discover(*extension_paths) _log.debug('Initialized!') _initialized = True
def stage_template(ctx, name, entry, include_files): '''Stage template data''' templates_path = unipath(ctx.project.data.path, 'templates') template_path = unipath(templates_path, name) template_item = types.Namespace( entry=entry, name=name, path=template_path, include_files=include_files, ) return template_item
def save_next_workfile(ctx, publish_items): '''Save the next workfile.''' host = get_host() scene = publish_items['scene'] # Get the next version number for the original scene name if ctx.workspace: next_version = ctx.workspace.get_next_version( scene['scene_data']['name'], scene['scene_data']['ext'], ) else: next_version = int(scene['scene_data']['version']) + 1 # Construct the next scene_file path next_scene_name = scene['scene_file'].replace( scene['scene_data']['version'], '{:0>3d}'.format(next_version), ) next_scene_file = utils.unipath(scene['scene_root'], next_scene_name) # If the path already exists Abort... if os.path.isfile(next_scene_file): raise Abort('Next scene file already exists. Reopening workfile.') # Copy the original scene file to the next version shutil.copy2(scene['scene_file'], next_scene_file) return next_scene_file
def stage_scene(ctx): '''Stage the current work file as a publish item''' path_template = get_path_template('workspace_file') scene_data = path_template.parse(str(ctx.file)) file_type = get_file_type(str(ctx.file)) if file_type: file_type = file_type[0] else: file_type = scene_data['ext'][1:] publish_path = get_path_template('publish').format( dict( task=str(ctx.task), file_type=file_type, )) publish_file = get_path_template('publish_file').format(scene_data) publish_item = dict( type='scene', task=ctx.task, scene_data=scene_data, scene_root=os.path.dirname(str(ctx.file)), scene_file=str(ctx.file), publish_root=publish_path, publish_file=utils.unipath(publish_path, publish_file), ) return {'scene': publish_item}
def path(resource): '''Get a resources filepath''' filepath = resource.lstrip(':/') for ext in EXTENSIONS: potential_path = unipath(THIS_PATH, filepath + ext) if os.path.isfile(potential_path): return potential_path raise ResourceError('Could not find resource: ' + resource)
def stage_task(parent, type, name=None, template=None): '''Stage task for creation''' name = name or type return dict( name=name, path=unipath(parent.path, name), tags=['task', type], template=api.get_template(template, 'task'), )
def build_filename(workspace, name, version, ext): '''Builds the full save path''' task = workspace.parent() path_template = get_path_template('workspace_file') filename = path_template.format( dict(task=task.short, name=name, version='{:0>3d}'.format(version), ext=ext)) return utils.unipath(workspace.path, filename)
def get_template_search_paths(): ctx = get_context() paths = set() if ctx.project: paths.add(unipath(ctx.project.data.path, 'templates')) for ext in extensions: paths.update(ext._template_paths) return [p for p in paths if os.path.isdir(p)]
def get_latest_version(filepath): '''Returns latest version, or the original file if it is not versioned''' root = os.path.dirname(filepath) # Check if this is a versioned file. versions = re.findall(r'\d+', filepath) if not versions: return filepath else: version = versions[-1] # Okay let's get the latest version name_pattern = rreplace(filepath, version, '*') path_pattern = unipath(root, name_pattern) versions = sorted(glob.glob(path_pattern)) if not versions: return filepath return unipath(versions[-1])
def setup_construct_hou(app): '''Setup Houdini environment''' hou_path = unipath(os.path.dirname(__file__), 'startup') old_hou_path = app.env.get('HOUDINI_PATH', None) if old_hou_path: hou_path += os.pathsep + old_hou_path old_pypath = app.env.get('PYTHONPATH', None) pypath = os.pathsep.join( [hou_path, os.path.join(os.path.dirname(__file__), '..')]) if old_pypath: pypath += os.pathsep + old_pypath app.env['HOUDINI_PATH'] = hou_path + os.pathsep + '&' app.env['PYTHONPATH'] = pypath
def before_create_reference_check(mfile, client_data): _log.debug('before_create_reference_check') reference = unipath(mfile.expandedFullName()) reference_name = os.path.basename(reference) latest = get_latest_version(reference) latest_name = os.path.basename(latest) if reference != latest: update = dialogs.ask( 'A newer version is available, would you like to update?', latest_name, title='Referencing ' + reference_name + '...') if update: mfile.setRawFullName(latest) return True
def from_path(cls, path): '''Extract context from file path''' ctx = Context.from_env(exclude=cls.entry_keys) if os.path.isfile(path): ctx.file = unipath(path) path = os.path.dirname(path) for entry in fsfs.search(path, direction=fsfs.UP): tags = entry.tags for key in Context.entry_keys: if key in tags: setattr(ctx, key, entry) return ctx
def list(search=None): '''List all resources''' def is_match(resource_path): return not search or search in resource_path resources = [] for ext in EXTENSIONS[1:]: pattern = unipath(THIS_PATH, '*', '*' + ext) for filepath in glob.glob(pattern): root = os.path.basename(os.path.dirname(filepath)) basename = os.path.basename(filepath) name, ext = os.path.splitext(basename) resource_path = ':/' + root + '/' + name if is_match(resource_path): resources.append(resource_path) return resources
RUNNING = 'RUNNING' SUCCESS = 'SUCCESS' FAILED = 'FAILED' SKIPPED = 'SKIPPED' PAUSED = 'PAUSED' DISABLED = 'DISABLED' ENABLED = 'ENABLED' DONE_STATUSES = [SUCCESS, FAILED] ACTION_SIGNALS = [ 'action.*', 'group.*', 'request.*', ] EXTENSIONS_ENTRY_POINT = 'construct.extensions' USER_CONFIG = unipath('~/.construct/construct.yaml') DEFAULT_CONFIG = package_path('defaults', 'construct.yaml') DEFAULT_ROOT = unipath('~/projects') DEFAULT_HOST = 'standalone' DEFAULT_LOGGING = dict( version=1, formatters={'simple': { 'format': '%(levelname).1s:%(name)s> %(message)s' }}, handlers={ 'console': { 'class': 'logging.StreamHandler', 'formatter': 'simple', } }, loggers={
def remove_template_path(self, path): p = unipath(path) if p in self._template_paths: self._template_paths.remove(p)
def add_template_path(self, path): self._template_paths.append(unipath(path))
def stage_project(root, template): '''Stage project data for validation''' return dict(path=unipath(root), name=os.path.basename(root), template=api.get_template(template))
# -*- coding: utf-8 -*- from __future__ import absolute_import import os import re import glob import logging from construct.utils import unipath from construct_ui.utils import get_scale_factor _log = logging.getLogger('construct.ui.resources') _initialized = False THIS_PATH = unipath(os.path.dirname(__file__)) EXTENSIONS = ['', '.png', '.ttf', '.css'] PATTERNS = [unipath(THIS_PATH, 'icons', '*.png')] ICON_EXT = '.png' ICONS_GLOB = unipath(THIS_PATH, 'icons', '*' + ICON_EXT) STYLE_EXT = '.css' STYLES_GLOB = unipath(THIS_PATH, 'styles', '*' + STYLE_EXT) FONT_EXT = '.ttf' FONTS_GLOB = unipath(THIS_PATH, 'fonts', '*' + FONT_EXT) class ResourceError(Exception): pass def style(resource, scale_factor=None): '''Get a stylesheet''' scale_factor = scale_factor or get_scale_factor()
def update_preview(self, *args): new_filename = self.generate_preview() self.name_preview.setText(new_filename) full_path = utils.unipath(self.data.workspace.path, new_filename) self.name_preview.valid = not os.path.exists(full_path)