diff --git a/release/scripts/modules/extensions_framework/__init__.py b/release/scripts/modules/extensions_framework/__init__.py deleted file mode 100644 index 6c4ced376c5..00000000000 --- a/release/scripts/modules/extensions_framework/__init__.py +++ /dev/null @@ -1,195 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -import time - -import bpy - -from extensions_framework.ui import EF_OT_msg - -bpy.types.register(EF_OT_msg) -del EF_OT_msg - - -def log(str, popup=False, module_name='EF'): - """Print a message to the console, prefixed with the module_name - and the current time. If the popup flag is True, the message will - be raised in the UI as a warning using the operator bpy.ops.ef.msg. - - """ - print("[%s %s] %s" % - (module_name, time.strftime('%Y-%b-%d %H:%M:%S'), str)) - if popup: - bpy.ops.ef.msg( - msg_type='WARNING', - msg_text=str - ) - - -added_property_cache = {} - -def init_properties(obj, props, cache=True): - """Initialise custom properties in the given object or type. - The props list is described in the declarative_property_group - class definition. If the cache flag is False, this function - will attempt to redefine properties even if they have already been - added. - - """ - - if not obj in added_property_cache.keys(): - added_property_cache[obj] = [] - - for prop in props: - try: - if cache and prop['attr'] in added_property_cache[obj]: - continue - - if prop['type'] == 'bool': - t = bpy.props.BoolProperty - a = {k: v for k,v in prop.items() if k in ['name', - 'description','default']} - elif prop['type'] == 'collection': - t = bpy.props.CollectionProperty - a = {k: v for k,v in prop.items() if k in ["ptype", "name", - "description"]} - a['type'] = a['ptype'] - del a['ptype'] - elif prop['type'] == 'enum': - t = bpy.props.EnumProperty - a = {k: v for k,v in prop.items() if k in ["items", "name", - "description", "default"]} - elif prop['type'] == 'float': - t = bpy.props.FloatProperty - a = {k: v for k,v in prop.items() if k in ["name", - "description", "min", "max", "soft_min", "soft_max", - "default", "precision"]} - elif prop['type'] == 'float_vector': - t = bpy.props.FloatVectorProperty - a = {k: v for k,v in prop.items() if k in ["name", - "description", "min", "max", "soft_min", "soft_max", - "default", "precision", "size", "subtype"]} - elif prop['type'] == 'int': - t = bpy.props.IntProperty - a = {k: v for k,v in prop.items() if k in ["name", - "description", "min", "max", "soft_min", "soft_max", - "default"]} - elif prop['type'] == 'pointer': - t = bpy.props.PointerProperty - a = {k: v for k,v in prop.items() if k in ["ptype", "name", - "description"]} - a['type'] = a['ptype'] - del a['ptype'] - elif prop['type'] == 'string': - t = bpy.props.StringProperty - a = {k: v for k,v in prop.items() if k in ["name", - "description", "maxlen", "default", "subtype"]} - else: - continue - - setattr(obj, prop['attr'], t(**a)) - - added_property_cache[obj].append(prop['attr']) - except KeyError: - # Silently skip invalid entries in props - continue - - -class declarative_property_group(bpy.types.IDPropertyGroup): - """A declarative_property_group describes a set of logically - related properties, using a declarative style to list each - property type, name, values, and other relevant information. - The information provided for each property depends on the - property's type. - - The properties list attribute in this class describes the - properties present in this group. - - Some additional information about the properties in this group - can be specified, so that a UI can be generated to display them. - To that end, the controls list attribute and the visibility dict - attribute are present here, to be read and interpreted by a - property_group_renderer object. - See extensions_framework.ui.property_group_renderer. - - """ - - """This list controls the order of property layout when rendered - by a property_group_renderer. This can be a nested list, where each - list becomes a row in the panel layout. Nesting may be to any depth. - - """ - controls = [] - - """The visibility dict controls the display of properties based on - the value of other properties. See extensions_framework.validate - for test syntax. - - """ - visibility = {} - - """The properties list describes each property to be created. Each - item should be a dict of args to pass to a - bpy.props.Property function, with the exception of 'type' - which is used and stripped by extensions_framework in order to - determine which Property creation function to call. - - Example item: - { - 'type': 'int', # bpy.props.IntProperty - 'attr': 'threads', # bpy.types..threads - 'name': 'Render Threads', # Rendered next to the UI - 'description': 'Number of threads to use', # Tooltip text in the UI - 'default': 1, - 'min': 1, - 'soft_min': 1, - 'max': 64, - 'soft_max': 64 - } - - """ - properties = [] - - def draw_callback(self, context): - """Sub-classes can override this to get a callback when - rendering is completed by a property_group_renderer sub-class. - - """ - - pass - - @classmethod - def get_exportable_properties(cls): - """Return a list of properties which have the 'save_in_preset' key - set to True, and hence should be saved into preset files. - - """ - - out = [] - for prop in cls.properties: - if 'save_in_preset' in prop.keys() and prop['save_in_preset']: - out.append(prop) - return out diff --git a/release/scripts/modules/extensions_framework/engine.py b/release/scripts/modules/extensions_framework/engine.py deleted file mode 100644 index 0a6fecb034a..00000000000 --- a/release/scripts/modules/extensions_framework/engine.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -from extensions_framework.plugin import plugin - -class engine_base(plugin): - """Render Engine plugin base class - - TODO: Remove, this class hasn't grown to be useful - - """ - - bl_label = 'Abstract Render Engine Base Class' - - def render(self, scene): - pass diff --git a/release/scripts/modules/extensions_framework/outputs/__init__.py b/release/scripts/modules/extensions_framework/outputs/__init__.py deleted file mode 100644 index f05ed25fbad..00000000000 --- a/release/scripts/modules/extensions_framework/outputs/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# diff --git a/release/scripts/modules/extensions_framework/outputs/xml_output.py b/release/scripts/modules/extensions_framework/outputs/xml_output.py deleted file mode 100644 index 3b1102c1888..00000000000 --- a/release/scripts/modules/extensions_framework/outputs/xml_output.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -import xml.etree.cElementTree as ET -import xml.dom.minidom as MD - -class xml_output(object): - """This class serves to describe an XML output, it uses - cElementTree and minidom to construct and format the XML - data. - - """ - - """The format dict describes the XML structure that this class - should generate, and which properties should be used to fill - the XML data structure - - """ - format = {} - - def __str__(self): - return ET.tostring(self.root) - - def write_pretty(self, file): - """Write a formatted XML string to file""" - xml_dom = MD.parseString(ET.tostring(self.root, encoding='utf-8')) - xml_dom.writexml(file, addindent=' ', newl='\n', encoding='utf-8') - - def pretty(self): - """Return a formatted XML string""" - xml_str = MD.parseString(ET.tostring(self.root)) - return xml_str.toprettyxml() - - def get_format(self): - """This should be overridden in classes that produce XML - conditionally - - """ - return self.format - - def compute(self, context): - """Compute the XML output from the input format""" - self.context = context - - self.root = ET.Element(self.root_element) - self.parse_dict(self.get_format(), self.root) - - return self.root - - """Formatting functions for various data types""" - format_types = { - 'bool': lambda c,x: str(x).lower(), - 'collection': lambda c,x: x, - 'enum': lambda c,x: x, - 'float': lambda c,x: x, - 'int': lambda c,x: x, - 'pointer': lambda c,x: x, - 'string': lambda c,x: x, - } - - def parse_dict(self, d, elem): - """Parse the values in the format dict and collect the - formatted data into XML structure starting at self.root - - """ - for key in d.keys(): - # tuple provides multiple child elements - if type(d[key]) is tuple: - for cd in d[key]: - self.parse_dict({key:cd}, elem) - continue # don't create empty element for tuple child - - x = ET.SubElement(elem, key) - - # dictionary provides nested elements - if type(d[key]) is dict: - self.parse_dict(d[key], x) - - # list provides direct value insertion - elif type(d[key]) is list: - x.text = ' '.join([str(i) for i in d[key]]) - - # else look up property - else: - for p in self.properties: - if d[key] == p['attr']: - if 'compute' in p.keys(): - x.text = str(p['compute'](self.context, self)) - else: - x.text = str( - self.format_types[p['type']](self.context, - getattr(self, d[key])) - ) diff --git a/release/scripts/modules/extensions_framework/plugin.py b/release/scripts/modules/extensions_framework/plugin.py deleted file mode 100644 index 76f41930fdd..00000000000 --- a/release/scripts/modules/extensions_framework/plugin.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -import bpy - -from extensions_framework import init_properties -from extensions_framework import log - -class plugin(object): - """Base class for plugins which wish to make use of utilities - provided in extensions_framework. Using the property_groups - attribute and the install() and uninstall() methods, a large number - of custom scene properties can be easily defined, displayed and - managed. - - TODO: Rename, 'extension' would be more appropriate than 'plugin' - - """ - - """The property_groups defines a list of declarative_property_group - types to create in specified types during the initialisation of the - plugin. - Item format: - ('bpy.type prototype to attach to', ) - - Example item: - ('Scene', myaddon_property_group) - In this example, a new property group will be attached to - bpy.types.Scene and all of the properties described in that group - will be added to it. - See extensions_framework.declarative_property_group. - - """ - property_groups = [] - - @classmethod - def install(r_class): - """Initialise this plugin. So far, all this does is to create - custom property groups specified in the property_groups - attribute. - - """ - for property_group_parent, property_group in r_class.property_groups: - call_init = False - if property_group_parent is not None: - prototype = getattr(bpy.types, property_group_parent) - if not hasattr(prototype, property_group.__name__): - init_properties(prototype, [{ - 'type': 'pointer', - 'attr': property_group.__name__, - 'ptype': property_group, - 'name': property_group.__name__, - 'description': property_group.__name__ - }]) - call_init = True - else: - call_init = True - - if call_init: - init_properties(property_group, property_group.properties) - - log('Extension "%s" initialised' % r_class.bl_label) - - @classmethod - def uninstall(r_class): - """Unregister property groups in reverse order""" - reverse_property_groups = [p for p in r_class.property_groups] - reverse_property_groups.reverse() - for property_group_parent, property_group in reverse_property_groups: - prototype = getattr(bpy.types, property_group_parent) - prototype.RemoveProperty(property_group.__name__) diff --git a/release/scripts/modules/extensions_framework/ui.py b/release/scripts/modules/extensions_framework/ui.py deleted file mode 100644 index 5bbd69c0628..00000000000 --- a/release/scripts/modules/extensions_framework/ui.py +++ /dev/null @@ -1,253 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -import bpy - -from extensions_framework.validate import Visibility - -class EF_OT_msg(bpy.types.Operator): - """An operator to show simple messages in the UI""" - bl_idname = 'ef.msg' - bl_label = 'Show UI Message' - msg_type = bpy.props.StringProperty(default='INFO') - msg_text = bpy.props.StringProperty(default='') - def execute(self, context): - self.report({self.properties.msg_type}, self.properties.msg_text) - return {'FINISHED'} - -def _get_item_from_context(context, path): - """Utility to get an object when the path to it is known: - _get_item_from_context(context, ['a','b','c']) returns - context.a.b.c - No error checking is performed other than checking that context - is not None. Exceptions caused by invalid path should be caught in - the calling code. - - """ - - if context is not None: - for p in path: - context = getattr(context, p) - return context - -class property_group_renderer(object): - """Mix-in class for sub-classes of bpy.types.Panel. This class - will provide the draw() method which implements drawing one or - more property groups derived from - extensions_framework.declarative_propery_group. - The display_property_groups list attribute describes which - declarative_property_groups should be drawn in the Panel, and - how to extract those groups from the context passed to draw(). - - """ - - """The display_property_groups list attribute specifies which - custom declarative_property_groups this panel should draw, and - where to find that property group in the active context. - Example item: - ( ('scene',), 'myaddon_property_group') - In this case, this renderer will look for properties in - context.scene.myaddon_property_group to draw in the Panel. - - """ - display_property_groups = [] - - def draw(self, context): - """Sub-classes should override this if they need to display - other (object-related) property groups. super().draw(context) - can be a useful call in those cases. - - """ - for property_group_path, property_group_name in \ - self.display_property_groups: - ctx = _get_item_from_context(context, property_group_path) - property_group = getattr(ctx, property_group_name) - for p in property_group.controls: - self.draw_column(p, self.layout, ctx, context, - property_group=property_group) - property_group.draw_callback(context) - - def check_visibility(self, lookup_property, property_group): - """Determine if the lookup_property should be drawn in the Panel""" - vt = Visibility(property_group) - if lookup_property in property_group.visibility.keys(): - if hasattr(property_group, lookup_property): - member = getattr(property_group, lookup_property) - else: - member = None - return vt.test_logic(member, - property_group.visibility[lookup_property]) - else: - return True - - # tab_level = 0 - - def is_real_property(self, lookup_property, property_group): - for prop in property_group.properties: - if prop['attr'] == lookup_property: - return prop['type'] not in ['text', 'prop_search'] - - return False - - def draw_column(self, control_list_item, layout, context, - supercontext=None, property_group=None): - # self.tab_level += 1 - """Draw a column's worth of UI controls in this Panel""" - if type(control_list_item) is list: - draw_row = False - - found_percent = None - # print('\t'*self.tab_level, '--', property_group, '--') - for sp in control_list_item: - # print('\t'*self.tab_level, sp) - if type(sp) is float: - found_percent = sp - elif type(sp) is list: - for ssp in [s for s in sp if self.is_real_property(s, property_group)]: - draw_row = draw_row or self.check_visibility(ssp, - property_group) - # print('\t'*self.tab_level, 'List: ', draw_row) - else: - draw_row = draw_row or self.check_visibility(sp, - property_group) - # print('\t'*self.tab_level, 'Single: ', draw_row) - # print('\t'*self.tab_level, '-->', draw_row) - # print('\t'*self.tab_level, '--', property_group, '--') - - next_items = [s for s in control_list_item if type(s) in [str, list]] - if draw_row and len(next_items) > 0: - if found_percent is not None: - splt = layout.split(percentage=found_percent) - else: - splt = layout.row(True) - for sp in next_items: - col2 = splt.column() - self.draw_column(sp, col2, context, supercontext, - property_group) - else: - if self.check_visibility(control_list_item, property_group): - - for current_property in property_group.properties: - if current_property['attr'] == control_list_item: - current_property_keys = current_property.keys() - if 'type' in current_property_keys: - - if current_property['type'] in ['int', 'float', - 'float_vector', 'enum', 'string']: - layout.prop( - property_group, - control_list_item, - text = current_property['name'], - expand = current_property['expand'] \ - if 'expand' in current_property_keys \ - else False, - slider = current_property['slider'] \ - if 'slider' in current_property_keys \ - else False, - toggle = current_property['toggle'] \ - if 'toggle' in current_property_keys \ - else False, - icon_only = current_property['icon_only'] \ - if 'icon_only' in current_property_keys \ - else False, - event = current_property['event'] \ - if 'event' in current_property_keys \ - else False, - full_event = current_property['full_event'] \ - if 'full_event' in current_property_keys \ - else False, - emboss = current_property['emboss'] \ - if 'emboss' in current_property_keys \ - else True, - ) - if current_property['type'] in ['bool']: - layout.prop( - property_group, - control_list_item, - text = current_property['name'], - toggle = current_property['toggle'] \ - if 'toggle' in current_property_keys \ - else False, - icon_only = current_property['icon_only'] \ - if 'icon_only' in current_property_keys \ - else False, - event = current_property['event'] \ - if 'event' in current_property_keys \ - else False, - full_event = current_property['full_event'] \ - if 'full_event' in current_property_keys \ - else False, - emboss = current_property['emboss'] \ - if 'emboss' in current_property_keys \ - else True, - ) - elif current_property['type'] in ['operator']: - layout.operator(current_property['operator'], - text = current_property['text'], - icon = current_property['icon'] - ) - - elif current_property['type'] in ['text']: - layout.label( - text = current_property['name'] - ) - - elif current_property['type'] in ['template_list']: - layout.template_list( - current_property['src'](supercontext, context), - current_property['src_attr'], - current_property['trg'](supercontext, context), - current_property['trg_attr'], - rows = 4 \ - if not 'rows' in current_property_keys \ - else current_property['rows'], - maxrows = 4 \ - if not 'rows' in current_property_keys \ - else current_property['rows'], - type = 'DEFAULT' \ - if not 'list_type' in current_property_keys \ - else current_property['list_type'] - ) - - elif current_property['type'] in ['prop_search']: - layout.prop_search( - current_property['trg'](supercontext, - context), - current_property['trg_attr'], - current_property['src'](supercontext, - context), - current_property['src_attr'], - text = current_property['name'], - ) - else: - layout.prop(property_group, control_list_item) - - # Fire a draw callback if specified - if 'draw' in current_property_keys: - current_property['draw'](supercontext, context) - - break - # self.tab_level -= 1 diff --git a/release/scripts/modules/extensions_framework/util.py b/release/scripts/modules/extensions_framework/util.py deleted file mode 100644 index dc737c6e4ae..00000000000 --- a/release/scripts/modules/extensions_framework/util.py +++ /dev/null @@ -1,223 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** -# -import configparser -import datetime -import os -import tempfile -import threading - -import bpy - -"""List of possibly appropriate paths to load/save addon config from/to""" -config_paths = [] -if bpy.utils.user_resource('CONFIG') != "": config_paths.append(bpy.utils.user_resource('CONFIG')) -if bpy.utils.user_resource('SCRIPTS') != "": config_paths.append(bpy.utils.user_resource('SCRIPTS')) -for pth in bpy.utils.script_paths(): - if pth != "": config_paths.append(pth) - -"""This path is set at the start of export, so that calls to -path_relative_to_export() can make all exported paths relative to -this one. -""" -export_path = ''; - -def path_relative_to_export(p): - """Return a path that is relative to the export path""" - global export_path - p = filesystem_path(p) - try: - relp = os.path.relpath(p, os.path.dirname(export_path)) - except ValueError: # path on different drive on windows - relp = p - - return relp.replace('\\', '/') - -def filesystem_path(p): - """Resolve a relative Blender path to a real filesystem path""" - if p.startswith('//'): - pout = bpy.path.abspath(p) - else: - pout = os.path.realpath(p) - - return pout.replace('\\', '/') - -# TODO: - somehow specify TYPES to get/set from config - -def find_config_value(module, section, key, default): - """Attempt to find the configuration value specified by string key - in the specified section of module's configuration file. If it is - not found, return default. - - """ - global config_paths - fc = [] - for p in config_paths: - if os.path.exists(p) and os.path.isdir(p) and os.access(p, os.W_OK): - fc.append( '/'.join([p, '%s.cfg' % module])) - - if len(fc) < 1: - print('Cannot find %s config file path' % module) - return default - - cp = configparser.SafeConfigParser() - - cfg_files = cp.read(fc) - if len(cfg_files) > 0: - try: - val = cp.get(section, key) - if val == 'true': - return True - elif val == 'false': - return False - else: - return val - except: - return default - else: - return default - -def write_config_value(module, section, key, value): - """Attempt to write the configuration value specified by string key - in the specified section of module's configuration file. - - """ - global config_paths - fc = [] - for p in config_paths: - if os.path.exists(p) and os.path.isdir(p) and os.access(p, os.W_OK): - fc.append( '/'.join([p, '%s.cfg' % module])) - - if len(fc) < 1: - raise Exception('Cannot find a writable path to store %s config file' % - module) - - cp = configparser.SafeConfigParser() - - cfg_files = cp.read(fc) - - if not cp.has_section(section): - cp.add_section(section) - - if value == True: - cp.set(section, key, 'true') - elif value == False: - cp.set(section, key, 'false') - else: - cp.set(section, key, value) - - if len(cfg_files) < 1: - cfg_files = fc - - fh=open(cfg_files[0],'w') - cp.write(fh) - fh.close() - - return True - -def scene_filename(): - """Construct a safe scene filename, using 'untitled' instead of ''""" - filename = os.path.splitext(os.path.basename(bpy.data.filepath))[0] - if filename == '': - filename = 'untitled' - return bpy.path.clean_name(filename) - -def temp_directory(): - """Return the system temp directory""" - return tempfile.gettempdir() - -def temp_file(ext='tmp'): - """Get a temporary filename with the given extension. This function - will actually attempt to create the file.""" - tf, fn = tempfile.mkstemp(suffix='.%s'%ext) - os.close(tf) - return fn - -class TimerThread(threading.Thread): - """Periodically call self.kick(). The period of time in seconds - between calling is given by self.KICK_PERIOD, and the first call - may be delayed by setting self.STARTUP_DELAY, also in seconds. - self.kick() will continue to be called at regular intervals until - self.stop() is called. Since this is a thread, calling self.join() - may be wise after calling self.stop() if self.kick() is performing - a task necessary for the continuation of the program. - The object that creates this TimerThread may pass into it data - needed during self.kick() as a dict LocalStorage in __init__(). - - """ - STARTUP_DELAY = 0 - KICK_PERIOD = 8 - - active = True - timer = None - - LocalStorage = None - - def __init__(self, LocalStorage=dict()): - threading.Thread.__init__(self) - self.LocalStorage = LocalStorage - - def set_kick_period(self, period): - """Adjust the KICK_PERIOD between __init__() and start()""" - self.KICK_PERIOD = period + self.STARTUP_DELAY - - def stop(self): - """Stop this timer. This method does not join()""" - self.active = False - if self.timer is not None: - self.timer.cancel() - - def run(self): - """Timed Thread loop""" - while self.active: - self.timer = threading.Timer(self.KICK_PERIOD, self.kick_caller) - self.timer.start() - if self.timer.isAlive(): self.timer.join() - - def kick_caller(self): - """Intermediary between the kick-wait-loop and kick to allow - adjustment of the first KICK_PERIOD by STARTUP_DELAY - - """ - if self.STARTUP_DELAY > 0: - self.KICK_PERIOD -= self.STARTUP_DELAY - self.STARTUP_DELAY = 0 - - self.kick() - - def kick(self): - """Sub-classes do their work here""" - pass - -def format_elapsed_time(t): - """Format a duration in seconds as an HH:MM:SS format time""" - - td = datetime.timedelta(seconds=t) - min = td.days*1440 + td.seconds/60.0 - hrs = td.days*24 + td.seconds/3600.0 - - return '%i:%02i:%02i' % (hrs, min%60, td.seconds%60) diff --git a/release/scripts/modules/extensions_framework/validate.py b/release/scripts/modules/extensions_framework/validate.py deleted file mode 100644 index d9cee8fd807..00000000000 --- a/release/scripts/modules/extensions_framework/validate.py +++ /dev/null @@ -1,213 +0,0 @@ -# -*- coding: utf8 -*- -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -------------------------------------------------------------------------- -# Blender 2.5 Extensions Framework -# -------------------------------------------------------------------------- -# -# Authors: -# Doug Hammond -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# ***** END GPL LICENCE BLOCK ***** -# -""" -Pure logic and validation class. - -By using a Subject object, and a dict of described logic tests, it -is possible to arrive at a True or False result for various purposes: -1. Data validation -2. UI control visibility - -A Subject can be any object whose members are readable with getattr() : -class Subject(object): - a = 0 - b = 1 - c = 'foo' - d = True - e = False - f = 8 - g = 'bar' - - -Tests are described thus: - -Use the special list types Logic_AND and Logic_OR to describe -combinations of values and other members. Use Logic_Operator for -numerical comparison. - -With regards to Subject, each of these evaluate to True: -TESTA = { - 'a': 0, - 'c': Logic_OR([ 'foo', 'bar' ]), - 'd': Logic_AND([True, True]), - 'f': Logic_AND([8, {'b': 1}]), - 'e': {'b': Logic_Operator({'gte':1, 'lt':3}) }, - 'g': Logic_OR([ 'baz', Logic_AND([{'b': 1}, {'f': 8}]) ]) -} - -With regards to Subject, each of these evaluate to False: -TESTB = { - 'a': 'foo', - 'c': Logic_OR([ 'bar', 'baz' ]), - 'd': Logic_AND([ True, 'foo' ]), - 'f': Logic_AND([9, {'b': 1}]), - 'e': {'b': Logic_Operator({'gte':-10, 'lt': 1}) }, - 'g': Logic_OR([ 'baz', Logic_AND([{'b':0}, {'f': 8}]) ]) -} - -With regards to Subject, this test is invalid -TESTC = { - 'n': 0 -} - -Tests are executed thus: -S = Subject() -L = Logician(S) -L.execute(TESTA) - -""" - -class Logic_AND(list): - pass -class Logic_OR(list): - pass -class Logic_Operator(dict): - pass - -class Logician(object): - """Given a subject and a dict that describes tests to perform on - its members, this class will evaluate True or False results for - each member/test pair. See the examples below for test syntax. - - """ - - subject = None - def __init__(self, subject): - self.subject = subject - - def get_member(self, member_name): - """Get a member value from the subject object. Raise exception - if subject is None or member not found. - - """ - if self.subject is None: - raise Exception('Cannot run tests on a subject which is None') - - return getattr(self.subject, member_name) - - def test_logic(self, member, logic, operator='eq'): - """Find the type of test to run on member, and perform that test""" - - if type(logic) is dict: - return self.test_dict(member, logic) - elif type(logic) is Logic_AND: - return self.test_and(member, logic) - elif type(logic) is Logic_OR: - return self.test_or(member, logic) - elif type(logic) is Logic_Operator: - return self.test_operator(member, logic) - else: - # compare the value, I think using Logic_Operator() here - # allows completeness in test_operator(), but I can't put - # my finger on why for the minute - return self.test_operator(member, - Logic_Operator({operator: logic})) - - def test_operator(self, member, value): - """Execute the operators contained within value and expect that - ALL operators are True - - """ - - # something in this method is incomplete, what if operand is - # a dict, Logic_AND, Logic_OR or another Logic_Operator ? - # Do those constructs even make any sense ? - - result = True - for operator, operand in value.items(): - operator = operator.lower().strip() - if operator in ['eq', '==']: - result &= member==operand - if operator in ['not', '!=']: - result &= member!=operand - if operator in ['lt', '<']: - result &= member']: - result &= member>operand - if operator in ['gte', '>=']: - result &= member>=operand - if operator in ['and', '&']: - result &= member&operand - if operator in ['or', '|']: - result &= member|operand - if operator in ['len']: - result &= len(member)==operand - # I can think of some more, but they're probably not useful. - - return result - - def test_or(self, member, logic): - """Member is a value, logic is a set of values, ANY of which - can be True - - """ - result = False - for test in logic: - result |= self.test_logic(member, test) - - return result - - def test_and(self, member, logic): - """Member is a value, logic is a list of values, ALL of which - must be True - - """ - result = True - for test in logic: - result &= self.test_logic(member, test) - - return result - - def test_dict(self, member, logic): - """Member is a value, logic is a dict of other members to - compare to. All other member tests must be True - - """ - result = True - for other_member, test in logic.items(): - result &= self.test_logic(self.get_member(other_member), test) - - return result - - def execute(self, test): - """Subject is an object, test is a dict of {member: test} pairs - to perform on subject's members. Wach key in test is a member - of subject. - - """ - - for member_name, logic in test.items(): - result = self.test_logic(self.get_member(member_name), logic) - print('member %s is %s' % (member_name, result)) - -# A couple of name aliases -class Validation(Logician): - pass -class Visibility(Logician): - pass