Fixed the licence header on two files that the epl:ling script missed for some reason.
#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
"""
Cone public API.
The core interface to the ConE functionality.
"""
import os
import re
import sys
import logging
import copy
import sets
import exceptions, utils, container, mapping
class Base(container.ObjectContainer):
"""
The Base class is intended for capturing same kind of naming scheme.
"""
def __init__(self, ref="", **kwargs):
if len(utils.dottedref.split_ref(ref)) > 1:
raise exceptions.InvalidRef("Invalid reference for Base object %s!" % ref)
self.ref = ref
container.ObjectContainer.__init__(self, ref)
for arg in kwargs.keys():
if kwargs.get(arg) != None:
setattr(self, arg, kwargs.get(arg))
def __repr__(self):
dict = self._dict()
return "%s(%s)" % (self.__class__.__name__, dict)
def _get_mapper(self,modelname):
"""
Return a instance of appropriate mapper for given model.
"""
return mapping.BaseMapper()
def _compare(self, other, dict_keys=None):
"""
Compare the attributes of elements
"""
if isinstance(other, Base):
keys = dict_keys or self._dict().keys()
for key in keys:
self_attr = None
other_attr = None
try:
self_attr = getattr(self, key)
other_attr = getattr(other, key)
except AttributeError:
# If the attribute is not found from either elements
# ignore it entirely
if self_attr == None and other_attr == None:
continue
if self_attr != other_attr:
return False
# If all given keys match report this as as similar element
return True
else:
return False
def _clone(self, **kwargs):
"""
A generic implementation for cloning the object.
Copies all (public) members in dictionary.
To clone objects recursively set the recursion level with recursion param.
@param recursion: Boolean to define recursion on or off
@param recursion_depth: positive integer to define recursion depth. default is -1 which will
perform recursion to all objects.
"""
dict = self._dict()
if kwargs.get('class_instance'):
class_instance = kwargs.get('class_instance')
del kwargs['class_instance']
else:
class_instance = self.__class__
obj = class_instance(**dict)
# Remove all children created at the construction phase
# This is needed when the recursion adds children to the object so that there are not duplicates
obj._order = []
obj._children = {}
# handle the recursion argument
recursion = kwargs.get('recursion', False)
if recursion:
recursion_depth = kwargs.get('recursion_depth', -1)
if recursion_depth < 0 or recursion_depth > 0:
# decrease the recursion
kwargs['recursion_depth'] = recursion_depth - 1
for child in self._objects():
obj._add(child._clone(**kwargs), container.APPEND)
return obj
def _dict(self):
"""
Return the public variables in a dictionary
"""
dict = {}
for key in self.__dict__.keys():
if key.startswith('_'):
continue
else:
dict[key] = self.__dict__[key]
return dict
def _default_object(self, name):
return Base(name)
@property
def fqr(self):
"""
Return a Fully Qualified Ref, which is the full name of the reference.
Joins the namespace and ref to one string.
@return: A string
"""
return utils.dottedref.join_refs([self.namespace, self.get_ref()])
@property
def namespace(self):
"""
@return: The namespace of the object.
"""
containerpath = ""
path = ""
parentcontainer = self.find_parent(container=True)
parent = self.find_parent(type=Base)
paths = []
while parent and parent != parentcontainer:
""" Skip the element if it is supposed to be hidden. Begins with _. """
if not parent.get_ref().startswith('_'):
paths.append(parent.get_ref())
parent = parent._get_parent()
if parentcontainer:
paths.append(parentcontainer.namespace)
paths.reverse()
return utils.dottedref.join_refs(paths)
def get_fullref(self):
"""
Return a full reference, reference including a
possible index of the object in list.
e.g. ref can be bar[1] or just the normal bar.
@return: The full reference of the object.
"""
if self.parent and utils.is_list(self.parent._get(self.ref)):
return "%s[%s]" % (self.ref, self.get_index())
else:
return self.ref
def get_fullfqr(self):
"""
Return a full reference, reference including a
possible index of the object in list.
ref and adds index.
@return: A string
"""
return utils.dottedref.join_refs([self.get_fullnamespace(), self.get_fullref()])
def get_fullnamespace(self):
"""
@return: The full namespace of the object with possible indexes of the parent objects
"""
containerpath = ""
path = ""
parentcontainer = self.find_parent(container=True)
parent = self.find_parent(type=Base)
paths = []
while parent and parent != parentcontainer:
paths.append(parent.get_fullref())
parent = parent.parent
if parentcontainer:
paths.append(parentcontainer.namespace)
paths.reverse()
return utils.dottedref.join_refs(paths)
def get_storage(self):
"""
Get the root storage from the root object.
"""
if self._find_parent():
return self._find_parent().get_storage()
else:
raise exceptions.StorageException("Storage is not found from root!")
def get_project(self):
"""
Get the root project from the root object.
"""
if isinstance(self, Project):
return self
elif self._find_parent():
return self._find_parent().get_project()
else:
raise exceptions.NotFound("Project not found!!")
def get_default_view(self):
"""
Get the default view from the root object.
"""
try:
return self._find_parent().get_default_view()
except exceptions.NotFound:
raise exceptions.NotFound("Default View is not found! No root configuration?")
def get_root(self):
"""
Get the root object
"""
try:
return self._find_parent().get_root()
except exceptions.NotFound:
return self
def get_root_configuration(self):
"""
Get the root object
"""
if self.find_parent(type=Configuration):
return self.find_parent(type=Configuration).get_root_configuration()
elif isinstance(self, Configuration):
return self
else:
return None
def get_index(self):
"""
@return : the index of the data element for sequential data defined inside the same configuration.
0 for normal data.
"""
# Get the list of items from parent which contains this element and ask my own index
# Make sure that the returned element is a list with get_list
selflist = utils.get_list(self._get_parent()._get(self.get_ref()))
return selflist.index(self)
def find_parent(self, **kwargs):
"""
find the closest parent object of given type.
e.g. find_parent(type=Configuration) returns the closest parent
Configuration parent instance
@param type: class definitiob
"""
type = kwargs.get('type', None)
container = kwargs.get('container', False)
try:
parent = self._find_parent()
if type and isinstance(parent, type):
return parent
elif container and hasattr(parent, 'container'):
return parent
else:
return parent.find_parent(**kwargs)
except exceptions.NotFound:
return None
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
raise exceptions.NotSupportedException("Cannot add %s object to %s" % (child, self))
def get_elem(self, fqr):
"""
A generic get function to get child objects and members. The function uses getattr
to traverse downwards the the object tree. The returned object is the final object or attribute
if it is found. Raises AttributeError if the child is not found.
Example: obj.get('test.bar'), returns child obj.test.bar
@param fqr: the fully qualified ref to the object
@raise AttributeError: if the given ref is not found.
"""
return None
class Project(Base):
"""
A project is a container that can hold several Configuration objects.
"""
def __init__(self, storage, **kwargs):
"""
Project constructor
"""
Base.__init__(self, "")
""" Try to set the model and tet the actual configuration class """
try:
self._model = storage.persistentmodule.MODEL
except AttributeError:
self._model = None
self.set_storage(storage)
self.update()
self.loaded = {}
def __add_loaded__(self, ref, obj):
"""
Add the object to loaded
"""
self.loaded[ref] = {'counter': 0, 'obj': obj}
def __get_loaded__(self, ref):
"""
Get a loaded object if it is existing and increase the reference counter
@param ref:
@return: The loaded object if it exists. None if it does not.
"""
if self.loaded.has_key(ref):
return self.loaded[ref]['obj']
else:
return None
def __loaded__(self, ref):
"""
Get a loaded object if it is existing and increase the reference counter
@param ref:
@return: The loaded object if it exists. None if it does not.
"""
if self.loaded.has_key(ref):
self.loaded[ref]['counter'] += 1
else:
raise exceptions.NotFound("ref %s is not found from loaded!" % ref)
def __unloaded__(self, ref):
"""
returns True when the reference count is zero and object can be released.
"""
if self.loaded.has_key(ref):
self.loaded[ref]['counter'] -= 1
if self.loaded[ref]['counter'] == 0:
del self.loaded[ref]
return True
else:
return False
else:
return True
def _supported_type(self, obj):
if isinstance(obj, Configuration) \
or isinstance(obj, ConfigurationProxy):
return True
else:
return False
def update(self):
"""
update the root confml files as configurations
"""
root_confmls = self.get_storage().list_resources(".")
root_confmls = utils.resourceref.filter_resources(root_confmls, "\.confml")
for rootml in root_confmls:
self._add(ConfigurationProxy(rootml))
def get_storage(self):
"""
Get the Storage instance of this Project.
"""
return self.storage
def set_storage(self, storage):
"""
Set the Storage instance of this Project.
"""
if isinstance(storage, Storage):
self.storage = storage
else:
raise exceptions.StorageException("The given storage is not a instance of Storage!")
def list_configurations(self, filter_or_filters=None):
"""
List the direct child objects of the project (Root configurations)
@param filter_or_filters: A regular expression or list of regular expressions
used for filtering the configuration paths. If None, all configurations are
returned.
@return: a list for configuration file paths
"""
filters = None
if isinstance(filter_or_filters, basestring): filters = [filter_or_filters]
elif filter_or_filters is not None: filters = filter_or_filters
configs = [obj.get_path() for obj in self._objects()]
if filters is not None:
result = []
for config in configs:
for filter in filters:
if re.match(filter, config) is not None:
result.append(config)
break
return result
else:
return configs
def list_all_configurations(self):
"""
List all configuration objects of the project (all configurations)
@return: a list for configuration file paths
"""
return [obj.get_path() for obj in self._traverse(type=(Configuration, ConfigurationProxy))]
def get_configuration(self, path):
"""
Get a configuration object from the given path
@param path: path to configuration
@return: a instance of Configuration.
"""
# Load the configuration object if it is not already loaded
try:
return self._get(utils.resourceref.to_objref(utils.resourceref.norm(path)))
except exceptions.NotFound, e:
if self.storage.is_resource(utils.resourceref.norm(path)):
proxy = ConfigurationProxy(utils.resourceref.norm(path))
proxy._set_parent(self)
return proxy
else:
raise e
def is_configuration(self, path):
"""
Return true if the given path is a configuration object in this Project.
@param path: path to configuration
@return: Boolean return value.
"""
# Changed from list_all_configurations to list_configurations
# (list_all_configurations causes a insane performance problem with _traverse)
return path in self.list_configurations()
def add_configuration(self, config):
"""
Add a Configuration object to this project
"""
if isinstance(config, Configuration):
if self.is_configuration(config.get_path()):
raise exceptions.AlreadyExists("%s" % config.get_path())
self._add(config)
self.__add_loaded__(config.get_path(), config)
self.__loaded__(config.get_path())
else:
raise exceptions.IncorrectClassError("Only Configuration instance can be added to Project!")
def create_configuration(self, path, namespace=""):
"""
Create a Configuration object to this project
"""
config = self.get_configuration_class()(utils.resourceref.norm(path), namespace=namespace)
self.add_configuration(config)
return config
def remove_configuration(self, path):
"""
Remove a Configuration by its reference
"""
# remove configuration as an object and try to remove it from the storage
self._remove(utils.resourceref.to_objref(path))
try:
self.storage.delete_resource(path)
except exceptions.NotSupportedException:
pass
return
def import_configuration(self, configuration):
"""
Import a configuration object from another storage
"""
self.storage.import_resources(configuration.list_resources(), configuration.get_storage())
return
def export_configuration(self, configuration, export_storage, empty_folders=False):
"""
Export a configuration object to another storage
"""
# First clone the configuration and then import the rest of the configuration resources
if isinstance(configuration, ConfigurationProxy):
configuration = configuration._get_obj()
export_storage.unload(configuration.get_full_path(),configuration)
for child in configuration._traverse(type=Configuration):
export_storage.unload(child.get_full_path(),child)
#If the configuration is not in the root of the project adding the path
#to final exporting source path.
#l = []
cpath = utils.resourceref.get_path(configuration.get_path())
resr = [utils.resourceref.join_refs([cpath,related]) \
for related in configuration.get_layer().list_all_related(empty_folders)]
self.storage.export_resources(resr ,export_storage, empty_folders)
return
def get_configuration_class(self):
"""
return the default configuration class that is used with the model.
"""
return utils.get_class(self._model, Configuration)
def save(self):
"""
Save the object to the permanent Storage object. Calls the save operation for
all the children and also for the Storage.
"""
for child in self._objects():
if isinstance(child, (Configuration, ConfigurationProxy)):
child.save()
self.storage.save()
def close(self):
"""
Close the Project.
"""
for child in self._objects():
if isinstance(child, (Configuration, ConfigurationProxy)):
child.close()
self.storage.close()
def load(self, path):
"""
Load an object from a reference. The given reference is loaded once from storage
and stored as a loaded object to the Project. Sequential loads to the same ref will
return the same object.
@param path: The reference where to load the object
@raise StorageException: if the given object cannot be loaded as an
object from this storage
"""
if not self.__get_loaded__(path):
configuration = self.get_storage().load(path)
if configuration.get_ref() == 'unknown':
configuration.set_ref(utils.resourceref.to_dref(path))
self.__add_loaded__(path, configuration)
""" increase the ref counter """
self.__loaded__(path)
return self.__get_loaded__(path)
def unload(self, path, object):
"""
Release the given ref, which decreases the reference counter of the given ref.
@param path: The reference where to store the object
@param object: The object instance to dump
@raise StorageException: if the given object cannot be dumped to this storage
"""
if self.__unloaded__(path):
self.get_storage().unload(path, object)
def get_path(self):
"""
Return the path of the project, which is always root
"""
return ""
class CompositeConfiguration(Base):
"""
A base class for composite Configuration objects.
"""
def __init__(self, ref="", **kwargs):
# self.meta = {}
# self.desc = ""
super(CompositeConfiguration, self).__init__(ref, **kwargs)
self.container = True
def add_configuration(self, config):
"""
Add an existing Configuration to this configuration
@param config: A Configuration instance:
@return: None
"""
"""
Merge the default view features from added config to this configs _default_view.
"""
self._add(config)
def include_configuration(self, configref):
"""
Add an existing Configuration to this configuration by its resource reference
@param config: A Configuration instance:
@return: None
"""
# add the configuration load proxy to this configuration instead
# adding the configuration directly
self._add(ConfigurationProxy(configref))
def create_configuration(self, path):
"""
Create a new configuration by its name to the Configuration.
1. Create new Configuration object
2. Create new ConfigurationProxy
3. Add proxy to this object
4. Set proxy to point to the created Configuration object
@param path: The reference of the configuration to create
@return: The new configuration object.
"""
# normalise the path
normpath = utils.resourceref.norm(path)
cklass = self.get_configuration_class()
conf = cklass(normpath, namespace=self.namespace)
proxy = ConfigurationProxy(normpath)
self.add_configuration(proxy)
proxy._set_obj(conf)
return conf
def remove_configuration(self, path):
"""
Remove a Layer object from the Configuration by its reference.
"""
self._remove(utils.resourceref.to_objref(path))
def list_configurations(self):
"""
List all Layer objects in the Configuration
@return: a copy array of layer references.
"""
return [config.get_path() for config in self._objects(type=(Configuration, ConfigurationProxy))]
def list_all_configurations(self):
"""
List all Layer objects in the Configuration
@return: a copy array of layer references.
"""
# TODO
# huge performance problem
return [config.get_path() for config in self._traverse(type=(Configuration, ConfigurationProxy))]
def get_configuration(self, path):
"""
Get a Layer object by if path
@return: a Layer object
"""
return self._get(utils.resourceref.to_objref(path))
def get_configuration_by_index(self, index):
"""
Get a Layer object by if indexing number
@return: a Layer object
"""
configs = self._objects(type=(Configuration, ConfigurationProxy))
return configs[index]
def get_last_configuration(self):
"""
Get the last Layer object from this configuration hierarchy.
@return: a Layer object
"""
last_config = self
try:
last_config = last_config.get_configuration_by_index(-1)
return last_config.get_last_configuration()
except IndexError:
return self
def get_configuration_class(self):
"""
return the default configuration class retrieved from the project if it is found.
Otherwise return cone.public.api.Configuration.
"""
try:
return self.get_project().get_configuration_class()
# catch the Parent/Project NotFound exception
except exceptions.NotFound:
return Configuration
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, Configuration):
self.add_configuration(child)
elif isinstance(child, ConfigurationProxy):
self.add_configuration(child)
elif isinstance(child, Base):
self._add(child)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
def layered_content(self, layers=None):
"""
fetch content from first to last and override content
if it is found from a later layer
Create an array of the layers based on the layer indexes.
"""
configuration_array = []
if layers == None:
configuration_array = self.list_configurations()
else:
all = self.list_configurations()
for i in layers:
configuration_array.append(all[i])
content = container.DataContainer()
for configuration_path in configuration_array:
content_folder = self.get_configuration(configuration_path).get_layer().content_folder()
content_path = content_folder.get_current_path()
for content_file in content_folder.list_resources("", True):
source_file = utils.resourceref.join_refs([content_path, content_file])
content.add_value(content_file, source_file)
return content
class Configuration(CompositeConfiguration):
"""
A Configuration is a container that can hold several Layer objects.
"""
def __init__(self, ref="", **kwargs):
self.path = kwargs.get('path') or ref
self.namespace = kwargs.get('namespace', '')
self.name = utils.resourceref.to_objref(self.path)
super(Configuration, self).__init__(utils.resourceref.to_objref(self.path))
self.container = True
def _default_object(self, name):
return Feature(name)
def _supported_type(self, obj):
if isinstance(obj, Configuration) \
or isinstance(obj, Feature) \
or isinstance(obj, Data) \
or isinstance(obj, ConfigurationProxy) \
or isinstance(obj, View) \
or isinstance(obj, Base):
return True
else:
return False
def _dict(self):
"""
Return the public variables in a dictionary
"""
dict = {}
for key in self.__dict__.keys():
if key.startswith('_'):
continue
else:
dict[key] = self.__dict__[key]
dict['namespace'] = self.namespace
return dict
def get_name(self):
"""
Return the name of the configuration
"""
return self.name
def set_name(self, name):
"""
Set the name
"""
self.name = name
def get_path(self):
"""
Return the path of the configuration resource
"""
return self.path
def set_path(self, path):
"""
Set the path of the configuration resource, and update the name and ref to correspond
"""
self.path = path
#self.name = utils.resourceref.to_objref(self.path)
self.set_ref(utils.resourceref.to_objref(self.path))
#@property
def get_full_path(self):
"""
Return the path of the configuration resource
"""
try:
parentconfig = self._find_parent(type=Configuration)
parent_path = utils.resourceref.get_path(parentconfig.get_path())
except exceptions.NotFound:
parent_path = ""
return utils.resourceref.join_refs([parent_path, self.path])
def get_layer(self):
"""
Get the layer object where this Configuration is located.
"""
if not hasattr(self, "layer"):
layerpath = utils.resourceref.get_path(self.get_path())
# hardcoded removal of confml folder from the layer path it is there
layerpath = utils.resourceref.remove_end(layerpath, '/confml')
self.layer = Layer(self.get_storage(), layerpath)
""" Add the sublayers to this layer if they are different from this configuration """
for configpath in self.list_configurations():
sublayer_path = utils.resourceref.get_path(self.get_configuration(configpath).get_full_path())
sublayer_path = utils.resourceref.remove_end(sublayer_path, '/confml')
if sublayer_path != utils.resourceref.get_path(self.get_path()):
self.layer.add_layer(self.get_configuration(configpath).get_layer())
return self.layer
def set_namespace(self, namespace):
"""
@param namespace: The new namespace of the object
"""
self._namespace = namespace
#self.root.set_namespace(namespace)
def get_namespace(self):
"""
@return: The reference of the object.
"""
return self._namespace
def del_namespace(self):
"""
@return: The reference of the object.
"""
self._namespace = None
namespace = property(get_namespace, set_namespace, del_namespace)
def list_resources(self, empty_folders=False):
"""
List all resources used in this configuration
"""
"""
1. First ensure that all configuration resource files are added
2. Then add all layer resources
3. Make the list distinct
"""
resources = [self.get_full_path()]
for config in self._traverse(type=Configuration):
resources.append(config.get_full_path())
layer = self.get_layer()
for resref in layer.list_all_resources(empty_folders):
resources.append(utils.resourceref.join_refs([layer.get_current_path(), resref]))
return utils.distinct_array(resources)
def get_resource(self, ref, mode="r"):
"""
Get the given resource as a Resource object. The resource is searched relative to the
Configuration path, e.g. Configuration('test/foo/root.confml') => searches from 'test/foo'.
@param ref: the reference path to the requested resource
@return: a instance of Resource.
"""
mypath = utils.resourceref.get_path(self.path)
myref = utils.resourceref.join_refs([mypath, ref])
return self.get_storage().open_resource(myref, mode)
def get_all_resources(self):
"""
Get all resources in resource list of Resource objects
"""
resources = []
res_list = self.list_resources()
for res in res_list:
resources.append(self.get_storage().open_resource(res))
return resources
def get_root_resource(self):
"""
Get the configuration reference resource.
"""
return self.get_storage().open_resource(self.get_path())
def get_feature(self, ref):
"""
Get a feature object by its reference.
@param ref: The reference to the feature object.
@return: A Feature object
"""
return self._get(ref)
def add_feature(self, feature, namespace=""):
"""
Add a feature object to the configuration.
@param feature: The Feature object to add.
@param namespace: The sub namespace for the feature.
e.g. to add fea2 under fea1 add_feature(fea2, 'fea1')
@return: None
"""
self._add_to_path(namespace, feature)
def remove_feature(self, ref):
"""
remove feature by its reference
@param ref:
"""
self._remove(ref)
def list_features(self):
"""
List immediate features found under the this configuration (the top nodes).
The features are also available via the _default_view of the configuration.
@return: a list of feature references.
"""
return [fea.get_ref() for fea in self._objects(type=Feature)]
def list_all_features(self):
"""
List all features found under the this configuration. The features are also
available via the _default_view of the configuration.
@return: a list of feature references.
"""
return [fea.fqr for fea in self._traverse(type=Feature)]
def add_data(self, data, policy=container.REPLACE):
"""
Add a data object to this configuration object.
@param data: The Data object to add.
@return: None
"""
if not self._has(data.attr):
self._add(DataContainer(data.attr, container=True))
(namespace, name) = utils.dottedref.psplit_ref(data.get_fearef())
self._get(data.attr)._add_to_path(namespace, data, policy)
def get_data(self, ref):
"""
Get a data object by its reference.
@param ref: The reference to the data object.
@return: A Data object
"""
return self.data._get(ref)
def remove_data(self, ref):
"""
remove feature by its reference
@param ref:
"""
self.data._remove(ref)
def list_datas(self):
"""
List all datas found under the this configuration.
@return: a list of Data references.
"""
if self._has('data'):
return [dataelem.fqr for dataelem in self.data._objects(type=Data)]
else:
return []
def get_datas(self):
"""
List immediate datas found under the this configuration (the top nodes).
@return: a list of Data references.
"""
if self._has('data'):
return [dataelem for dataelem in self.data._objects(type=Data)]
else:
return []
def list_all_datas(self):
"""
List all Data elements found under the this configuration (or subconfigurations).
@return: a list of Data references.
"""
return [dataelem.fqr for dataelem in self._traverse(type=Data)]
def get_all_datas(self):
"""
List all Data elements found under the this configuration (or subconfigurations).
@return: a list of Data references.
"""
return [dataelem for dataelem in self._traverse(type=Data)]
def list_leaf_datas(self):
"""
List all leaf Data elements (i.e. actually modified settings) found under this configuration (or subconfigurations).
@return: A list of Data references.
"""
return [dataelem.fqr for dataelem in self._find_leaves(type=Data)]
def get_leaf_datas(self):
"""
Get all leaf Data elements (i.e. actually modified settings) found under this configuration (or subconfigurations).
@return: A list of Data objects.
"""
return [dataelem for dataelem in self._find_leaves(type=Data)]
def get_view(self, ref):
"""
Get a view object by its reference.
@param ref: The reference to the view object.
@return: A View object
"""
# Populate the view object before returning it
view = self._get(ref)
view.populate()
return view
def add_view(self, viewname):
"""
Add a view object to the configuration.
@param viewname: The name of the view to add.
@return: None
"""
return self._add(View(viewname))
def remove_view(self, ref):
"""
Remove a view object from the configuration.
@param ref: The reference to the View.
@return: None
@raise NotFound: when view is not found.
"""
return self._remove(ref)
def list_views(self):
"""
List all views found under the this configuration.
@return: a list of view references.
"""
return [view._path(self) for view in self._traverse(type=View)]
def save(self):
"""
Save the object to the permanent Storage object. Calls the save operation of
all the children.
"""
for child in self._objects():
if isinstance(child, (Configuration,ConfigurationProxy)):
child.save()
self.get_project().unload(self.get_full_path(), self)
def close(self):
"""
Close the configuration
"""
for child in self._objects():
if isinstance(child, (Configuration, ConfigurationProxy)):
child.close()
# if self.get_full_path() != "":
# self.get_project().unload(self.get_full_path(), self)
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, Feature):
self.add_feature(child)
elif isinstance(child, View):
self._add(child)
elif isinstance(child, (Data)):
self.add_data(child)
else:
super(Configuration, self).add(child)
def get_default_view(self):
"""
Get the default view from this configuration hierarchy.
This returns always the view from the Root configuration point of view.
"""
try:
parent = self._find_parent_or_default()
if parent and isinstance(parent, Configuration):
return parent.get_default_view()
else:
if not hasattr(self, '_default_view'):
self._create_default_view()
return self._default_view
except exceptions.NotFound, e:
raise e
# raise exceptions.NotFound("Default View is not found! No root configuration?")
def recreate_default_view(self):
try:
parent = self._find_parent_or_default()
if parent and isinstance(parent, Configuration):
parent.recreate_default_view()
else:
self._create_default_view()
except exceptions.NotFound, e:
raise e
# raise exceptions.NotFound("Default View is not found! No root configuration?")
def _create_default_view(self):
# Rebuild the default view for this Configuration
self._default_view = View("_default_view", data=True)
self._default_view._parent= self
# First add all features of the configuration to the view.
# Then add all data elements under the features
for child in self._traverse(type=Feature):
self._default_view.add_feature(child, child.namespace)
for child in self._traverse(type=Data):
#parent_config = child._find_parent_or_default(type=Configuration)
#print "Adding data %s: fqr: %s from file %s." % (child.get_value(), child.fqr, parent_config.get_path())
try:
fea = self._default_view.get_feature(child.fqr)
fea.add_data(child)
except exceptions.NotFound, e:
data_parent_config = child._find_parent_or_default(type=Configuration)
logging.getLogger('cone').info("Warning: Feature '%s' for data in %s not found." % (child.fqr, data_parent_config.get_path()))
class ConfigurationProxy(container.LoadProxy):
"""
Configuration loading proxy. Loads the configuration from the given reference, when needed.
"""
def __init__(self, path, **kwargs):
"""
The ConfigurationProxy that represents a configuration that is included in another configuration.
@param ref: the reference to the storage resource
The ConfigurationProxy trust to get the store_interface from the parent object with get_storage() function.
"""
container.LoadProxy.__init__(self, path)
self.set('_name', utils.resourceref.to_objref(path))
def _clone(self, **kwargs):
"""
A ConfigurationProxy specific implementation for cloning.
Copies all (public) members in dictionary.
To clone call the actual object that is proxied as well if the reqursion is on.
@param recursion: Boolean to define recursion on or off
@param recursion_depth: positive integer to define recursion depth. default is -1 which will
perform recursion to all objects.
"""
dict = self._dict()
obj = self.__class__(**dict)
# handle the recursion argument
recursion = kwargs.get('recursion', False)
if recursion:
recursion_depth = kwargs.get('recursion_depth', -1)
if recursion_depth < 0 or recursion_depth > 0:
# decrease the recursion
kwargs['recursion_depth'] = recursion_depth - 1
newobj = self._get_obj()._clone(**kwargs)
obj._set_obj(newobj)
return obj
def _dict(self):
"""
Return the public variables in a dictionary
"""
dict = {}
for key in self.__dict__.keys():
if key.startswith('_'):
continue
else:
dict[key] = self.__dict__[key]
return dict
def _get_mapper(self,modelname):
"""
Return a instance of appropriate mapper for given model.
"""
return mapping.BaseMapper()
class Group(Base):
"""
A Group class. Group is used in View to group up other Group/Feature objects.
"""
def __init__(self, ref="", **kwargs):
super(Group, self).__init__(ref, **kwargs)
self.name = ref
self.support_data = kwargs.get("data", False)
def _supported_type(self, obj):
if isinstance(obj, (Group, \
Base, \
_FeatureProxy, \
FeatureLink)):
return True
else:
return False
def _default_object(self, name):
return Group(name)
def get_name(self):
"""
Return the name of the configuration
"""
return self.name
def set_name(self, name):
"""
Set the name
"""
self.name
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, (Group, \
Base, \
_FeatureProxy, \
FeatureLink)):
self._add(child)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
def get_name(self):
"""
Return the name of the configuration
"""
return self.name
def set_name(self, name):
"""
Set the name
"""
self.name = name
def add_feature(self, feature, path=""):
"""
Add feature to this Group.
"""
if not isinstance(feature, Feature):
raise exceptions.IncorrectClassError("add_feature requires instance of Feature!! Given %s" % feature)
if not self.support_data:
self._add_to_path(path, _FeatureProxy(feature._name, feature))
else:
self._add_to_path(path, _FeatureDataProxy(feature._name, feature))
def remove_feature(self, ref):
"""
remove a given feature from this view by reference.
@param ref:
"""
self._remove(ref)
def get_feature(self, ref):
"""
@param path: The path (ref) to the given feature
"""
try:
return self._get(ref)
except exceptions.NotFound:
raise exceptions.NotFound("Feature '%s' not found." % ref)
def get_features(self, ref, **kwargs):
"""
Get a list of features that match the ref.
Example1: get_features('foo.bar') would be the same as get_feature('foo.bar'), but this returns
always a list [<Feature>].
Example2: get_features('foo.*') would try to retrieve a list of all foo children.
Example3: get_features('foo.*', type='') would try to retrieve a list of all foo children,
that have a defined type.
@param path: The path (ref) to the given feature or xpath like expression
@return: A list of features.
"""
(startref, last) = utils.dottedref.psplit_ref(ref)
startelem = self._get(startref)
if last == '**':
return [fea for fea in startelem._traverse(**kwargs)]
elif last == '*':
return [fea for fea in startelem._objects(**kwargs)]
else:
return [self._get(ref)]
def list_features(self):
"""
Return a array of all Feature children references under this object.
"""
return [fea.get_ref() for fea in self._objects(type=(_FeatureProxy))]
def list_all_features(self):
"""
Return a array of all Feature children references under this object.
"""
return [fea.fqr for fea in self._traverse(type=(_FeatureProxy))]
def add_group(self, groupname):
"""
"""
self._add(Group(groupname))
def remove_group(self, ref):
"""
remove a given feature from this view by reference.
@param ref:
"""
self._remove(ref)
def get_group(self, ref):
"""
@param path: The path (ref) to the given feature
"""
return self._get(ref)
def list_groups(self):
"""
"""
return [group.get_name() for group in self._objects(type=Group)]
def populate(self):
"""
Populate or fetch the link to the actual feature for this featureproxy.
This method fetches the feature to the _obj member variable and populates also
subfeatures.
"""
for child in self._traverse(type=FeatureLink):
child.populate()
class View(Group):
"""
A View class. View is intended to create new or different hierarchies of existing features. A View can contain Group and/or Feature objects.
"""
def __init__(self, ref="", **kwargs):
super(View, self).__init__(self.to_ref(ref), **kwargs)
self.name = ref
self.container = True
@classmethod
def to_ref(cls, ref):
"""
return a view reference converted from name
"""
return ref.replace('.', '').replace('/', '')
class Feature(Base):
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
PROPERTIES = ['value']
def __init__(self, ref="", **kwargs):
super(Feature, self).__init__(ref, **kwargs)
self.name = kwargs.get('name', ref)
self.type = kwargs.get('type', None)
self._dataproxy = None
def __copy__(self):
dict = {}
for key in self.__dict__.keys():
if key.startswith('_') or key == 'ref':
continue
else:
dict[key] = self.__dict__[key]
fea = self.__class__(self.ref, **dict)
return fea
def _supported_type(self, obj):
# For now support added for desc element via support for Base
if isinstance(obj, (Feature, Option, Base)):
return True
else:
return False
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, Feature):
self.add_feature(child)
elif isinstance(child, Option):
self._add(child, policy)
elif isinstance(child, Base):
self._add(child, policy)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
def get_name(self):
"""
Return the name of the configuration
"""
return self.name
def set_name(self, name):
"""
Set the name
"""
self.name = name
def get_type(self):
return self.type
def set_type(self, type):
self.type = type
def add_feature(self, feature, path=""):
"""
@param feature: The Feature object to add
"""
configuration = self.find_parent(type=Configuration)
if configuration:
feapath = utils.dottedref.join_refs([self._path(configuration), path])
configuration.add_feature(feature, feapath)
else:
self._add_to_path(path, feature)
def get_feature(self, path):
"""
@param path: The path (ref) to the given feature
"""
return self._get(path)
def remove_feature(self, ref):
"""
remove a given feature from this view by reference.
@param ref:
"""
configuration = self.find_parent(type=Configuration)
if configuration:
fullfqr = utils.dottedref.join_refs([self._path(configuration), ref])
configuration.remove_feature(fullfqr)
else:
self._remove(ref)
def list_features(self):
"""
Return a array of all Feature children references under this object.
"""
return [fea.get_ref() for fea in self._objects(type=Feature)]
def list_all_features(self):
"""
Return a array of all Feature children references under this object.
"""
return [fea._path(self) for fea in self._traverse(type=Feature)]
def add_option(self, option):
"""
@param option: option object
"""
if not isinstance(option, Option):
raise TypeError("%r is not an instance of Option!" % option)
self._add(option)
def create_option(self, name, value):
"""
@param name: option name
@param value: option value
"""
self._add(Option(name, value))
def get_option(self, ref):
"""
@param name: The option reference of the option (as returned by list_options())
"""
real_ref = 'opt_' + ref
obj = self._get(real_ref)
if not isinstance(obj, Option):
raise TypeError('Object %r is not an instance of Option (%r instead)' % (real_ref, type(obj)))
return obj
def remove_option(self, ref):
"""
remove a given option from this feature by option reference.
"""
real_ref = 'opt_' + ref
obj = self._get(real_ref)
if not isinstance(obj, Option):
raise TypeError('Trying to remove option with ref %r, but object with ref %r is not an instance of Option (%s instead)' % (ref, real_ref, type(obj)))
self._remove(real_ref)
def list_options(self):
"""
Return a array of all Option children references under this object.
"""
# Return option refs without the leading 'opt_'
return [opt.ref[4:] for opt in self._objects(type=Option)]
def get_value(self, attr=None):
"""
Get the current value of the feature
@param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
"""
# Do not allow getting of setting of sequence values directly with Feature object
if not self.is_sequence():
return self.get_value_cast(self.dataproxy._get_value(attr), attr)
else:
""" get the feature specific data from sequence => a column of data table """
coldata = []
feasequence = self.get_sequence_parent()
feapath = self._path(feasequence)
for row in feasequence.data:
feadata = row.get_feature(feapath)
coldata.append(feadata.value)
return coldata
def set_value(self, value, attr=None):
"""
Set the current value for this feature. Set the value on the topmost layer.
@param value: the value to set
"""
# Do not allow setting of setting of sequence values directly with Feature object
if not self.is_sequence():
value = self.set_value_cast(value, attr)
self.dataproxy._set_value(value, attr)
def del_value(self, attr=None):
"""
Delete the topmost value for this feature.
"""
if not self.is_sequence():
self.dataproxy._del_value(attr)
def get_value_cast(self, value, attr=None):
"""
A function to perform the value type casting in get operation
@param value: the value to cast
@param attr: the attribute which is fetched from model (normally in confml either None='data' or 'rfs')
"""
return value
def set_value_cast(self, value, attr=None):
"""
A function to perform the value type casting in the set operation
@param value: the value to cast
@param attr: the attribute which is fetched from model (normally in confml either None='data' or 'rfs')
"""
return value
def get_original_value(self, attr=None):
"""
Get the current value of the feature
@param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
"""
# Do not allow getting of setting of sequence values directly with Feature object
if not self.is_sequence():
return self.dataproxy._get_value(attr)
else:
""" get the feature specific data from sequence => a column of data table """
coldata = []
feasequence = self.get_sequence_parent()
feapath = self._path(feasequence.data)
for row in feasequence.data:
feadata = row.get_feature(feapath)
coldata.append(feadata.value)
return coldata
def add_data(self, data):
"""
Add a data value.
@param data: A Data object
"""
try:
return self.dataproxy._add_data(data)
except AttributeError:
self.dataproxy = self.get_default_view().get_feature(self.get_fullfqr())
return self.dataproxy._add_data(data)
def get_data(self, attr=None):
"""
Helper function to get the topmost data value from the default view.
@param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
"""
try:
return self.dataproxy._get_data(attr)
except AttributeError:
self.dataproxy = self.get_default_view().get_feature(self.get_fullfqr())
return self.dataproxy._get_data(attr)
def get_datas(self):
"""
Helper function to get the data values from the default view.
"""
try:
return self.dataproxy._get_datas()
except AttributeError:
self.dataproxy = self.get_default_view().get_feature(self.get_fullfqr())
return self.dataproxy._get_datas()
def get_valueset(self):
"""
Get the ValueSet object for this feature, that has the list of available values.
"""
if self.get_type() == 'boolean':
return ValueSet([True, False])
elif self.get_type() == 'int':
return ValueRange(0, sys.maxint)
elif self.get_type() == 'string':
return ValueRe('.*')
elif self.get_type() in ('selection', 'multiSelection'):
values = []
for opt in self._objects(type=Option):
v = opt.get_value()
if v is not None: values.append(v)
return ValueSet(values)
def is_sequence(self):
""" Return true if the feature is a sequence or part of a sequence """
try:
return self._parent.is_sequence()
except AttributeError:
return False
def get_sequence_parent(self):
""" Try to get a FeatureSequence object for this Feature if it is found """
try:
return self._parent.get_sequence_parent()
except AttributeError:
return None
def getdataproxy(self):
if self._dataproxy == None:
self.dataproxy = self.get_default_view().get_feature(self.get_fullfqr())
return self._dataproxy
def setdataproxy(self, value): self._dataproxy = value
def deldataproxy(self): self._dataproxy = None
dataproxy = property(getdataproxy, setdataproxy, deldataproxy)
value = property(get_value, set_value, del_value)
class FeatureSequence(Feature):
POLICY_REPLACE = 0
POLICY_APPEND = 1
POLICY_PREPEND = 2
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
dataelem_name = '?datarows'
template_name = '?template'
def __init__(self, ref="", **kwargs):
super(FeatureSequence, self).__init__(ref)
self.name = kwargs.get('name', ref)
self.type = 'sequence'
self.mapKey = kwargs.get('mapKey')
self.mapValue = kwargs.get('mapValue')
self._templatedata = None
def _get_policy(self, data):
"""
parse the policy from a policy string and return a constant
@return: POLICY_* constant
"""
try:
containerdata = utils.get_list(data._get_parent()._get(data.get_ref()))
firstdata = containerdata[0]
except AttributeError:
firstdata = data
if firstdata.policy == 'append':
return self.POLICY_APPEND
elif firstdata.policy == 'prefix':
return self.POLICY_PREPEND
elif firstdata == data:
# otherwise the policy is either replace or undefined
# (firstdata.policy == 'replace' or firstdata.policy == ''):
return self.POLICY_REPLACE
else:
return self.POLICY_APPEND
def _set_template_data(self, data=None):
"""
Set the template of the feature sequence
"""
# If template data is not existing, create it
if data != None:
self._templatedata = data
for feaname in self.list_features():
if self._templatedata._has(feaname):
self.get_feature(feaname)._templatedata = self._templatedata._get(feaname)
else:
subdata = Data(ref=feaname)
self.get_feature(feaname)._templatedata = subdata
self._templatedata._add(subdata)
def _add_datarow(self, dataobj=None, policy=POLICY_APPEND):
"""
Add a feature data row for a new data in this sequence
"""
if dataobj == None:
dataobj = Data(fqr=self.fqr)
elif dataobj.attr != 'data':
# Add data rows only for data objects (not e.g. RFS)
return
fea = FeatureSequenceSub(self.dataelem_name)
rowproxy = _FeatureDataProxy(fea._name, fea)
""" the imaginary features share the parent relation of the proxy objects """
self.dataproxy._add(rowproxy, policy)
fea._parent = rowproxy._parent
rowproxy._add_data(dataobj)
""" update the FeatureSequenceSub index from the index number of dataproxy """
fea._index = utils.get_list(self.dataproxy._get(self.dataelem_name)).index(rowproxy)
# Create a the subfeatures / columns for the parent feature and
# add a data element under each feature.
for feaname in self.list_all_features():
(pathto_fea, fearef) = utils.dottedref.psplit_ref(feaname)
rowproxy.add_feature(FeatureSequenceSub(fearef), pathto_fea)
subproxy = rowproxy.get_feature(feaname)
subproxy._obj._parent = subproxy._parent
if not dataobj._has(feaname):
dataobj._add_to_path(pathto_fea, Data(ref=fearef))
subproxy._add_data(dataobj._get(feaname))
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, Feature):
self.add_feature(child)
elif isinstance(child, Option):
self._add(child)
elif isinstance(child, Base):
self._add(child)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
def add_sequence(self, data=None, policy=POLICY_APPEND):
"""
Add a feature data row for a new data in this sequence
"""
self._add_datarow(None, policy)
# set the initial data if it is given
rowproxy = utils.get_list(self.dataproxy._get(self.dataelem_name))[-1]
if data != None:
for index in range(len(data)):
rowproxy[index].set_value(data[index])
# add the new data sequence/row to the last configuration layer
dataobj = rowproxy._get_data()
last_config = self.get_root_configuration().get_last_configuration()
last_config.add_data(dataobj, container.APPEND)
return dataobj
def set_template(self, data=None):
"""
Set the template of the feature sequence
"""
# If template data is not existing, create it
if self._templatedata == None:
self._set_template_data(Data(ref=self.ref, template=True))
# Add the template data to parent config
pconfig = self.find_parent(type=Configuration)
pconfig.add_data(self._templatedata)
if data != None:
templdatas = self._templatedata._objects()
for index in range(len(data)):
templdatas[index].set_value(data[index])
def get_template(self):
"""
Add a feature data row for a new data in this sequence
"""
#self._set_template(None)
# set the initial data if it is given
if self._templatedata:
return [data.get_value() for data in self._templatedata._objects()]
else:
return None
def get_data(self):
"""
Helper function to get the topmost data value from the default view.
"""
if self.dataproxy._has(self.dataelem_name):
return utils.get_list(self.dataproxy._get(self.dataelem_name))
else:
return []
def add_data(self, data):
"""
Add a data value.
@param data: A Data object
"""
# Skip template data adding
if data.template:
self._set_template_data(data)
else:
# Get the data index
self._add_datarow(data, self._get_policy(data))
return
def get_map_key(self):
"""
Returns the setting that corresponds to mapKey attribute of this sequence feature.
"""
if self.mapKey != None:
mapkey = self.get_feature(self.mapKey)
return mapkey
else:
return None
def get_map_key_value(self,key):
"""
Returns the setting that corresponds to mapKey attribute of this sequence feature.
"""
value = None
if self.mapKey != None and self.mapValue != None:
data = self.get_data()
for item in data:
kv = item.get_feature(self.mapKey).get_value()
if kv == key:
value = item.get_feature(self.mapValue).get_value()
return value
def get_map_value(self):
"""
Returns the setting that corresponds to mapValue attribute of this sequence feature.
"""
if self.mapValue != None:
mapvalue = self.get_feature(self.mapValue)
return mapvalue
else:
return None
def get_value(self, attr=None):
"""
Helper function to get the topmost data value from the default view.
"""
datatable = self.get_data()
rettable = []
for row in datatable:
rowvalues = row.value
rettable.append(rowvalues)
return rettable
def set_value(self, value, attr=None):
"""
Set the current value for this feature. Set the value on the topmost layer.
@param value: the value to set. The value must be a two dimensional array (e.g. matrix)
"""
# sets the first data element to replace policy
try:
self.add_sequence(value.pop(0), self.POLICY_REPLACE)
# ignore the index error of an empty list
except IndexError:
pass
for row in value:
self.add_sequence(row)
def is_sequence(self):
""" Return always true from a sequence object """
return True
def get_sequence_parent(self):
""" Return this object as a sequence parent """
return self
value = property(get_value, set_value)
data = property(get_data)
class FeatureSequenceCell(Feature):
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
def __init__(self, ref="", **kwargs):
super(Feature, self).__init__(ref)
self.name = kwargs.get('name', ref)
self.type = 'seqcell'
def get_value(self, attr=None):
"""
Get the current value of the feature
@param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
"""
return self.dataproxy._get_value(attr)
def set_value(self, value):
"""
Set the current value for this feature. Set the value on the topmost layer.
@param value: the value to set
"""
# The sequence cell only updates the latest value in the proxy
self.dataproxy.get_data().set_value(value)
value = property(get_value, set_value)
class FeatureSequenceSub(Feature):
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
def __init__(self, ref="", **kwargs):
super(Feature, self).__init__(ref)
self.name = kwargs.get('name', ref)
self.type = 'subseq'
self._index = 0
def get_index(self):
"""
@return : the index of the data element for sequential data defined inside the same configuration.
0 for normal data.
"""
return self._index
def set_value(self, value, attr=None):
"""
Set the current value for this sequence row.
@param value: the value row to set
"""
if utils.is_list(value):
for subindex in range(0, len(value)):
self.dataproxy[subindex].get_data().set_value(value[subindex])
else:
self.dataproxy.get_data().set_value(value)
def get_value(self, attr=None):
"""
Set the current value for this feature. Set the value on the topmost layer.
@param value: the value to set
"""
# dataproxy = self.get_default_view().get_feature(self.get_fullfqr())
# The sequence cell only updates the latest value in the proxy
childdatas = self.dataproxy._objects()
if len(childdatas) > 0:
return [subdata.value for subdata in childdatas]
else:
return self.dataproxy._get_value(attr=attr)
value = property(get_value, set_value)
class FeatureLink(Base):
"""
A _FeatureProxy class. _FeatureProxy is the object that is added to View as a
link to the actual Feature object.
"""
def __init__(self, link="", **kwargs):
# Store the fully qualified reference to this object
self.link = link
ref = link.replace('.', '_')
super(FeatureLink, self).__init__(ref)
self._obj = None
self._populated = False
@property
def fqr(self):
return self.link
def populate(self):
"""
Populate or fetch the link to the actual feature for this featureproxy.
This method fetches the feature to the _obj member variable and populates also
subfeatures.
"""
try:
if not self._populated:
feas = self.get_default_view().get_features(self.link)
# add the found features to the parent
for fea in feas:
self._get_parent().add_feature(fea._obj)
except exceptions.NotFound, e:
parent_view = self._find_parent_or_default(type=View)
view_name = parent_view.get_name()
logging.getLogger('cone').info("Warning: Feature '%s' in view '%s' not found." % (self.link, view_name))
class _FeatureProxy(container.ObjectProxyContainer, Base):
"""
A _FeatureProxy class. _FeatureProxy is the object that is added to View as a
link to the actual Feature object.
"""
def __init__(self, ref="", obj=None, **kwargs):
super(_FeatureProxy, self).__init__(obj, ref)
Base.__init__(self, ref)
self.support_data = False
def __getattr__(self, name):
"""
First check if the requested attr is a children then
direct all not found attribute calls to the sub object getattr
"""
try:
return self.__dict__['_children'][name]
except KeyError:
return getattr(self._obj, name)
def __getitem__(self, index):
return self._objects()[index]
def __setitem__(self, index, value):
raise exceptions.NotSupported()
def __delitem__(self, index):
item = self.__getitem__(index)
return self._remove(item.get_ref())
def __len__(self):
return len(self._order)
def _supported_type(self, obj):
if isinstance(obj, _FeatureProxy):
return True
else:
return False
def _default_object(self, name):
return Group(name)
def _set_parent(self, newparent):
"""
@param newparent: The new parent object
@return: None
"""
self._parent = newparent
def add_feature(self, feature, path=""):
"""
"""
if not isinstance(feature, Feature):
raise exceptions.IncorrectClassError("add_feature requires instance of Feature!! Given %s" % feature)
if not self.support_data:
self._add_to_path(path, _FeatureProxy(feature._name, feature))
else:
self._add_to_path(path, _FeatureDataProxy(feature._name, feature))
def remove_feature(self, ref):
"""
remove a given feature from this view by reference.
@param ref:
"""
self._remove(ref)
def get_feature(self, path):
"""
@param path: The path (ref) to the given feature
"""
return self._get(path)
def list_features(self):
"""
Return a array of all Feature children references under this object.
"""
return self._list()
def list_all_features(self):
"""
Return a array of all Feature children references under this object.
"""
return [fea._path(self) for fea in self._traverse(type=_FeatureProxy)]
def populate(self):
"""
Dummy implementation of populate
"""
pass
class _FeatureDataProxy(_FeatureProxy):
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
DEFAULT_KEY = 'data'
def __init__(self, ref="", obj=None, **kwargs):
# Initialize _obj to None, because __getattr__(), __setattr__()
# and __delattr__() access it.
# Note that we cannot use self._obj = None here, since that would
# invoke __setattr__(), causing a kind of a chicken-and-egg problem
object.__setattr__(self, '_obj', None)
super(_FeatureDataProxy, self).__init__(ref, obj)
self.support_data = True
""" Create the data container of all types of data. Add the key for the default key. """
self.defaultkey = _FeatureDataProxy.DEFAULT_KEY
self.datas = {self.defaultkey : []}
def __getattr__(self, name):
"""
"""
if object.__getattribute__(self, '_obj') is not None:
self._obj.dataproxy = self
if name in Feature.PROPERTIES:
return getattr(self._obj, name)
else:
return super(_FeatureDataProxy, self).__getattr__(name)
def __setattr__(self, name, value):
"""
"""
if object.__getattribute__(self, '_obj') is not None:
self._obj.dataproxy = self
if name in Feature.PROPERTIES:
return setattr(self._obj, name, value)
else:
super(_FeatureDataProxy, self).__setattr__(name, value)
def __delattr__(self, name):
"""
"""
if name in Feature.PROPERTIES:
return delattr(self._obj, name)
else:
return super(_FeatureDataProxy, self).__delattr__(name)
def _add_data(self, data):
"""
Add a data value.
@param data: A Data object
"""
try:
self.datas[data.attr].append(data)
except KeyError:
""" Create a list object for missing attribute """
self.datas[data.attr] = []
self.datas[data.attr].append(data)
def _get_data(self, attr=None):
"""
Get the data value. in sequence setting cases returns an array of data.
"""
dataattr = attr or self.defaultkey
try:
if len(self.datas[dataattr]) > 0:
return self.datas[dataattr][-1]
else:
return None
except KeyError:
""" return None for missing attribute """
return None
def _get_datas(self, attr=None):
"""
Get the entire data array.
"""
dataattr = attr or self.defaultkey
return self.datas[dataattr]
def _get_value(self, attr=None):
"""
Get the topmost data value.
"""
if self._get_data(attr):
return self._get_data(attr).get_value()
else:
return None
def _set_value(self, datavalue, attr=None):
"""
Set the value for the feature the last configuration in the current hierarchy
@param value: The value for the feature.
@return: The created Data object.
"""
# Make sure that data value exists only once the the last configuration layer
# So if last_data exists on last layer, update the value of that data element.
# otherwise create a new data elem to the topmost layer
dataobj = self._get_data(attr)
last_config = self.get_root_configuration().get_last_configuration()
if dataobj and dataobj.find_parent(type=Configuration) == last_config:
dataobj.set_value(datavalue)
else:
dataobj = Data(fqr=self.fqr, value=datavalue, attr=attr)
last_config.add_data(dataobj)
self._add_data(dataobj)
return dataobj
def _del_value(self, attr=None):
"""
Remove the
"""
data = self._get_data(attr)
if data:
dataattr = attr or self.defaultkey
parentconfig = data.find_parent(type=Configuration)
if parentconfig:
parentconfig.remove_data(data.get_fullfqr())
del self.datas[dataattr][-1]
def _get_values(self, attr=None):
"""
Get the topmost data value.
"""
dataattr = attr or self.defaultkey
return [dataelem.get_value() for dataelem in self.datas[dataattr]]
class DataBase(Base):
def __init__(self, ref="", **kwargs):
super(DataBase, self).__init__(ref, **kwargs)
def _supported_type(self, obj):
if isinstance(obj, (DataContainer, DataBase)):
return True
else:
return False
def _default_object(self, name):
return Data(ref=name)
def count(self):
return len(self._objects())
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
proxy function that call the correct add function based on the child objects class.
Example: obj.add(Feature("test")), actually obj.add_feature(Feature("test"))
@param child: the child object to add
@raise IncorrectClassError: if the given class cannot be added to this object.
"""
if isinstance(child, (Data)):
self._add(child, container.APPEND)
else:
raise exceptions.IncorrectClassError("Cannot add %s object to %s" % (child, self))
class DataContainer(DataBase):
def __init__(self, ref="", **kwargs):
super(DataContainer, self).__init__(ref, **kwargs)
class Data(DataBase):
"""
The data element can contain any data setting for a feature. The data element can be
a value definition for any type of data. It basically just links some data to a feature.
The default Data attribute is 'data', but it can be any string. For example current use case
is 'rfs'.
"""
def __init__(self, **kwargs):
"""
@param ref: the reference to the feature. E.g. foo
@param fqr: the full reference to the feature. E.g. 'foo.bar'
@param value: the value of the data
@param attr: the attribute which the Data object defines. e.g. default is 'data'. But could be
for example 'rfs'
"""
name = kwargs.get('ref', '')
self.fearef = kwargs.get('fqr', None)
if self.fearef:
(namespace, name) = utils.dottedref.psplit_ref(self.fearef)
super(Data, self).__init__(name)
self.value = kwargs.get('value', None)
self.attr = kwargs.get('attr') or 'data'
self.policy = kwargs.get('policy', '')
self.template = kwargs.get('template', False)
self.map = kwargs.get('map')
def get_fearef(self):
if self.fearef:
return self.fearef
else:
return self.fqr
def get_value(self):
if self.map != None:
ref = utils.resourceref.to_dref(self.get_map_ref())
key = self.get_map_key_value()
dview = self.get_root_configuration().get_default_view()
fea = dview.get_feature(ref)
return fea.get_map_key_value(key)
else:
return self.value
def get_map(self):
return self.map
def set_map(self, map):
self.map = map
if self.value:
#Either value or mapping can be defined. Not both.
self.value = None
def get_map_ref(self):
if self.map != None:
return utils.DataMapRef.get_feature_ref(self.map)
else:
return None
def get_map_key_value(self):
if self.map != None:
return utils.DataMapRef.get_key_value(self.map)
else:
return None
def set_value(self, value):
self.value = value
if self.map:
#Either value or mapping can be defined. Not both.
self.map = None
def get_policy(self): return self._policy
def set_policy(self, value): self._policy = value
def del_policy(self): self._policy = None
policy = property(get_policy, set_policy, del_policy)
class ValueSet(sets.Set):
"""
A value set object to indicate a set of possible values for a feature.
e.g. A boolean feature ValueSet([True, False])
"""
def __init__(self, initial_set=None):
super(ValueSet, self).__init__(initial_set or [])
class ValueRange(object):
"""
"""
def __init__(self, fromvalue, tovalue, step=1):
self.fromvalue = fromvalue
self.tovalue = tovalue
self.step = step
def __contains__(self, value):
return self.fromvalue <= value and value <= self.tovalue and (value-self.fromvalue) % self.step == 0
class ValueRe(object):
"""
"""
def __init__(self, regexp):
self.regexp = re.compile(regexp)
def __contains__(self, value):
if isinstance(value, str):
return self.regexp.match(value)
else:
return False
class Option(Base):
"""
Confml option class.
"""
def __init__(self, name, value, **kwargs):
super(Option, self).__init__(Option.to_optref(value, kwargs.get('map', None)))
self.name = name
self.value = value
self.map = kwargs.get('map', None)
self.relevant = kwargs.get('relevant', None)
@classmethod
def to_optref(cls, value, map):
"""
@return: An option reference converted from value or map, depending
on which one is not None.
"""
if value is not None:
return "opt_value_%s" % value.replace('.', '').replace('/', '').replace(' ', '')
elif map is not None:
return "opt_map_%s" % map.replace('.', '').replace('/', '').replace(' ', '')
else:
raise ValueError("Both value and map are None!")
def get_name(self):
return self.name
def get_value(self):
return self.value
def __cmp__(self, other):
try:
ref = getattr(other, 'ref')
except AttributeError:
ref = other
if self.ref < ref:
return -1
elif self.ref == ref:
return 0
else:
return 1
class Storage(object):
"""
A general base class for all storage type classes
"""
""" File open modes """
MODE_UNKNOWN= -1
MODE_READ = 1
MODE_WRITE = 2
MODE_APPEND = 3
MODE_DELETE = 4
def __init__(self, path):
"""
@param path: the reference to the root of the storage.
"""
self.rootpath = path
self.curpath = ""
self.container = True
self.__opened_res__ = {}
def __opened__(self, res):
"""
Internal function to add a newly opened Resource object to the list of open resources.
@param res: The resource object
"""
if self.__opened_res__.has_key(res.path):
self.__opened_res__[res.path].append(res)
else:
self.__opened_res__[res.path] = [res]
def __closed__(self, res):
"""
Internal function to remove a Resource object from the list of open resources.
@param res: The resource object to remove
@raise StorageException if the given resource object is not found:
"""
try:
self.__opened_res__[res.path].remove(res)
if len(self.__opened_res__[res.path]) == 0:
del self.__opened_res__[res.path]
except KeyError, e:
raise exceptions.StorageException("No such %s open resource! %s" % (res, e))
def __has_open__(self, ref):
"""
Internal function to find out if any Resource objects are open from given ref.
@param ref: The resource ref
@return: True if resources found. Otherwise False.
"""
return self.__opened_res__.has_key(ref)
def __get_open__(self, path):
"""
Internal function to get all resource opened on a certain ref .
@param ref: The resource ref
@return: A list of open resources. Empty list if nothing is found
"""
if self.__has_open__(path):
# return a copy of currently open resources
return self.__opened_res__[path][:]
else:
return []
def __has_resource__(self, res):
"""
Internal function to find out if the given Resource objects is open in this storage.
@param ref: The resource object
@return: True if resources found. Otherwise False.
"""
try:
res = self.__opened_res__[res.path].index(res)
return True
except KeyError, e:
return False
@classmethod
def open(cls,path, mode="r", **kwargs):
"""
Class method for opening an instance of Storage
@param path: path to storage, which will determine what type of storage is initiated.
"""
# import all storage instances
from cone.storage import storages
for storagename in storages:
storagemodule = 'cone.storage.'+storagename
module = __import__(storagemodule)
for storage_class in utils.all_subclasses(Storage):
if storage_class.supported_storage(path):
if hasattr(storage_class, '__open__'):
return storage_class.__open__(path, mode, **kwargs)
else:
return storage_class(path, mode, **kwargs)
obj = Storage(path)
return obj
@classmethod
def supported_storage(cls, path):
"""
Class method for determing if the given clas supports a storage by given path.
E.g. foo.zip, foo.cpd, foo/bar, http://foo.com/
@param path:
@return: Boolean value. True if the storage of the path is supported. False if not.
"""
return False
def set_path(self, path):
"""
"""
self.rootpath = path
def get_path(self):
"""
"""
return self.rootpath
def set_current_path(self, path):
"""
@param path: the current path under the Storage.
"""
self.curpath = utils.resourceref.remove_end_slash(utils.resourceref.remove_begin_slash(path))
def get_current_path(self):
"""
get the current path under the Storage.
"""
return self.curpath
def close(self):
"""
Close the repository, which will save and close all open resources.
"""
for openref in self.__opened_res__.keys():
for res in self.__get_open__(openref):
self.close_resource(res)
def save(self):
"""
Flush changes from all resources to the repository.
"""
for openref in self.__opened_res__.keys():
for res in self.__get_open__(openref):
self.save_resource(res)
def open_resource(self, path, mode="r"):
"""
Open the given resource and return a File object.
@param path : reference to the resource
@param mode : the mode in which to open. Can be one of r = read, w = write, a = append.
raises a NotResource exception if the ref item is not a resource.
"""
raise exceptions.NotSupportedException()
def delete_resource(self, path):
"""
Delete the given resource from storage
@param path: reference to the resource
raises a NotSupportedException exception if delete operation is not supported by the storage
"""
raise exceptions.NotSupportedException()
def close_resource(self, path):
"""
Close a given resource instance. Normally this is called by the Resource object
in its own close.
@param path the reference to the resource to close.
"""
raise exceptions.NotSupportedException()
def is_resource(self, path):
"""
Return true if the ref is a resource
@param ref : reference to path where resources are searched
"""
raise exceptions.NotSupportedException()
def list_resources(self, path, recurse=False):
"""
find the resources under certain ref/path
@param ref : reference to path where resources are searched
@param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders.
Default value is False. Set to True to enable recursion.
"""
return []
def import_resources(self, paths, storage):
"""
import resources from a list of resources to this storage
@param paths : a list of Resourse objects.
@param storage : the external storage from which files are imported.
"""
raise exceptions.NotSupportedException()
def export_resources(self, paths, storage):
"""
export resources from this storage based on a list of reference to this storage
@param path : a list of resource paths in this storage (references).
@param storage : the external storage where to export.
"""
raise exceptions.NotSupportedException()
def close_resource(self, path):
"""
Close a given resource instance. Normally this is called by the Resource object
in its own close.
@param ref the reference to the resource to close.
"""
raise exceptions.NotSupportedException()
def save_resource(self, path):
"""
Flush the changes of a given resource instance. Normally this is called by the Resource object
in its own save.
@param ref the reference to the resource to close.
"""
raise exceptions.NotSupportedException()
def create_folder(self, path):
"""
Create a folder entry to a path
@param path : path to the folder
"""
raise exceptions.NotSupportedException()
def delete_folder(self, path):
"""
Delete a folder entry from a path. The path must be empty.
@param path : path to the folder
"""
raise exceptions.NotSupportedException()
def is_folder(self, path):
"""
Check if the given path is an existing folder in the storage
@param path : path to the folder
"""
raise exceptions.NotSupportedException()
def get_mode(self, mode_str):
if mode_str.find("w") != -1:
return self.MODE_WRITE
elif mode_str.find("r") != -1:
return self.MODE_READ
elif mode_str.find("a") != -1:
return self.MODE_APPEND
elif mode_str.find("d") != -1:
return self.MODE_DELETE
else:
return self.MODE_UNKNOWN
def unload(self, path, object):
"""
Dump a given object to the storage
@param object: The object to dump to the storage, which is expected to be an instance
of Base class.
@param path: The reference where to store the object
@param object: The object instance to dump
@raise StorageException: if the given object cannot be dumped to this storage
"""
raise exceptions.NotSupportedException()
def load(self, path):
"""
Load an object from a reference.
@param path: The reference where to load the object
@raise StorageException: if the given object cannot be loaded as an object from this storage
"""
raise exceptions.NotSupportedException()
path = property(get_path, set_path)
class Resource(object):
STATE_OPEN = 0
STATE_CLOSE = 1
def __init__(self, storage, path, mode=Storage.MODE_READ):
self.storage = storage
self.path = path
self.mode = mode
self.state = Resource.STATE_OPEN
self.content_info = None
def get_path(self):
return self.path
def close(self):
"""
Close the resource.
Note1: the resource object cannot be accessed anymore after it has been closed.
Note2: the changes are not automatically saved. The save operation must be explicitly called,
to save data.
"""
self.storage.close_resource(self.path)
self.state = Resource.STATE_OPEN
def read(self, bytes=0):
"""
Read data.
"""
raise exceptions.NotSupportedException()
def write(self, string):
"""
Write data.
"""
raise exceptions.NotSupportedException()
def truncate(self, size=0):
"""
Trunkate this resource data to the given size.
@param size: The size to trunkate. Default value is zero, which make the resource empty.
"""
raise NotSupportedException()
def save(self, size=0):
"""
Save all changes to data to storage.
"""
raise NotSupportedException()
def get_mode(self):
return self.storage.get_mode(self.mode)
def get_size(self):
"""
Return the size of this resource in bytes.
Note that this does not work in write mode.
@return: The resource size in bytes:
@raise exceptions.StorageException: The resource was opened in write mode.
"""
raise exceptions.NotSupportedException()
def get_content_info(self):
"""
Return the ContentInfo class that contains content information about
resource.
"""
raise exceptions.NotSupportedException()
class ContentInfo(object):
"""
A ContentInfo object is used to describe content of Resource.
"""
logger = logging.getLogger('cone.contentinfo')
def __init__(self, mimetype, mimesubtype):
#: MIME Media type (http://www.iana.org/assignments/media-types/)
#: as a string. E.g. 'image' or 'application'
self.mimetype = mimetype
#: MIME Media subtype as a string. E.g. 'svg+xml' or 'bmp'.
self.mimesubtype = mimesubtype
@property
def content_type(self):
"""
Returns MIME Media type (http://www.iana.org/assignments/media-types/)
and subtype as a string. E.g. 'image/bmp'.
"""
return self.mimetype + '/' + self.mimesubtype
class ImageContentInfo(ContentInfo):
"""
A ImageContentInfo object is used to describe content of image Resources.
"""
def __init__(self):
ContentInfo.__init__(self, 'image', '')
class BmpImageContentInfo(ImageContentInfo):
"""
A BmpImageContentInfo object is used to describe content of bmp image
Resources.
"""
_BMP_BITS_PER_PIXEL_OFFSET_ = int('0x1C', 16)
def __init__(self, resource, data):
ContentInfo.__init__(self, 'image', 'bmp')
#: Color depth as bits per pixel.
self.color_depth = None
if (resource != None):
try:
self.color_depth = ord(data[self._BMP_BITS_PER_PIXEL_OFFSET_])
except Exception, e:
self.logger.warning("Invalid BMP-file: %s" % resource.get_path())
class Folder(object):
"""
A Folder object is a subfolder of a Storage, offering access to part of the Storages resources.
"""
def __init__(self, storage, path):
"""
Create a layer folder to the storage if it does not exist.
"""
#if not storage.is_folder(path):
# storage.create_folder(path)
self.storage = copy.copy(storage)
self.storage.set_current_path(path)
def __getattr__(self, name):
return getattr(self.storage, name)
class CompositeLayer(object):
"""
A base class for composite Configuration objects.
"""
def __init__(self, path="", **kwargs):
self.layers = kwargs.get('layers', [])
self.path = path
def add_layer(self, layer):
self.layers.append(layer)
def remove_layer(self, path):
if self.get_layer(path):
self.layers.remove(self.get_layer(path))
else:
raise exceptions.NotFound('Layer with given path %s not found!' % path)
def get_layer(self, path):
for layer in self.layers:
if layer.get_current_path() == path:
return layer
return None
def list_layers(self):
return [layer.get_current_path() for layer in self.layers]
def list_confml(self):
"""
@return: array of confml file references.
"""
lres = []
for layerpath in self.list_layers():
for respath in self.get_layer(layerpath).list_confml():
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
def list_implml(self):
"""
@return: array of implml file references.
"""
lres = []
for layerpath in self.list_layers():
for respath in self.get_layer(layerpath).list_implml():
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
def list_content(self):
"""
@return: array of content file references.
"""
lres = []
for layerpath in self.list_layers():
for respath in self.get_layer(layerpath).list_content():
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
def list_doc(self):
"""
@return: array of document file references.
"""
lres = []
for layerpath in self.list_layers():
for respath in self.get_layer(layerpath).list_doc():
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
def list_all_resources(self, empty_folders=False):
"""
Returns a list of all layer related resource paths with full path in the storage.
"""
lres = []
for layerpath in self.list_layers():
sublayer = self.get_layer(layerpath)
for respath in sublayer.list_all_resources(empty_folders):
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
class Layer(CompositeLayer):
"""
A Layer object is a subfolder of a Storage, offering access to part of the Storages resources.
"""
def __init__(self, storage, path, **kwargs):
"""
Create a layer folder to the storage if it does not exist.
@param storage: a reference to the Storage object
@param path: path for the layer
@param confml_path: optional parameter for confml files path (give in confml_path="something")
@param imlpml_path: optional parameter for implml files path (give in implml_path="something")
@param content_path: optional parameter for content files path (give in content_path="something")
@param doc_path: optional parameter for doc files path (give in doc_path="something")
"""
super(Layer, self).__init__(path, **kwargs)
#if not storage.is_folder(path):
# storage.create_folder(path)
self.storage = copy.copy(storage)
self.storage.set_current_path(path)
self.predefined = {'confml_path' : 'confml',
'implml_path' : 'implml',
'content_path' : 'content',
'doc_path' : 'doc'}
# list through all "hardcoded" paths and check whether the
# hardcoded or given path exists under this Layer.
# if it does then create a folder instance to that path
for (pretag, prevalue) in self.predefined.items():
self.predefined[pretag] = kwargs.get(pretag, prevalue)
def __getattr__(self, name):
return getattr(self.storage, name)
def list_confml(self):
"""
@return: array of confml file references.
"""
res = self.storage.list_resources(self.predefined['confml_path'], True)
res += super(Layer, self).list_confml()
return res
def list_implml(self):
"""
@return: array of implml file references.
"""
res = self.storage.list_resources(self.predefined['implml_path'], True)
res += super(Layer, self).list_implml()
return res
def list_content(self):
"""
@return: array of content file references.
"""
res = self.storage.list_resources(self.predefined['content_path'], True)
res += super(Layer, self).list_content()
return res
def list_doc(self):
"""
@return: array of document file references.
"""
res = self.storage.list_resources(self.predefined['doc_path'], True)
res += super(Layer, self).list_doc()
return res
def confml_folder(self):
cpath = self.storage.get_current_path()
spath = self.predefined['confml_path']
return Folder(self.storage, utils.resourceref.join_refs([cpath, spath]))
def implml_folder(self):
cpath = self.storage.get_current_path()
spath = self.predefined['implml_path']
return Folder(self.storage, utils.resourceref.join_refs([cpath, spath]))
def content_folder(self):
cpath = self.storage.get_current_path()
spath = self.predefined['content_path']
return Folder(self.storage, utils.resourceref.join_refs([cpath, spath]))
def doc_folder(self):
cpath = self.storage.get_current_path()
spath = self.predefined['doc_path']
return Folder(self.storage, utils.resourceref.join_refs([cpath, spath]))
def list_all_resources(self, empty_folders=False):
"""
Returns a list of all layer related resource paths with full path in the storage.
"""
lres = []
mypath = self.get_current_path()
for folderpath in sorted(self.predefined.values()):
lres += self.storage.list_resources(folderpath, recurse=True, empty_folders=empty_folders)
lres += super(Layer, self).list_all_resources(empty_folders)
return lres
def list_all_related(self, empty_folders=False):
"""
Returns a list of all (non confml) layer related resource paths with full path in the storage.
"""
lres = []
predef = self.predefined.copy()
del predef['confml_path']
mypath = self.get_current_path()
for folderpath in sorted(predef.values()):
lres += self.storage.list_resources(folderpath, recurse=True, empty_folders=empty_folders)
lres += super(Layer, self).list_all_resources(empty_folders=empty_folders)
return lres
class Rule(object):
"""
Base class for Rules in the system.
"""
def __init__(self):
raise exceptions.NotSupportedException()
class FactoryBase(object):
pass
class Factory(object):
def __getattr__(self, name):
"""
The Factory getattr find all subclasses for the Factory and searches for given attr
in those.
"""
for sub_factory in utils.all_subclasses(FactoryBase):
try:
return getattr(sub_factory(), name)
except AttributeError:
continue
raise AttributeError("type object %s has no attribute '%s'" % (self.__class__, name))
def get_mapper(modelname):
"""
Return a instance of appropriate mapper for given model.
"""
mapmodule = __import__('cone.public.mapping')
return mapmodule.public.mapping.BaseMapper()
##################################################################
class NullHandler(logging.Handler):
"""
Default handler that does not do anything.
"""
def emit(self, record):
pass
#Initialization of default logger that contains NullHandler.
logger = logging.getLogger('cone')
logger.addHandler(NullHandler())