# HG changeset patch
# User m2lahtel
# Date 1281439768 -10800
# Node ID e7e0ae78773e97d457054a2f301b1408641dee97
# Parent 87cfa131b535a582e5589a7be34fbe735f9d8c00
ConE 1.2.11 release
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/RELEASE.TXT
--- a/configurationengine/RELEASE.TXT Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/RELEASE.TXT Tue Aug 10 14:29:28 2010 +0300
@@ -1,82 +1,193 @@
- ConE the Configuration Engine
- Version cone-1.1.5
- Release Notes, 11.1.2010
+ ConE - the Configuration Engine
+ Version cone-1.2.11
+ Release Notes, 10.08.2010
Release notes:
=============
-== Version Cone-1.1.5 ==
- * Stories:
- - #792: Change ConE licenses from SFL to EPL
- - #80: As a variant engineer I want to merge my configuration so that "old" content is removed
- - #639: As a variant engineer I want that color depth argument for bmconv and mifconv is configurable
- - #703: As a SW developer I want to merge my confml and implml to global configuration project easily so that I don't need to manually copy the files and update the root files.
- - #765: As a user I want to configure cone logging output so that I can use the cone logs more efficiently
- - #785: CommandML does not support tag elements
- * Bug fixes:
- - #814: ERROR: Content folder in vascos "dummy" layer is not added to CPF when adding layer with -a option
- - #763: Selection setting option map does not work properly when option map element is used
- - #193: Different configurations open on the same project return the same setting values
- - #737: ConE merge produces incorrect output (layer root contains all data)
- - #762: ConE: option mapping does not store the mapKey/mapValue to confml file when confml output is written
- - #764: ConE must not assume that the executive process will have write access to workdir
- - #820: MultiSelection value setting does not work correctly
-
-== Version Cone-1.1.4 ==
- * Stories:
- - #663: As a variant engineer I want to get resource's size in ruleml.
- - #700: As a variant engineer I want to have a rule which automatically sets correct color depth so that I don't need to manually do that.
- * Bug fixes:
- - #701: ConE crml: cenrep txt generation with sid & capabilities produces incorrect output
+
+== Version Cone-1.2.11 ==
+* Stories
+ * #1012 As a user I want to get information whether the setting has been changed in the layer usign regex for layer name so that only needed rules are run
+ * #1022 As a RHEL 64-bit user I want to run ConE without any extra steps
+ * #1013 As a user I want use environment variables when defining convertprojectml paths
+ * #1033 Name-ID mapping with file/folder settings as mapKey or mapValue should default to using localPath
+ * #929 ConE support for confml specification 2.88 / 2.90
+ * #1035 As a cone user I want to define the data update policy so, that it would be possible to add the configuration as the first include to the target configuration
+
+* Bug fixes
+ * #1031 Copying of empty directories does not work with ContentML
+ * #1026 Contentml plugin gives memory error on big content files.
+ * #1007 As a user I want to be able to export vasco langpack customization root as such without filtering so that it works (Verifying and Code reviews)
+ * #1021 ContentML throws exception when localpath is empty
+ * #1027 Makefile generation gives error message with empty CPF and creates UDA always
+
+== Version Cone-1.2.10 ==
+* Bug fixes
+ * #999 Makefile generation does not work
+ * #1015 Merge conesub_update.py patch to trunk
+ * #1014 ContentML external input doesn't work with network drives.
+
+== Version Cone-1.2.9 ==
+* Stories
+ * #948 As a user I want run a custom script on top of cone api to investigate deprecate features from Carbon confmls
+ * #975 As a user I want to set the value of a tempFeature from the cone generate commandline with --set=TempFea=1
+ * #979 As a cone user I want to store the rule execution outputs to a confml file so that I can use the rule output configuration in some other context
+ * #994 RuleML filtering bug
+ * #995 As a ConE user I want to get the list of generation output to separate “what” list so that I can create a zip file with WinZip (using winzip include)
+ * #997 PRODBUG: # (sharp/hash) in title name causes reference
+ * #998 Extending support of ticket #948 implementation
+ * #1004 ConE export fails if option name or value is missing
+
+* Bug fixes
+ * #984 RuleML logging error the first sequence item is not shown in the log
+ * #989 Modifying sequence values via default view doesn't save the data correctly
+ * #996 Execution of /source/scripts/tests/unittest_configroot2flat.py fails in packed bat.
+ * #1001 Implementation container condition does not work if value is None
+ * #1006 Error: Initvariant merges also AMPI custvariant layers
-== Version Cone-1.1.3 ==
- * Stories:
- - #696: Factory Settings cannot be restored as phone resets every time the security code is inserted
- - #698: cone.cmd returns 0 even if ConE execution fails
- * Bug fixes:
- - #699: Remove target:core tag from existing implementations so that no content is by default generated to core image.
+== Version Cone-1.2.8 ==
+* Bug fixes
+ * #1002 ConE execution conflicts EC image creation because of pyc file creation
+
+== Version Cone-1.2.7 ==
+* Stories
+ * #991 As a cone developer I want to configure the script interface of cone command line client
+
+* Bug fixes
+ * #980 ConE --run-action=fix leaves old options in merged ConfML
+ * #976 An incorrectly defined rule element causes the entire implml file to fail
+ * #985 uses_layer() method doesn't work correctly in all cases
+ * #988 Name-ID mapping does not work if the source setting is not of string type
+ * #990 cone.cmd does not preserve caret characters (^) correctly
+ * #993 ConE in wk18 release does not generate all cenrep files for S60 asset
+
+== Version Cone-1.2.6 ==
+
+* Features:
+ * #928 As a user I want to create a rule that resolves is there any uda content in the generated layers
+ * #933 As a user I want to get image type as parameter from imaker so that factorydmprofiles can be customized
+ * #977 Remove the temp features from the refs with no output from the generation report
-== Version Cone-1.1.2 ==
+* Bug fixes:
+ * #955 NUAGE: Read error with readOnly attribute in View
+
+== Version Cone-1.2.5 ==
+* Features:
+ * #925 As a user I want to name cone generation report after CPF name
+ * #927 Rules are not working as implementations in generation report.
+ * #934 As a variant engineer I want to use Initvariant for initialization of new variant based on existing one
+ * #936 Study and integrate Jani's packvariant solution
+ * #943 As a developer I want to see validation information in S60 dashboard
+ * #944 As a user I want to filter out content files via command line paratemeters when exporting configuration so that the export size is smaller
+
+* Errors:
+ * #852 Generation report does not work with --all-layers
+ * #921 Commandml condition problem with temp variables
+ * #924 Ruleml tag filtering error
+ * #956 Destination Netvork fix to accesspoint_id_counter.py
+
+== Version Cone-1.2.4 ==
+
+== Stories ==
+ * #916 As vasco I need extra flag to create svgs to mif so that I would show startup images on my screen
+
+== Bug fixes ==
-== Version Cone-1.1.2 RC2 ==
- * Bugfixes:
- - Fixed template plug-in bug fix
-
-== Version Cone-1.1.2 RC1 ==
+ * #921 Commandml condition problem with temp variables
+ * #923 ConE documentation errors
+ * #941 Casting None error in model.set_value_case()
+
+== Version Cone-1.2.3 ==
- * Stories:
- - #588: As a user I want to run the same command on several configurations in a batch mode
- - #611: As a product integrator I want to have info report in csv format so that importing to Excel is easy to made
- - #612: As a product integrator I want to see possible values for certain setting so that default values template is easy to made
- - #643: Impml harmonization with container concept
- - #652: Content plugin refactoring to enable better use
+== Stories ==
+ * #690 As a Variant Engineer I want to read imageml documentation
+ * #789 Value report should show if a setting value is set in a specific configuration
+ * #900 As a user I want to have configuration name visible instead of configuration root name in the default settng document
+ * #913 As a cone rule script writer I want to know the output folder of the generation so that I can generate a output file inside the rule script1
+ * #931 As a user I want to define name for layer root files in convert project so that the layer name can be shown in nuage
+
+== Bug fixes ==
+ * #192 Values inside sequence setting values are not cast to the correct type
+ * #683 Generation report reports a file as not generated if it is the output of an implementation filtered out of the generation by a condition
+ * #914 ConE way of creating temp files is racy and not good for server usage
+ * #919 Error: ConE container conditions do not work correctly with data comparison on different data types
+ * #932 Wildcards are working only in the beginning of filename in convertprojectml
+
+== Version Cone-1.2.2 ==
+Major features
+ * Bug fixes 1.2, to mainly fix bugs found in real build environments (parallel building, etc).
- * Bug fixes:
- - #657: Project.create_configuration takes forever with big configuration project
- - #659: Content plugins copy operation does not do anything if the file attribute in input has capital letter
- - #660: plugins get increased to an insane amount!
+== Stories ==
+ * #860 CI interface compare report
+
+== Bug fixes ==
+ * #917 Error: Cone generate fails when parameters to paths are given with \path syntax
+ * #878 Helium 6.0.x: ConE errors in image creation
+
+== Version Cone-1.2.1 ==
+Major features
+ * Bug fixes and small new features to ConE 1.2.1
+
+== Stories ==
+ * #830 NUAGE: As a customisation engineer I want to override property elements in a view so that the properties can be extended / overriden
+ * #846 As a variant engineer I want to easily merge a customer variant from a CPF back into the configuration project
+ * #743 EPIC: Automatic validation with ConE
+ * #851 Exporting CPFs to path creates that path
+ * #884 As a user I want to generate certain layers based on the layer naming so that variant creation manual layer is included automatically when needed
+ * #898 As a variant engineer I want to specifiy line change in templateml file for each template so that I can write either unix or windows files.
-== Version Cone-1.1.1 RC4 ==
- * Bugfixes:
- - cone.cmd fix
-
-== Version Cone-1.1.1 RC3 ==
- * Bugfixes:
- - GenConfML plugin to use LXML instead of 4Suite
- - Changed installation system to make the installation into a sub-directory depending on the current Python version (e.g. cone/2.5/lib/ instead of cone/lib/ etc.)
- - Changed cone.cmd so that it chooses the correct base directory based on the Python version
- - Added dep-eggs for Python 2.6
- - Updated setuptools to version 0.6c11 from 0.6c9
- - PYTHONCASEOK=1 added to cone.cmd
+Bug fixes
+ * #861 NUAGE: Template/sequence problem
+ * #864 NUAGE: File setting problem in template part
+ * #876 Configuration version does not get read/written to confml output
+ * #877 Empty attributes of elements are removed in read/write test
+ * #207 set_value(value) method for sequence features modifies its parameter
-== Version Cone-1.1.1 RC2 ==
- * Bugfixes:
- * #640: Tag definitions in TemplateML namespace do not work
- * #645: Report generation fails if the changed data contains references to non-existent settings
- * #648: TemplateML plug-in does not list output files correctly
- * #589: Change ImageML get_refs() to report references used in determining input
-== Version Cone-1.1.1 RC1 ==
+== Version Cone-1.2.0 ==
+* Features:
+ * #40: As a variant engineer/Sw integrator I want to check data compatibility of certain configuration so that I can be sure that my configuration is valid.
+ * #42: As a variant engineer I want to create operator cache using ConE so that content is visible already before image has been created
+ * #84: EPIC: Cenrep changes related cenrep version 2 and PREQ2112
+ * #96: As a variant engineer I need to enter variantID and variant version as a commandline parameter for the variant in case not included in the CPF
+ * #120: ConE view inclusion support
+ * #130: iMaker: Support baseporting team in iMaker - Cone HCR integration.
+ * #559: As a customization designer I want have only delta cenreps in ROFS3 so that re-creation of ROFS3 images in PR update is minimized.
+ * #584: As a variant engineer I want to be able to override implementation file in later layers so that public confml definition is easier.
+ * #636: Export action does not export ConfML files correctly
+ * #692: Value report generation fails if the view references non-existent settings
+ * #693: Value report generation fails if the specified view file does not directly contain the view
+ * #702: As a SW developer I want to validate my ConfML and Implml file schemas using ConE
+ * #705: Change rule plugin due to engine changes
+ * #74: 6NUAGE: As a cone developer I want to access view overridden and original attributes so that I can know which attributes are set in view level
+ * #747: As a user I want to see different schema validation as different error types so that I can filter them
+ * #792: Change ConE licenses from SFL to EPL
+ * #794: Preliminary model-level validation framework design
+ * #797: Productization and merging model level validation to ConE 1.2 release
+ * #826: ConE Linux delivery
+ * #858: Refs changed by rule execution should be visible to other implementations immediately
+ * #859: Common ImplML elements should be inherited correctly to sub-implementations
+ * #879: As a user I want to filter errors in the validation report so that I can find my errors easily
+* Bug fixes:
+ * #156: SchemaLocation attribute in Configuration element is invalid
+ * #791: Writing FeatureLink objects to confml file fails
+ * #799: As a customisation engineer I want to override option lists in a view so that the option list can be extended / overriden
+ * #829: ConE must not assume that the executive process will have write access to workdir: change the usage of os.rename to use shutil.move
+ * #831: Defining several mailbox feature elements under same group overrides the previously defined mailboxes in a view
+ * #832: ConE log file parameter causes error if filename contains \x
+ * #833: As a ConE API user I want to use all Confml feature xml schema facets consistently so that I can always trust that I get a certain type value
+ * #834: As a user I want read/write length attribute of a confml feature/setting
+ * #835: As a user I want to set desc and name attributes via constructor to a Confml sequence setting so that I can create it easily
+ * #836: NUAGE: As a ConE API user I want to read/write the id of any confml element so that the id can be accessed via the API
+ * #837: The ConfmlSequenceSetting template does not return ConfmlFile element data when it is fetched from confml
+ * #854: Filtering based on setting references does not work correctly with ImplContainers
+ * #855: ThemeML does not work in ImplML containers
+ * #857: Template plug-in does not do ref-based filtering correctly
+ * #866: Python version checking in cone.cmd might cause errors if multiple cone.cmd are executed at the same time.
+ * #587: Cone.cmd contains strange line
+
+== Version Cone-1.2.0DEV ==
* Features:
* Support for new webstorage (Carbon extapi)
* Export features and data. Supports exporting of features and data from carbon to Configuration project and confml files.
@@ -86,8 +197,30 @@
is not a valid confml ref. e.g. refs withs dots or any unicode characters.
* Selection type feature cannot be created with the Carbon extapi (Creation of groups fails).
* Directory separators '/' in configuration names will break the loading of configurations.
- * Carbon allows only references in lower case, which is contradicting current confml specification.
-== Version Cone-1.1.1 ==
+ * Carbon allows only references in lower case, which is contradicting current confml specification.
+ * Stories:
+ * #746 : As a cone developer I want to access view overridden and original attributes
+ so that I can know which attributes are set in view level
+
+== Version Cone-1.1.1 RC4 ==
+ * Bugfixes:
+ - cone.cmd fix
+== Version Cone-1.1.1 RC3 ==
+ * Bugfixes:
+ - GenConfML plugin to use LXML instead of 4Suite
+ - Changed installation system to make the installation into a sub-directory depending on the current Python version (e.g. cone/2.5/lib/ instead of cone/lib/ etc.)
+ - Changed cone.cmd so that it chooses the correct base directory based on the Python version
+ - Added dep-eggs for Python 2.6
+ - Updated setuptools to version 0.6c11 from 0.6c9
+ - PYTHONCASEOK=1 added to cone.cmd
+== Version Cone-1.1.1RC2 ==
+ * Bugfixes:
+ * #640: Tag definitions in TemplateML namespace do not work
+ * #645: Report generation fails if the changed data contains references to non-existent settings
+ * #648: TemplateML plug-in does not list output files correctly
+ * #589: Change ImageML get_refs() to report references used in determining input
+
+== Version Cone-1.1.0 ==
* New features
* Templateml plugin
* Command plugin
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/build-scripts/export_bat.py
--- a/configurationengine/build-scripts/export_bat.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/build-scripts/export_bat.py Tue Aug 10 14:29:28 2010 +0300
@@ -30,13 +30,12 @@
assert os.path.exists(PLUGIN_SOURCE_ROOT)
assert os.path.exists(TESTAUTOMATION_ROOT)
-sys.path.append(PLUGIN_SOURCE_ROOT)
-import plugin_utils
+
sys.path.append(TESTAUTOMATION_ROOT)
import testautomation
from testautomation.copy_dir import copy_dir
-
+from testautomation import plugin_utils
import utils
utils.setup_logging('export_bat.log')
@@ -124,7 +123,7 @@
# --------------------------------------
log.info("Exporting plug-in integration test files...")
- subpaths_by_package = plugin_utils.find_plugin_package_subpaths('integration-test', PLUGIN_PACKAGE)
+ subpaths_by_package = plugin_utils.find_plugin_package_subpaths(PLUGIN_SOURCE_ROOT, 'integration-test', PLUGIN_PACKAGE)
for package_name, tests_path in subpaths_by_package:
log.debug(" Package: %s" % package_name)
log.debug(" Path: %s" % tests_path)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/build-scripts/install_cone.py
--- a/configurationengine/build-scripts/install_cone.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/build-scripts/install_cone.py Tue Aug 10 14:29:28 2010 +0300
@@ -24,15 +24,30 @@
ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+# The sub-directory of the main install directory where all required libraries
+# etc. are installed
+INSTALL_SUBDIR = 'configurationengine'
+
+# The sub-directory for required libraries, platform-specific
+if sys.platform == "win32":
+ PLATFORM_SUBDIR = 'win'
+else:
+ PLATFORM_SUBDIR = 'linux'
+
+PYTHON_EXECUTABLE = 'python'
+
SOURCE_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '../source'))
assert os.path.isdir(SOURCE_ROOT)
SCRIPTS_SOURCE_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '../source/scripts'))
assert os.path.isdir(SCRIPTS_SOURCE_ROOT)
PLUGIN_SOURCE_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '../source/plugins'))
assert os.path.isdir(PLUGIN_SOURCE_ROOT)
+TESTAUTOMATION_ROOT = os.path.abspath(os.path.join(SOURCE_ROOT, 'testautomation'))
+assert os.path.isdir(TESTAUTOMATION_ROOT)
+sys.path.insert(0, TESTAUTOMATION_ROOT)
sys.path.append(PLUGIN_SOURCE_ROOT)
-import plugin_utils
+from testautomation import plugin_utils
# Temporary directory where ConE eggs are built into
TEMP_CONE_EGG_DIR = os.path.join(ROOT_PATH, 'install-temp/cone-eggs')
@@ -48,20 +63,20 @@
"""
paths = [SOURCE_ROOT,
SCRIPTS_SOURCE_ROOT]
- plugin_paths = plugin_utils.find_plugin_sources_by_package(plugin_package)
+ plugin_paths = plugin_utils.find_plugin_sources_by_package(PLUGIN_SOURCE_ROOT, plugin_package)
paths.extend(plugin_paths)
log.debug("ConE egg source paths:\n%s" % '\n'.join(paths))
return paths
-def build_cone_eggs(source_paths):
+def build_cone_eggs(source_paths, python_executable):
log.info("Cleaning temporary ConE egg dir...")
utils.recreate_dir(TEMP_CONE_EGG_DIR)
log.info("Building ConE eggs...")
for source_path in source_paths:
- ok = utils.build_egg(source_path, TEMP_CONE_EGG_DIR)
+ ok = utils.build_egg(source_path, TEMP_CONE_EGG_DIR, python_executable)
if not ok:
raise BuildFailedError()
@@ -74,18 +89,21 @@
log.debug("Copying eggs from '%s'..." % source_dir)
for name in os.listdir(source_dir):
if name.endswith('.egg'):
- utils.copy_file(
- source_path = os.path.join(source_dir, name),
- target_path = TEMP_LIB_EGG_DIR)
+ if PLATFORM_SUBDIR == 'linux' and name.startswith('setuptools-0.6c11'):
+ continue
+ else:
+ utils.copy_file(
+ source_path = os.path.join(source_dir, name),
+ target_path = TEMP_LIB_EGG_DIR)
dep_dirs_by_package = [(None, os.path.join(ROOT_PATH, '../dep-eggs'))]
- dep_dirs_by_package.extend(plugin_utils.find_plugin_package_subpaths('dep-eggs', plugin_package))
+ dep_dirs_by_package.extend(plugin_utils.find_plugin_package_subpaths(PLUGIN_SOURCE_ROOT, 'dep-eggs', plugin_package))
for package_name, dep_dir in dep_dirs_by_package:
copy_eggs(dep_dir)
def init_target_dir(target_dir, python_version):
- BASE_DIR = os.path.normpath(os.path.join(target_dir, 'cone', python_version))
+ BASE_DIR = os.path.normpath(os.path.join(target_dir, INSTALL_SUBDIR, PLATFORM_SUBDIR, python_version))
LIB_DIR = os.path.join(BASE_DIR, 'lib')
SCRIPT_DIR = os.path.join(BASE_DIR, 'scripts')
@@ -102,7 +120,8 @@
LIB_DIR, SCRIPT_DIR = init_target_dir(target_dir, python_version)
# Collect the eggs to install
- eggs = ['setuptools'] # Setuptools are needed also
+ eggs = ['setuptools'] # Setuptools are needed
+
for name in os.listdir(TEMP_CONE_EGG_DIR):
if name.endswith('.egg'):
eggs.append(TEMP_CONE_EGG_DIR + '/' + name)
@@ -111,18 +130,24 @@
for egg in eggs:
log.debug(egg)
- if sys.platform == "win32":
- platform_args = ["--always-copy"]
+ if PLATFORM_SUBDIR == 'win':
+ command = ['easy_install-%s' % python_version,
+ '--allow-hosts None',
+ '--find-links install-temp/dep-eggs',
+ '--install-dir "%s"' % LIB_DIR,
+ '--script-dir "%s"' % SCRIPT_DIR,
+ '--site-dirs "%s"' % LIB_DIR,
+ '--always-copy',
+ '--always-unzip']
else:
- platform_args = ["--no-deps"]
-
- command = ['easy_install',
- '--allow-hosts None',
- '--find-links install-temp/dep-eggs',
- '--install-dir "%s"' % LIB_DIR,
- '--script-dir "%s"' % SCRIPT_DIR,
- '--site-dirs "%s"' % LIB_DIR]
- command.extend(platform_args)
+ command = ['easy_install-%s' % python_version,
+ '--allow-hosts None',
+ '--find-links install-temp/dep-eggs',
+ '--install-dir "%s"' % LIB_DIR,
+ '--script-dir "%s"' % SCRIPT_DIR,
+ '--site-dirs "%s"' % LIB_DIR,
+ '--always-unzip']
+
command.append('"' + egg + '"')
command = ' '.join(command)
@@ -131,7 +156,7 @@
if not ok:
raise BuildFailedError()
-def develop_install_cone_sources(source_paths, target_dir, python_version):
+def develop_install_cone_sources(source_paths, target_dir, python_version, python_executable):
log.info("Installing ConE sources in develop mode...")
LIB_DIR, SCRIPT_DIR = init_target_dir(target_dir, python_version)
@@ -139,7 +164,7 @@
try:
for source_path in source_paths:
os.chdir(source_path)
- command = ['python setup.py develop',
+ command = ['%s setup.py develop' % python_executable,
'--allow-hosts None',
'--find-links "%s"' % os.path.normpath(os.path.join(ROOT_PATH, 'install-temp/dep-eggs')),
'--install-dir "%s"' % LIB_DIR,
@@ -154,10 +179,11 @@
finally:
os.chdir(orig_workdir)
-def perform_build(target_dir, plugin_package, install_type, python_version):
- log.info("Target directory: %s" % target_dir)
- log.info("Plug-in package: %r" % plugin_package)
- log.info("Python version: %s" % python_version)
+def perform_build(target_dir, plugin_package, install_type, python_version, python_executable):
+ log.info("Target directory: %s" % target_dir)
+ log.info("Plug-in package: %r" % plugin_package)
+ log.info("Python version: %s" % python_version)
+ log.info("Python executable: %s" % python_executable)
# Retrieve dependencies to the correct location
retrieve_dep_eggs(plugin_package)
@@ -169,26 +195,29 @@
if not os.path.exists(target_dir):
os.makedirs(target_dir)
+ if install_type == 'build':
+ build_cone_eggs(source_paths, python_executable)
if install_type == 'install':
- build_cone_eggs(source_paths)
+ build_cone_eggs(source_paths, python_executable)
install_cone_eggs(target_dir, python_version)
else:
- develop_install_cone_sources(source_paths, target_dir, python_version)
+ develop_install_cone_sources(source_paths, target_dir, python_version, python_executable)
# Copy RELEASE.txt
utils.copy_file(
source_path = os.path.join(SOURCE_ROOT, '..', 'RELEASE.TXT'),
- target_path = os.path.join(target_dir, 'cone', 'RELEASE.TXT'))
+ target_path = os.path.join(target_dir, INSTALL_SUBDIR, 'RELEASE.TXT'))
# Copy cone.cmd or cone.sh, depending on the platform
if sys.platform == "win32":
- filename = "cone.cmd"
+ sourcefile = targetfile = "cone.cmd"
else:
- filename = "cone.sh"
- log.info("Copying %s" % filename)
+ sourcefile = "cone.sh"
+ targetfile = "cone"
+ log.info("Copying %s" % sourcefile)
utils.copy_file(
- source_path = os.path.join(SOURCE_ROOT, filename),
- target_path = target_dir)
+ source_path = os.path.join(SOURCE_ROOT, sourcefile),
+ target_path = os.path.join(target_dir, targetfile))
def main():
parser = optparse.OptionParser()
@@ -200,26 +229,33 @@
parser.add_option("-i", "--install-type",\
help="The installation type, can be 'install' (the default) or 'develop'.",\
default='install')
+ parser.add_option("--python-executable",\
+ help="The Python executable to run type, defaults to 'python'.",\
+ default='python')
(options, args) = parser.parse_args()
if options.target_dir is None:
parser.error("Target directory must be given")
- if options.install_type not in ('install', 'develop'):
+ if options.install_type not in ('install', 'build', 'develop'):
parser.error("Invalid install type ('%s')" % options.install_type)
-
- if not utils.run_command("python --help"):
- log.critical("Could not run 'python'. Please make sure that you "\
- "have Python installed and in your path.")
+
+ if not utils.run_command("%s --help" % options.python_executable):
+ log.critical("Could not run '%s'. Please make sure that you "\
+ "have Python installed and in your path." % options.python_executable)
return 1
- if not utils.run_command("easy_install --help"):
- log.critical("Could not run 'easy_install'. Please make sure that you "\
- "have setuptools installed and the Python scripts directory in your path.")
+ python_version = utils.get_python_version(options.python_executable)
+
+ easy_install_cmd = "easy_install-%s" % python_version
+ if not utils.run_command("%s --help" % easy_install_cmd):
+ log.critical("Could not run '%s'. Please make sure that you "\
+ "have setuptools installed and the Python scripts directory in your path."\
+ % easy_install_cmd)
return 1
- python_version = utils.get_python_version()
+
try:
- perform_build(options.target_dir, options.plugin_package, options.install_type, python_version)
+ perform_build(options.target_dir, options.plugin_package, options.install_type, python_version, options.python_executable)
except BuildFailedError:
return 1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/build-scripts/utils.py
--- a/configurationengine/build-scripts/utils.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/build-scripts/utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -43,7 +43,7 @@
else:
os.makedirs(path)
-def build_egg(source_dir, target_dir):
+def build_egg(source_dir, target_dir, python_executable='python'):
"""
Build an egg file from the given source directory (must contain a setup.py)
into the given target directory.
@@ -53,7 +53,7 @@
orig_workdir = os.getcwd()
os.chdir(source_dir)
try:
- cmd = 'python setup.py bdist_egg --dist-dir "%s"' % target_dir
+ cmd = '%s setup.py bdist_egg --dist-dir "%s"' % (python_executable, target_dir)
return run_command(cmd)
finally:
os.chdir(orig_workdir)
@@ -65,12 +65,13 @@
os.makedirs(target_dir)
shutil.copy2(source_path, target_path)
-def get_python_version():
+def get_python_version(executable='python'):
"""
- Return the version of the Python that is run when the command 'python'
- is run (not the Python where this script is executing).
+ Return the version of the Python that is run when the given Python
+ executable is run (not the Python where this script is executing).
+ @param executable: The Python executable to run, defaults to 'python'.
"""
- p = subprocess.Popen('python -c "import sys; print sys.version[:3]"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
+ p = subprocess.Popen('%s -c "import sys; print sys.version[:3]"' % executable, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
out, err = p.communicate()
if p.returncode != 0:
log.critical("Failed to get python version")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/build.xml
--- a/configurationengine/build.xml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/build.xml Tue Aug 10 14:29:28 2010 +0300
@@ -2,269 +2,401 @@
* Configuration Engine (ConE) main build file
* This ant build.xml will build, install and test ConE and its plugins
****************************************************************************-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Revert SVN revision in source/cone/__init__.py
-
-
-
-
- Determine current working copy revision
-
-
-
- SVN revision: ${svn.version}
-
-
- Update SVN revision in __init__.py
-
-
-
-
-
-
-
-
-
-
-
-
-
- Revert SVN revision in source/cone/__init__.py
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Revert SVN revision in source/cone/__init__.py
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Revert SVN revision in source/cone/__init__.py
+
+
+
+
+
+
+
+
-
-
- Installing with first Python version (PATH=${build.dualversioninstall.path1})
-
-
-
-
-
- Installing with second Python version (PATH=${build.dualversioninstall.path2})
-
-
-
-
-
- Revert SVN revision in source/cone/__init__.py
-
-
-
-
-
-
-
-
-
-
-
-
+ Installing with first Python version (PATH=${build.dualversioninstall.path1})
+
+
+
+
+
+
+ Installing with second Python version (PATH=${build.dualversioninstall.path2})
+
+
+
+
+
+
+ Revert SVN revision in source/cone/__init__.py
+
+
+
+
+
+
+
+
+ Installing with first Python version (executable=${build.dualversioninstall.executable1})
+
+
+
+
+ Installing with second Python version (executable=${build.dualversioninstall.executable2})
+
+
+
+
+
+ Revert SVN revision in source/cone/__init__.py
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/common.properties
--- a/configurationengine/common.properties Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/common.properties Tue Aug 10 14:29:28 2010 +0300
@@ -4,8 +4,10 @@
****************************************************************************-->
# ConE version that is added to the produced ZIP file
-common.version = 1.1
+common.version = 1.2.11
common.build_scripts_dir = build-scripts
document.output =docbuild
+build.plugin_package = symbian
+cone_python_path = ./source;./source/testautomation;./source/plugins/common/ConeCommandPlugin;./source/plugins/common/ConeLegacyRulePlugin;./source/plugins/common/ConeRulePlugin;./source/plugins/common/ConeTemplatePlugin;./source/plugins/symbian/ConeCRMLPlugin;./source/plugins/common/ConeContentPlugin;./source/plugins/example/ConeExamplePlugin;./source/plugins/symbian/ConeGenconfmlPlugin;./source/plugins/symbian/ConeHCRPlugin;./source/plugins/symbian/ConeProjectConverterPlugin;./source/plugins/symbian/ConeThemePlugin;./source/plugins/symbian/ConeImagePlugin;
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/debian/control
--- a/configurationengine/debian/control Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/debian/control Tue Aug 10 14:29:28 2010 +0300
@@ -5,7 +5,7 @@
Build-Depends: debhelper (>= 5), python (>=2.4), python-central, python-setuptools
Standards-Version: 3.7.2
XS-Python-Version: >= 2.4
-Homepage: http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware
+Homepage: http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware/ConE
Package: python-cone
Architecture: all
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/debian/copyright
--- a/configurationengine/debian/copyright Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/debian/copyright Tue Aug 10 14:29:28 2010 +0300
@@ -1,7 +1,7 @@
This package was debianized by Zoltan Andrasi on
Thu, 11 Dec 2008 11:57:50 +0200.
-It was downloaded from http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware
+It was downloaded from http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware/ConE
Upstream Author(s):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/dep-eggs/Jinja2-2.1.1-py2.5-win32.egg
Binary file configurationengine/dep-eggs/Jinja2-2.1.1-py2.5-win32.egg has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/dep-eggs/Jinja2-2.1.1-py2.6-win32.egg
Binary file configurationengine/dep-eggs/Jinja2-2.1.1-py2.6-win32.egg has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/api/api.rst
--- a/configurationengine/doc/api/api.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/api/api.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,5 +1,8 @@
-Cone API
+
+.. _cone-api:
+ConE API
========
+
The Cone API consists of submodules that contain the actual api implementations. The modules are splitted according to the purpose of use.
* public api is the main public interface that Cone offers.
* plugin api is the interface which defines all plugin extension base classes and a general plugin framework.
@@ -7,7 +10,7 @@
modules:
.. toctree::
-
+ :maxdepth: 3
+
public
plugin
- howto
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/api/howto.rst
--- a/configurationengine/doc/api/howto.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/api/howto.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,15 +1,22 @@
+.. _cone-api-howto:
+
How to use cone APIs
====================
The ConE public usage is described here with few common use cases as HowTo guides.
+* See `Cone API epydoc <../epydoc/index.html>`_ for reference guide of api functions.
+
How to open a Configuration project
-----------------------------------
+* See reference of `Project class <../epydoc/cone.public.api.Project-class.html>`_
+
To open a project with ConE the api offers a Storage and Project classes. The Storage is the storage
agostic implemenetation for cpf/zip, filestorage and soon also a webstorage. To access anything in ConE
you must a project open.
+
.. code-block:: python
from cone.public import api,exceptions
@@ -33,6 +40,8 @@
How to access and manipulate Configurations
-------------------------------------------
+* See reference of `Configuration class <../epydoc/cone.public.api.Configuration-class.html>`_
+
A Configuration normally is presented inside the Configuration project as a .confml file. So when you
are accessing configurations your are actually accessing confml files. The project offers funtionality to
get,add, remove configurations, which acts on root configurations inside the given project.
@@ -92,8 +101,51 @@
myconfig = prj.get_configuration('myconfig.confml')
myconfig.include_configuration('../data.confml')
+
+How to set / write metadata to a Configuration root file
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The metadata element is currently confml model specific, so you need to import the confml.model to enable metadata writing.
+The ConfmlMeta element is desinged so that it can contain several ConfmlMetaProperty elements, each of which can be in
+different xml namespaces.
+
+.. code-block:: python
+
+ from cone.public import api
+ from cone.confml import model
+
+ store = api.Storage.open(".","w")
+ prj = api.Project(store)
+ config = prj.create_configuration("test_meta.confml")
+
+ prop1 = model.ConfmlMetaProperty("test", 'testing string')
+ prop2 = model.ConfmlMetaProperty("testName", 'testing string2', \
+ "http://www.nokia.com/xml/cpf-id/1", \
+ attrs={"name":"name1", "value": "value1"})
+ prop3 = model.ConfmlMetaProperty("configuration-property", None, \
+ "http://www.nokia.com/xml/cpf-id/1", \
+ attrs={"name":"sw_version", "value": "1.0.0"})
+ metaelem = model.ConfmlMeta([prop1, prop2, prop3])
+
+ config.meta = metaelem
+ config.save()
+ prj.close()
+
+The output file *test_meta.confml* should look like this..
+
+.. code-block:: xml
+
+
+
+ testing string
+ testing string2
+
+
+
+
Feature Access and manipulation
-------------------------------
+* See reference of `Feature class <../epydoc/cone.public.api.Feature-class.html>`_
How to add a Feature to Configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,6 +183,12 @@
prj.close()
+Feature acces via Views
+-----------------------
+* See reference of `View class <../epydoc/cone.public.api.View-class.html>`_
+* See reference of `Group class <../epydoc/cone.public.api.Group-class.html>`_
+* See reference of `FeatureLink class <../epydoc/cone.public.api.FeatureLink-class.html>`_
+
How to get a Feature from Configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -269,6 +327,61 @@
prj.save()
prj.close()
+
+How to Create a View
+^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ from cone.public import api
+ from cone.confml import model
+
+ store = api.Storage.open(".","w")
+ prj = api.Project(store)
+ """ First create the configuration with two features """
+ if prj.is_configuration("test_override.confml"):
+ config = prj.get_configuration("test_override.confml")
+ else:
+ config = prj.create_configuration("test_override.confml")
+ fea1 = config.create_feature("foo", name="foo name")
+ fea2 = fea1.create_feature("bar", name="bar name")
+
+ """ Create the view and group to it """
+ view = config.create_view('testview')
+ group = view.create_group('group1')
+
+ """
+ Create a featurelink.
+ Note! the featurelink now overrides the name attribute of the original feature.
+ """
+ link = group.create_featurelink('foo', name="foo name overridden")
+ """ override the description attribute of the view link """
+ link.desc = "override desc"
+ config.save()
+
+How to Get a view and test attribute overrides
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In this example we assume that the previous example was stored to a file *test_override.confml*.
+
+.. code-block:: python
+
+ from cone.public import api
+ from cone.confml import model
+
+ store = api.Storage.open(".","w")
+ prj = api.Project(store)
+ config = prj.get_configuration("test_override.confml")
+ """ get the view and a feature from it """
+ view = config.get_view('testview')
+ fea = view.get_feature('group1.foo')
+ """ assert that the feature attributes have been overridden in the view """
+ assert(fea.has_attribute('name'))
+ assert(fea.has_attribute('desc'))
+ assert(fea.has_attribute('minLength') == False)
+ assert(fea._obj.name == 'foo name')
+ prj.close()
+
+
Data access and manipulation
----------------------------
The data access inside a configuration is possible, but basically this can be avoided by manipulating the values
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/api/plugin.rst
--- a/configurationengine/doc/api/plugin.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/api/plugin.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,91 +1,24 @@
-Plugin API
-===============
-
-.. module:: cone.public.plugin
- :platform: Unix, Windows
- :synopsis: Configuration interface.
-.. moduleauthor:: Teemu Rytkonen
+.. _plugin-api:
-The Plugin api is intended for extending the ConE functionality with plugins that can be for example
-implementation or relation plugins. See :ref:`plugin-howto`
-
-.. image:: cone_plugin_api.png
-
-Classes
--------
-
-.. class:: ImplBase(ref, configuration)
-
-The ImplBase class is intended for deriving any implementation plugin in ConE. A single ImplBase
-instance is created by ConE for each implml file inside a given Configuration.
+Extending ConE with plugin API
+==============================
-See :ref:`plugin-howto`
-
- .. method:: list_output_files()
-
- The list_output_files should return a list of output files with path, with the current configuration.
- This mechanism should enable listing of all output files before without actually generating them.
-
- .. method:: generate()
-
- The plugin instance is supposed to generate its output with the call of generate().
+The Plugin api is intended for extending the ConE functionality with plugins.
+Currently there are two ways to extend the functionality:
- .. method:: has_ref(refs)
-
- This method receives a list as an attribute and is supposed to return True|False. True if this
- particular plugin instance has a reference to a Feature inside the given refs list. Otherwise False.
-
-.. class:: ImplSet
-
-The ImplSet is a sets.Set object for a set of ImplBase instances. The main purpose of ImplSet
-is to allow operations to a set of ImplBase instances, such as generate, filter, etc.
-
-.. class:: ImplFactory
-
-ImplFactory is a constructor class for the plugin instances.
+1. Adding support for new implementation languages
+2. Extending ConfML or ImplML validation
- .. method:: get_impl_by_ext(cls, ext)
-
- Get the class name by file extension.
-
-
- .. method:: get_impl_by_filename(cls, ref, configuration)
+Usually a plug-in that provides a new implementation language also provides
+validation for it.
- Get the class name by filename.
-
-.. class:: Relation(left, right)
-
- .. method:: execute()
-
- Executes the rule initiated for this Relation.
-
+Developing a ConE plugin
+------------------------
+* See `Cone API epydoc <../epydoc/index.html>`_ for reference guide.
- Relation is a base class for all Relation implementations. The purpose of a Relation instance is to offer a verb or an
- action that can be used in a rule. A rule in this context means a textual relation between two or more :class:`Feature`'s.
- For example a Depends class could be used to define dependencies between two :class:`Feature`
-
- ::
-
- example rule
- A depends B
-
- Where A and B are :class:`Feature` references.
+.. toctree::
+ :maxdepth: 3
-.. class:: RelationContainer
-
- RelationContainer is a container object that derives Relation interface, but is meant for storing a set of :class:`Relation`
- objects. It can be used to execute a set of rules read to the container.
-
-.. class:: RelationFactory
-
- .. method:: get_by_name(name)
-
- returns a :class:`Relation` if the class that matches the name is found.
-
- The RelationFactory is intended to be used when the rules are read from some persistent storage. When a rule is found from
- :class:`Configuration` ConE will try to create a :class:`Relation` instance of the rule, by trying to get class
- by :meth:`RelationFactory.get_by_name` and create an instance of that class.
-
-
-
-
+ ../plugins/dev-plugin/plugin-interface
+ ../plugins/dev-plugin/index
+ ../plugins/dev-plugin/validation-plugin-index
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/api/public.rst
--- a/configurationengine/doc/api/public.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/api/public.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,147 +1,21 @@
-Public API
-**********
-Cone public API is the main interface of Cone.
-
-.. image:: cone_public_api.png
+.. _cone-public-api:
-
-.. module:: cone.public.api
- :platform: Unix, Windows
- :synopsis: Configuration interface.
-.. moduleauthor:: Teemu Rytkonen
+Using ConE public API
+=====================
-Classes
--------
-.. class:: ObjectContainer
+Cone public API is the main interface of Cone.
- ObjectContainer is a base class for all Configuration related elements. It is container class for a tree structure,
- where it can contain other ObjectContainer objects. So basically you can create B-tree type of hiararchy with it.
-
- The main functionality of ObjectContainer is that **all children of an object container are accessible as members**
- of the container.
-
- .. _example_member_access:
-
- Example of ObjectContainer member access:
-
- ``objcontainer.configuration.get_name()``
-
+Developing with ConE API
+------------------------
+The ConE public API is described most accurately in the generated api documentation, which can be used as a reference guide.
- .. method:: _add(child)
-
- Add a ObjectContainer instance to this object. Checks with internal function :meth:`__supported_type__` if the given
- child is a supported class for this object.
-
- .. method:: _add_to_path(path,child)
-
- Add a ObjectContainer instance to a specific node under this object. It creates any missing nodes between this object
- and the path. For example __add_to_path__("foo.fii", obj), would create two nodes (foo and under it fii) if they are
- missing (Uses internal :meth:`__default_class__` to retrieve the class which is created in this case).
-
- .. method:: _remove(path)
-
- Remove a child from given path.
-
- .. method:: _get(path)
-
- get a child from given path.
-
- .. method:: _list()
-
- Get a list of names of immediate children of this ObjectContainer instance.
-
- .. method:: _objects()
-
- Get a list of immediate children objects of this ObjectContainer instance.
-
- .. method:: _traverse(filters)
-
- Get a list of children objects of this ObjectContainer instance, by filtering them with filters. This will cause a
- recursive _traverse method call to all children of the ObjectContainer.
-
- .. method:: _path(toparent=None)
-
- Return the path to this object up to the toparent object. When toparent=None this will
- return a full path to the object in the ObjectContainer hierarhcy.
-
- .. method:: _supported_type(obj)
-
- A method that is supposed to be overridden by the deriving classed if they need to change, which classes can be added
- under each class.
- Return True if the type of the obj is supported.
-
- .. method:: _default_class(obj)
-
- A method that is supposed to be overridden by the deriving classed if they need to change, what class is
- the default class that is created with __add_to_path__ when objects are missing.
- Return a class.
-
-
-.. class:: Base
+* See `Cone API epydoc <../epydoc/index.html>`_ reference guide.
- Base class for all :class:`~cone.public.api.Configuration` and its child objects.
-
- .. method:: get_ref()
-
- return the ref of this object.
-
- .. method:: get_namepace()
-
- return the namespace of this object.
-
-.. class:: Project
-
- Project is a container for Configuration's.
+Example usage of ConE public API
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The below section is a example orientated desciption of ConE public api usage.
-.. class:: Configuration
-
- ConE Configuration is the main interface for all configuration related activities. It is the main interface of ConE
- itself as ConE is eventually a python interface to a configuration project.
-
-Configuration as a Container
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- The Configuration instance itself in ConE is actually just a container for a bunch of different elements. These elements can practically be any elements that exist in a
- Configuration Project.
-
- * :class:`~cone.public.api.Configuration`
- * :class:`~cone.public.api.View`
- * :class:`~cone.public.api.Feature`
- * :class:`~cone.public.api.Resource`
- * :class:`~cone.public.plugin.Relation`
- * :class:`~cone.public.api.Data`
-
-.. class:: Feature
-
- Feature element is the base class for any Configurable item in a Configuration Project.
-
-.. class:: View
+.. toctree::
- A :class:`~cone.public.api.Configuration` can contain one or more View elements, which basically can define different type of tree structure of Feature elements that exist in the Configuration.
- A View element can contain :class:`~cone.public.api.Group` and :class:`FeaturePoxy` elements.
-
-.. class:: Group
-
- Group element can be child element of a :class:`~View`. It can include other Groups and :class:`~FeaturePoxy` elements to define a View hierarhcy.
-
-.. class:: FeatureProxy
-
- FeatureProxy element is a linking object inside View that has its own ref, name, etc but it basically just
- points to an actual :class:`Feature` instance.
-
-.. class:: Data
+ howto
- Data element defines a data value for a :class:`Feature` element. The Data elements can be defined in a
- :class:`Configuration` and single configurable :class:`Feature` can have multiple data definitions, in different
- configurations. The new definition always overrides the previous one. However the entire data definition hierarchy
- is stored and is available from the Cone API.
-
-.. class:: Storage
-
- Storage offers platform and persistence independent interface to store :class:`Resource` elements (data files,
- configuration files, etc).
-
-.. class:: Resource
-
- Resource is an instance of single storable element. Basically on normal filesystem this would be same as one file.
-
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/common.rst
--- a/configurationengine/doc/cli/common.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/cli/common.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,3 +1,5 @@
+.. _cone-cli:
+
Cone command line interface
===========================
@@ -19,45 +21,48 @@
cone --help
And you will get something like this as output::
-
- Usage: cone_tool.py [action] [options].
+
+ Usage: ConE [action] [options].
+
+
+ Use ConE [action] -h to get action specific help.
Available actions
- info
- compare
- merge
- export
- generate
- update
+ Main actions for one or more configurations.
+ compare : Compare two configurations
+ fix : Run automatic fixes for configurations.
+ generate : Generate a configuration.
+ report : Create report of existing report data.
+ update : Update/set values to features in configuration(s).
+ validate : Validate a configuration, or individual confml/imp
- Use cone_tool.py [action] -h to get action specific help.
- Options:
- --version show program's version number and exit
- -h, --help show this help message and exit
- -c CONFIG, --configuration=CONFIG Define the name of the configuration for the action
- -v LEVEL, --verbose=LEVEL Print error, warning and information on system out.
- Possible choices:
- NONE 0
- CRITICAL 1
- ERROR 2
- WARNING 3
- INFO 4
- DEBUG 5
- Default is 3.
- -p STORAGE, --project=STORAGE Defines the location of current project. Default is the current working directory.
+ Actions related to the configuration project maintenance.
+ export : Export configurations.
+ info : Get information about project / configurations.
+ merge : Merge a configuration/layer to the project.
+
+
+ extensions:
+ initvariant : Initialize a variant from a cpf.
+ packvariant : Pack (zip) the variant layers of a configuration.
+ rootflatten : Configuration root flattener.
ConE actions
------------
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
- info
+ generate
+ fix
compare
+ report
+ update
+ validate
+ export
merge
- export
- generate
- update
- report
+ info
+ initvariant
+ rootflatten
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/compare.rst
--- a/configurationengine/doc/cli/compare.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/cli/compare.rst Tue Aug 10 14:29:28 2010 +0300
@@ -13,9 +13,12 @@
>cd configproject_root
>cone compare -s configuration_root1.confml -t configuration_root2.confml
-By default the output is generated under current folder to compare.html (use switch --report=FILENAME
+The output is generated under current folder.
+By default the compare type is data comparison to data_comparison.html (use switch --report=FILENAME
to change the output file).
+* Example output `Data comparison report <../_static/data_comparison.html>`_
+
**Compare configurations between the current storage and some remote storage**:
The target configuration can also include remote storage path, which must be separated from the
@@ -31,6 +34,23 @@
>cd configproject_root
>cone compare -s configuration_root1.confml -t \config_project2;configuration_root2.confml --report-type api
+* Example output `API comparison report <../_static/api_comparison.html>`_
+
+**Compare Customisation interface to a product configuration interface**
+
+The **ci** comparison is created for specific comparison of Customisation interface to a product configuration interface. Its purpose is to find out differences between the CI and actual developer confmls (for example in assets/s60 layer). It compares the source configuration to target and reports differences and source features that are missing from target configuration.
+
+Use the --report-type switch make an ci (CustomisationInterface) comparison.::
+
+ >cd configproject_root
+ >cone compare -s customisation\CustomisationInterface\ci_root.confml -t vasco_langpack_01_root.confml --report-type=ci
+ Writing report to ci_comparison.html
+ Generated report to 'ci_comparison.html'
+ Done.
+
+* Example output `CI comparison report <../_static/ci_comparison.html>`_
+
+
**Compare configurations using a custom template**
Use the --template switch to specify a custom template file.::
@@ -87,9 +107,12 @@
--report-type=TYPE The type of the report to generate. This is a
convenience switch for setting the used template.
Possible values:
- api - Report changes in feature definitions
+ api - Report changes in feature definitions
+ ci - Report changes in CustomisationInterface definitions
+ crml_dc - Report CRML data compatibility issues
+ crml_dc_csv - Report CRML data compatibility issues
+ (CSV format)
data - Report changes in data values
- crml_dc - Report CRML data compatibility issues
--impl-filter=PATTERN
The pattern used for filtering implementations for the
comparison. See the switch --impl in action generate
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/export.rst
--- a/configurationengine/doc/cli/export.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/cli/export.rst Tue Aug 10 14:29:28 2010 +0300
@@ -3,12 +3,12 @@
Running action export
Usage: cone export [options]
-The export functionality exports configurations from the current project to a remote project. Default value for the current project is the currently working directory. A project can be either a folder or a CPF/ZIP file.
+The export functionality exports configurations from the current project to a remote project. Default value for the current project is the currently working directory. A project can be either a folder or a CPF/ZIP file or even a Carbon webstorage (via ExtAPI).
Examples
--------
-**Export a configuration from folder to a zip file**::
+**Export a configuration from configuration project folder to a zip file**::
>cd configproject_root
>cone export -c configuration_root.confml --remote=exported.zip
@@ -39,17 +39,24 @@
>cd configproject_root
>cone export --remote http://carbonqa.nokia.com/extapi -c configuration_root.confml
+**Export a configuration and run a action during the export**::
+ConE can also run separate actions during the exporting for example to fix model level errors if possible. To run for example the fix step during export you can use --run-action=fix attribute.
+
+ >cd configproject_root
+ >cone export -c configuration_root.confml --remote=../export_folder --run-action=fix
Options list
------------
+Options:
--version show program's version number and exit
-h, --help show this help message and exit
--print-settings Print all the default settings from the current
setting container.
--print-supported-impls
Print all supported ImplML XML namespaces and file
- extension.
+ extensions.
+ --print-runtime-info Print runtime information about ConE.
-v LEVEL, --verbose=LEVEL
Print error, warning and information on system out.
Possible choices: Default is 3.
@@ -60,24 +67,66 @@
INFO 4
DEBUG 5
--log-file=FILE Location of the used log file. Default is 'cone.log'
+ --log-config=FILE Location of the used logging configuration file.
+ Default is 'logging.ini'
+ --username=USERNAME Username for webstorage operations. Not needed for
+ filestorage or cpf storage. If the username
+ is not given, the tool will use the logged in
+ username. Example: cone export -p webstorage_url -r .
+ -c sample.confml --username=admin --password=abc123.
+ --password=PASSWORD Password for webstorage operations. Not needed for
+ filestorage or cpf storage. If the password
+ is not given, the tool will prompt for password if
+ needed.
-c CONFIG, --configuration=CONFIG
- defines the name of the configuration for the action
+ Defines the name of the configuration for the action,
+ can be specified multiple times to include multiple
+ configurations.
+ --config-wildcard=WILDCARD
+ Wildcard pattern for including configurations, e.g.
+ product_langpack_*_root.confml
+ --config-regex=REGEX Regular expression for including configurations, e.g.
+ product_langpack_\d{2}_root.confml
-p STORAGE, --project=STORAGE
defines the location of current project. Default is
the current working directory.
Export options:
- The export functionality is meant to export configurations between
- current project (defined with -p) to an remote project (defined with
- -r). Default value for the current project is the currently working
- directory. A project can be either a folder or a cpf/zip file.
+ The export action is intended for exporting configurations from one
+ project (storage) to another. A project can be a folder, a CPF or ZIP
+ file, or a Carbon web storage URL.
+ Two different ways of exporting are supported:
+ 1. Exporting multiple configurations into one new project using
+ --remote
+ 2. Exporting configurations into a number of new projects using
+ --export-dir
-r STORAGE, --remote=STORAGE
- defines the location of remote storage. Default name
- for remote storage is the source configuration name
- -a SET, --add=SET Add a configuration layer to the given configuration
- as last element.The add operation can be used several
+ Defines the location of remote storage. All
+ configurations included using --configuration,
+ --config-wildcard and --config-regex are exported into
+ the storage. If the remote storage location is not
+ given, the default location is determined based on the
+ first included source configuration name. E.g.
+ 'example.confml' would be exported into 'example.cpf'
+ --export-dir=EXPORT_DIR
+ Defines the directory where each included
+ configuration is exported as a new project.
+ --export-format=EXPORT_FORMAT
+ Defines the format into which projects are exported
+ when using --export-dir. Possible values are 'cpf'
+ (the default) and 'dir'.
+ -a CONFIG, --add=CONFIG
+ Adds a configuration layer to the given configuration
+ as last element. The add operation can be used several
times in a single command and it can create even an
- empty layer.Example --add foo/root.confml --add bar
+ empty layer. Example --add foo/root.confml --add bar
/root-confml.
- --exclude-folders Excludes empty folders from .cpf export
+ --run-action=PLUGIN
+ Adds a execution of extra step that can manipulate the
+ configuration before it is exported to external
+ storage. The --run-action operation can be used
+ several times in a single command and it will execute
+ the actions in given order.Example --run-action=fix,
+ which would execute fix action during export.
+ --exclude-folders Excludes empty folders from export
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/fix.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/doc/cli/fix.rst Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,81 @@
+ConE fix action
+================
+Running action fix
+Usage: cone fix [options]
+
+The fix functionality is meant for running possible automatic fixes to problems which validation reports.
+
+Examples
+--------
+
+**Fix a configuration**::
+
+ >cd configproject_root
+ >cone fix -c configuration_root.confml
+
+or use the option -p|--project to point to the configuration project root::
+
+ >cone fix --project=configproject_root -c configuration_root.confml
+
+**Print a list of available fix classes**::
+
+ >cone fix --print-available-fixes
+
+ Running action fix
+ Available fixers:
+ :
+ A Fix class for duplicate features that merges all setting under a duplicate feature
+ to the first instance of the feature and removes the duplicates.
+
+Options list
+------------
+ --version show program's version number and exit
+ -h, --help show this help message and exit
+ --print-settings Print all the default settings from the current
+ setting container.
+ --print-supported-impls
+ Print all supported ImplML XML namespaces and file
+ extensions.
+ --print-runtime-info Print runtime information about ConE.
+ -v LEVEL, --verbose=LEVEL
+ Print error, warning and information on system out.
+ Possible choices: Default is 3.
+ NONE (all) 0
+ CRITICAL 1
+ ERROR 2
+ WARNING 3
+ INFO 4
+ DEBUG 5
+ --log-file=FILE Location of the used log file. Default is 'cone.log'
+ --log-config=FILE Location of the used logging configuration file.
+ Default is 'logging.ini'
+ --username=USERNAME Username for webstorage operations. Not needed for
+ filestorage or cpf storage. If the username
+ is not given, the tool will use the logged in
+ username. Example: cone export -p webstorage_url -r .
+ -c sample.confml --username=admin --password=abc123.
+ --password=PASSWORD Password for webstorage operations. Not needed for
+ filestorage or cpf storage. If the password
+ is not given, the tool will prompt for password if
+ needed.
+ -c CONFIG, --configuration=CONFIG
+ Defines the name of the configuration for the action
+ -p STORAGE, --project=STORAGE
+ defines the location of current project. Default is
+ the current working directory.
+
+ Fix options:
+ The fix action is intended for performing fixes on a
+ configuration.
+
+ --print-available-fixes
+ Print all configuration fixer objects available.
+ --exclude-filter=EXCLUDE_FILTER
+ Exclude problems by given filter. Examples: --exclude-
+ filter=schema, --exclude-filter=schema.implml,
+ --exclude-filter=schema.confml, --exclude-
+ filter=schema.implml.ruleml
+ --include-filter=INCLUDE_FILTER
+ Include problems by given filter.Examples: --include-
+ filter=schema.implml, --include-
+ filter=schema.implml.ruleml
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/initvariant.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/doc/cli/initvariant.rst Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,98 @@
+ConE initvariant action
+=======================
+
+The *initvariant* action is intended for merging a variant CPF back into the
+configuration project. It is basically a special-purpose merge action that
+merges all customer variant layers (layers with ``custvariant*`` in their path
+name) and renames them based on the given variant ID and variant name
+(``custvariant__``).
+
+Examples
+--------
+
+**Merging a variant CPF using variant ID and name**::
+
+ > cd configproject_root
+ > cone initvariant -r variant.cpf --variant-id 123 --variant-name foobar
+
+This will merge customer variant layers into the project. The configuration
+root into which they are merged is also determined automatically based on the
+supplied information. The automatically determined root file is named
+``_custvariant___root.confml``,
+and the merged layers will have ``custvariant__``
+as part of their layer path.
+E.g. the layer ``familyx/productx/customer/custvariant/configurator/root.confml``
+is merged as ``familyx/productx/customer/custvariant_123_foobar/configurator/root.confml``
+and the configuration root would be ``productx_custvariant_123_foobar_root.confml``.
+
+**Merging a variant CPF into a specific root file**::
+
+ > cd configproject_root
+ > cone initvariant -r variant.cpf --variant-id 123 -c foovariant.confml
+
+This does basically the same thing as the previous command, except that the
+configuration root into which the merge is done is explicitly specified. Also,
+the optional argument ``--variant-name`` is missing, so the layers will be merged
+as ``custvariant_``.
+
+Options list
+------------
+ --version show program's version number and exit
+ -h, --help show this help message and exit
+ --print-settings Print all the default settings from the current
+ setting container.
+ --print-supported-impls
+ Print all supported ImplML XML namespaces and file
+ extensions.
+ --print-runtime-info Print runtime information about ConE.
+ -v LEVEL, --verbose=LEVEL
+ Print error, warning and information on system out.
+ Possible choices: Default is 3.
+ NONE (all) 0
+ CRITICAL 1
+ ERROR 2
+ WARNING 3
+ INFO 4
+ DEBUG 5
+ --log-file=FILE Location of the used log file. Default is 'cone.log'
+ --log-config=FILE Location of the used logging configuration file.
+ Default is 'logging.ini'
+ --username=USERNAME Username for webstorage operations. Not needed for
+ filestorage or cpf storage. If the username
+ is not given, the tool will use the logged in
+ username. Example: cone export -p webstorage_url -r .
+ -c sample.confml --username=admin --password=abc123.
+ --password=PASSWORD Password for webstorage operations. Not needed for
+ filestorage or cpf storage. If the password
+ is not given, the tool will prompt for password if
+ needed.
+ -p STORAGE, --project=STORAGE
+ Defines the location of current project. Default is
+ the current working directory.
+
+ Initvariant options:
+ The initvariant action is intended for merging a variant CPF back into
+ the configuration project. It merges all customer variant layers
+ (layers with custvariant* in their path name) and renames them based
+ on the variant ID and variant name ("custvariant__").
+
+ -c CONFIG, --configuration=CONFIG
+ Defines the name of the target configuration. By
+ default the configuration file name is composed of
+ product name, variant ID and variant name like this:
+ _custvariant___root.confml
+ -r STORAGE, --remote=STORAGE
+ Defines the location of remote storage (CPF)
+ -s CONFIG, --sourceconfiguration=CONFIG
+ Defines the name of the remote configuration inside
+ the remote storage. Default is the active root of the
+ remote project.
+ --variant-id=VARIANT_ID
+ Variant ID, mandatory.
+ --variant-name=VARIANT_NAME
+ Variant name, optional.
+ --product-name=PRODUCT_NAME
+ Product name, taken from the configuration data by
+ default (i.e. defaults to '${imakerapi.productname}')
+ --set-active-root Set the newly created (or merged) configuration root
+ as the project's active root after the merge is done.
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/rootflatten.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/doc/cli/rootflatten.rst Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,52 @@
+ConE rootflatten action
+=======================
+
+The *rootflatten* action is intended to be a temporary solution for enabling
+Configuration roots anywhere inside the project structure. The current
+Configuration project specification (0.4) is defined to allow configuration roots
+only in the project root folder, so the root flatten will convert a file located
+in any subfolder of the project to root file under the project folder that follows
+the Configuration project specification.
+
+The configuration roots in the subfolders can use absolute includes to include other
+configuration roots and / or layers.
+
+
+Examples
+--------
+
+**Create a flat configuration from a Country configuration**
+
+The configuration root could for example exist in family/product/country/`product_Euro2_ALPS_02_customisation_root.confml <../_static/country/product_Euro1_ALPS_01_customisation_root.confml>`_.
+So this configuration root includes another configuration and two extra layers. The script trusts that the normal SD naming convention is in use, where all layer root confml files
+are just name root.confml (to know what is a configuration root and what is a layer).
+
+Commands::
+
+ > cd configproject_root
+ > cone rootflatten -c family\product\country\product_Euro2_ALPS_02_customisation_root.confml
+ Running action rootflatten
+ Processing configurations ['family\\product\\country\\product_Euro1_ALPS_01_customisation_root.confml']
+ opened family\product\country\product_Euro1_ALPS_01_customisation_root.confml for flattening
+ Creating a new configuration root 'product_Euro1_ALPS_01_customisation_root.confml' for flattening
+
+After the conversion there will be a file with the same name in root where includes are flattened and meta data is merged.
+ * See `product_Euro2_ALPS_02_customisation_root.confml <../_static/product_Euro1_ALPS_01_customisation_root.confml>`_
+
+
+Options list
+------------
+Options:
+ -h, --help show this help message and exit
+ -c CONFIG, --configuration=CONFIG
+ Defines the name of the configuration for the action,
+ can be specified multiple times to include multiple
+ configurations.
+ --config-wildcard=WILDCARD
+ Wildcard pattern for including configurations, e.g.
+ product_langpack_*_root.confml
+ --config-regex=REGEX Regular expression for including configurations, e.g.
+ product_langpack_\d{2}_root.confml
+ -p STORAGE, --project=STORAGE
+ defines the location of current project. Default is
+ the current working directory.
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/cli/validate.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/doc/cli/validate.rst Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,103 @@
+.. _cli-action-validate:
+
+ConE validate action
+====================
+
+The validate action can be used to validate individual ConfML and ImplML files,
+or an entire configuration. See also :ref:`validation-overview`.
+
+Examples
+--------
+
+**Validating a single ConfML file**::
+
+ cone validate --confml-file something.confml
+
+This will validate the specified ConfML file and generate a report in
+``validation_report.html`` using the default html report template. If you would like to
+produce an xml report ``validation_report.xml`` (which is based on Diamonds format) use the following command instead::
+
+ cone validate --confml-file something.confml --report-type xml
+
+* Example output `Validation report for Diamonds <../_static/report.xml>`_
+
+**Validating multiple ConfML files**::
+
+ cone validate --confml-file file1.confml --confml-file file2.confml
+
+This will validate the list of specified ConfML files with --confml-file option. Several Implml files can be validated correspondingly with
+--implml-file option.
+
+**Validating an entire configuration**::
+
+ cone validate --project myproject --configuration myconfig.confml
+
+This will find all ConfML and ImplML files in the configuration and validate
+them, generating a report into ``validation_report.html``. The command output
+might look something like this::
+
+ C:\>cone validate --project myproject --configuration myconfig.confml
+ Running action validate
+ Project: myproject
+ Configuration: myconfig.confml
+ Finding ConfML files in configuration...
+ 282 ConfML file(s)
+ 2 problem(s) while parsing
+ Performing XML schema validation on ConfML files...
+ 40 problem(s)
+ Validating ConfML model...
+ 34 problem(s)
+ Finding ImplML files in configuration...
+ Found 393 supported files
+ Performing XML schema validation on ImplML files...
+ 7 problem(s)
+ Parsing implementations...
+ Validating implementations...
+ 1 problem(s)
+ Total 84 problem(s) after filtering
+ Generating report...
+ Generated report to 'validation_report.html'
+
+
+**Validating only ConfML files in a configuration**::
+
+ cone validate --project myproject --configuration myconfig.confml --include-filter *.confml
+
+This will run the same validation as in the previous example, except that
+ImplML files are not validated.
+
+**Validating only ImplML files in a configuration**::
+
+ cone validate --project myproject --configuration myconfig.confml --include-filter *.implml
+
+**Performing only schema validation**::
+
+ cone validate --project myproject --configuration myconfig.confml --include-filter schema
+
+Options list
+------------
+
+ --confml-file=FILE Validate only the given single ConfML file.
+ --implml-file=FILE Validate only the given single ImplML file.
+ --template=FILE Template used in report generation. Example:
+ --template report_template.html.
+ --report=FILE Specifies the location of the validation report.
+ Example --report report.html.
+ --report-type=TYPE The type of the report to generate. This is a
+ convenience switch for setting the used template. If
+ --template is given, this option has no effect.
+ Possible values:
+ xml - Generate an xml report
+ html - Generate html report
+ --dump-schema-files=DIR
+ Dump the XML schema files used for validation into the
+ specified directory.
+ --exclude-filter=EXCLUDE_FILTER
+ Exclude validation problems by given filter. Examples:
+ --exclude-filter=schema, --exclude-
+ filter=schema.implml, --exclude-filter=schema.confml,
+ --exclude-filter=schema.implml.ruleml
+ --include-filter=INCLUDE_FILTER
+ Include validation problems by given filter.Examples:
+ --include-filter=schema.implml, --include-
+ filter=schema.implml.ruleml
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/conf.py
--- a/configurationengine/doc/conf.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/conf.py Tue Aug 10 14:29:28 2010 +0300
@@ -51,15 +51,15 @@
# General substitutions.
project = u'ConE'
-copyright = u'2008, Nokia Corporation and/or its subsidiary(-ies)'
+copyright = u'2008, Teemu Rytkönen'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.1'
+version = '1.2'
# The full version, including alpha/beta/rc tags.
-release = '1.1.5'
+release = '1.2.11DEV'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/development.rst
--- a/configurationengine/doc/development.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/development.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,32 +1,99 @@
-Cone development
-================
+.. _cone-development:
+
+Development with ConE
+=====================
This page should describe all relevant information on any developer who has or will create any functionality on
top of the ConE functionality.
-
-ConE is open source
--------------------
+ConE in SF
+----------
ConE is a open source project (Currently under Eclipse Public License v1.0), which can take contributions from anyone interested in ConE. In future the ConE
-will propably be split to two separate parts; core and plugins. The core of ConE is mainly the public interface
-and the storage agnostic functionality of ConE. This core part is intended to be more generic and functional on
-any platform. The plugin part is meant for extensions of ConE that could be for example platform specific
-implementation plugins that generate output files based on the configurations.
+will propably be split to two separate parts; ConE *core* and ConE *plugins*.
+
+The core of ConE is mainly the public interface and the storage agnostic functionality of ConE.
+This core part is intended to be more generic and functional on any platform.
+
+The plugin part is meant for extensions of ConE that could be for example platform specific implementation plugins
+that generate output files based on the configurations.
+
+
+Development environment
+-----------------------
+The development environment requires a set of python packages, which you mostly install with easy_install after
+installation of setuptools. So you must install the necessary libraries in order to be able to do cone development.
+The best way to test whether your development environment has everything that is required is to run all the unittest
+of cone (See :ref:`cone-development-test-running`). When everything works, your environment is properly
+setup :)
+
+**Required Python packages**
+ - jinja2
+ - simplejson
+ - lxml (at least version 2.2.2) run easy_install lxml==2.2.2
+ - nose (for running testing)
+ - epydoc (for documentation generation)
+ - sphinx (for documentation generation)
+
+
+To install the above packages, run easy_install
-Developing ConE plugin
-----------------------
+easy_install call::
+
+ easy_install
+
+easy_install jinja2 package::
+
+ easy_install jinja2
+
+
+.. _cone-development-test-running:
+
+Running tests
+-------------
+The different packages inside cone have a tests subpackage which contains all the tests for that particular package.
+Each package also contains a runtests.py file that runs all tests inside that package with `nose `_.
+
+The higher levels packages also contain a runtests.py which also collect all subpackage tests, so you can basically
+run every test of cone source by running the runtests.py at the root of source directory.
+
+**Setting PYTHONPATH**
-See :ref:`plugin-howto`.
+The cone modules need to be set to the PYTHONPATH to enable test running. If you are using eclipse with PyDev as
+developement environment, the PYTHONPATH should be automatically correct as the eclipse .project file is included
+in version control.
+
+For command line testing you can run the testing_paths.cmd/testing_paths.sh to set the PYTHONPATH correctly.
+After that you should be able to run individual test are all test with a normal python call .
+
+running all cone tests::
+
+ cd source
+ python runtests.py
+
+
+running individual unittest example::
+
+ cd source/cone/public/tests
+ python unittest_configuration.py
+
+running all module tests::
+
+ cd source/cone/public/tests
+ python runtests.py
+running tests with nose::
+
+ Tests can also be run with nose, effectively this is the same as running the runtests.py
+
+ cd source/cone/
+ nosetests --include=unittest
+
Using ConE API
-==============
+--------------
.. toctree::
:maxdepth: 2
api/api
- rule
-
-
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/extref.rst
--- a/configurationengine/doc/extref.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/extref.rst Tue Aug 10 14:29:28 2010 +0300
@@ -8,8 +8,10 @@
configurationml085
-ConE API documentation
-----------------------
+.. _cone-api-epydoc:
+
+ConE API documentation (epydoc)
+-------------------------------
* `Cone API epydoc <./epydoc/index.html>`_
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/index.rst
--- a/configurationengine/doc/index.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/index.rst Tue Aug 10 14:29:28 2010 +0300
@@ -8,7 +8,7 @@
Contents:
.. toctree::
- :maxdepth: 2
+ :maxdepth: 3
intro
cli/common
@@ -16,6 +16,7 @@
plugins/index
extref
imakercone
+ validation-overview
Indices and tables
==================
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/intro.rst
--- a/configurationengine/doc/intro.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/intro.rst Tue Aug 10 14:29:28 2010 +0300
@@ -7,26 +7,31 @@
#. ConE plugin API (A plugin interface to add functionality to ConE)
#. ConE command line interface (tools/utilities that use the API)
-ConE API
---------
+ConE API introduction
+---------------------
The ConE API tries to offer a simple way to access the configurations inside the Configuration
project. The concepts of confml and the Configuration project are quite complicated, but the API
simplifies the project quite a bit to enable effective programming. Although the API aims for
simplicity, everything is made available via the API.
-The API is described in this document with python api documentation tool *epydoc*.
+
+The API is described in :ref:`cone-api` with a :ref:`cone-api-howto` and with python api documentation tool *epydoc*.
-ConE plugin API
----------------
+ConE plugin (extension) API
+---------------------------
The purpose of the plugin API is to offer the possibility to expand the functionality of Configuration project. Normal use case
is an implementation plugin which reads data from the configuration and transforms it into some other form
-(e.g. centralrepository text file).
+(e.g. centralrepository text file).
-ConE command line interface
----------------------------
+See :ref:`plugin-api`.
+
+ConE command line interface introduction
+----------------------------------------
The main purpose of ConE is to offer the above APIs, but ConE installation as tool
offers also set of command line utilities that can used to modify, read and utilize (generate other output files
with implementation plugins) from a Configuration project. These utilities lie on the cone-script package and
-are described in the ConE command line interface section.
+are described in the ConE command line interface section.
+
+See :ref:`cone-cli`
Installation
------------
@@ -100,9 +105,8 @@
Fetch the latest ConE build from our CruiseControl build server (works only in Nokia intranet):
-* Goto http://trwec021.nmp.nokia.com:8080/buildresults/cone-build
-* Click on the Build Artifacts to get the latest build. Older builds are also available for some time.
-* Download the zip file
+* Goto https://trace1.isource-nokia.nokia.com/trac/cone/wiki/ConeReleases
+* Download the release zip file from ConE releases.
The ZIP file should contain a pre-built standalone installation described in the previous section.
Simply unzip it where you please.
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/commandml-plugin/commandml.rst
--- a/configurationengine/doc/plugins/commandml-plugin/commandml.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/commandml-plugin/commandml.rst Tue Aug 10 14:29:28 2010 +0300
@@ -178,6 +178,12 @@
+NOTE! In CommandML localPath is handled as any other string, so don't expect the localPaths of file and folder settings
+to work directly. A localPath is just a string that references files and folders under the configuration project content
+(e.g. 'somedir/somefile.txt', which could physically be located under 'somelayer/content/somedir/somefile.txt').
+If you need an absolute path to the actual file, you need to obtain that yourself using the ConE API. You may
+also need to write the file to a temporary folder, since we might be generating from a CPF.
+
Element
**************************
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/convertprojectplugin.rst
--- a/configurationengine/doc/plugins/convertprojectplugin.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/convertprojectplugin.rst Tue Aug 10 14:29:28 2010 +0300
@@ -103,6 +103,119 @@
Examples
'''''''''
+Defining layer
+'''''''''
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Normally targetProject's **path** attribute is defined as empty. It means that the project is generated to ConE's normal output location which can be given as command line parameter (-o).
+
+Convert project ML is constructed so that the highest data structure is **layer**. Layer has attribute **path**, which defines relative location to output path. Layer can contain one or more
+**folders** and/or **files**.
+
+Folder defines folder entry inside the layer and in file system level is a directory. Folder has **path** attribute which is relative to layer's path. Folder can contain **filters** which define
+how folder's content is constructed. With action **add** data is copied to the folder from location which is defined in **data** attribute.
+**Note** that the path in data attribute is relative to configuration project's root (normally \epoc32\rom\config). Example here copies all crml and gcfml files from confml folder to impml folder.
+
+Layer can also define files. Each file has **type** which can be layer_root or configuration_root. The former one is creating layer root file to the path defined in **path** attribute, location is
+relative to layers location. Action **include_file** defines a search pattern. In the example all files from layer's confml folder with extension confml are included in the layer's root file. This can
+be used to generate layer root files automatically in the build even when the exact content in filename level is not known. Configuration root files are always generated to the root of the
+configuration project. Filter action **include_layer** defines configuration layer root files which are included to the configuration root.
+
+
+Defining metadata and configuration name
+'''''''''
+.. code-block:: xml
+
+
+
+
+
+
+
+ 001
+
+
+
+
+
+
+File element's **configuration_name** attribute can be used to override ConE's default configuration name. Value is written to ConfML file's configuration element to name attribute. **Meta**
+structure defines ConfML metadata which is added to configuration root file. It supports normal ConfML metadata like in this example **version** and cv namespace metadata like **sw_version**.
+Value of sw_version is fetched from ConfML setting **convertproject.versioninfo** at run time. Configuration_name and metadata are available to both layer and configuration root files.
+
+Creating loops
+'''''''''
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Loops can be defined in convert project ml using **foreach** structures. Attribute **data** defines path where from all the folder names are scanned. Value of attribute **variable** is the
+name of the folder e.g. if /epoc32/rom/config/language_packs contains folders *lp1*,* lp2* and *lp3* then variable has value lp1 in the first round, lp2 in the second round and lp3 in the third round.
+Meaning that in the first round layer path will be language_packs/lp1 and configuration root file name is langpack_lp1_root.confml, which includes language_packs/lp1/root.confml as the last layer root.
+
+Extending configuration root information
+'''''''''
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The first part is exactly same as above. What has been added is a new layer which includes only one file generated in the example above. Example here adds extra metadata *'based_on_ctr** to
+the configuration root langpack_lp1_root.confml. Note that convert project ml works so that if there is no existing file then that is created in case file exists then it is updated.
+
+
XSD
'''
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/confml-validation-classes.jpg
Binary file configurationengine/doc/plugins/dev-plugin/confml-validation-classes.jpg has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/diagrams.uml
--- a/configurationengine/doc/plugins/dev-plugin/diagrams.uml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/dev-plugin/diagrams.uml Tue Aug 10 14:29:28 2010 +0300
@@ -71,7 +71,7 @@
1
-ImplContainer
+ImplSetFalse
@@ -400,7 +400,7 @@
26417853
-ImplContainer contains a number
+ImplSet contains a number
of implementation instances and
generates output using them.
@@ -510,7 +510,7 @@
38420283
-When an ImplContainer is created
+When an ImplSet is created
on a Configuration,
ImplFactory.get_impls_from_file()
is used on all supported files to create
@@ -538,7 +538,7 @@
49619268
-ImplContainer.get_impls_from_file()
+ImplFactory.get_impls_from_file()
in turn uses all registered reader
classes to create the actual
implementations.
@@ -571,40 +571,41 @@
56816190
-38
+53ImplBase and ReaderBase comprise
-the ConE plug-in interface
+the ConE plug-in interface for
+implementations.
clMaroon$00B9FFFF
-569,139;645,53
+569,141;638,68D2lNkx9zqkGIrORCziB2MwAAKeRNcoIQK0KSH6AGF9UzjAAAclMaroon$00B9FFFF
-727,152;672,53
+726,152;677,68D2lNkx9zqkGIrORCziB2MwAA2t2cUMI4f0SGZ3fMzCfV2QAAclMaroon$00DFFFFF
-20
+241216738
-ImplContainer is used when
+ImplSet is used when
generating output using ConE.
clMaroon$00B9FFFF
-166,148;113,49
+167,148;117,49v84tCD/ORU6aA+sNvC8HbgAAEFzcsknNQ0O+rr8VseO9MAAA
@@ -798,9 +799,9 @@
-17
+16
-ImplContainer
+ImplSetNmvwO09X4Uu7xy6qNwdIDQAA4EFzcsknNQ0O+rr8VseO9MAAA
@@ -935,11 +936,7 @@
ConfigurationNmvwO09X4Uu7xy6qNwdIDQAA
-
-Jung, Yoontae
-NmvwO09X4Uu7xy6qNwdIDQAA
-
-
+SomeImplReaderNmvwO09X4Uu7xy6qNwdIDQAA4
@@ -953,7 +950,7 @@
eu5J5ZGSGUmZFfbh0cHFewAAAeNNCbWnPEKWIb774GWlfQAA
-
+NmvwO09X4Uu7xy6qNwdIDQAAJQvuxGbsdE2jFadShkxqKgAAg0zWWZA9xEWvFh0sRnmMqgAA
@@ -963,7 +960,7 @@
oxtgEPTKIkyuZW+/1ioAPAAAC3LeagDb40ac4fqEDvNK5AAA
-
+NmvwO09X4Uu7xy6qNwdIDQAArDKOyCdZEkCOx+oFSF1RfgAAlPra4OiszU2H/arMBBwTVgAA
@@ -973,7 +970,7 @@
cxdf5fynWEG7/Wzlz9wAZgAACOnrVcktJUCdGcPafp3OSAAA
-
+NmvwO09X4Uu7xy6qNwdIDQAA4qO84lDa9Q0qJdFLxAzRcQQAA
@@ -986,8 +983,8 @@
g0zWWZA9xEWvFh0sRnmMqgAA46HcxdQob+UOT1wCYJ4QeHgAA
-MfI12JH1kkSbXGyVvMqqXQAA
-tMamOzqFxk6hZeNgqluobwAA
+tMamOzqFxk6hZeNgqluobwAA
+MfI12JH1kkSbXGyVvMqqXQAA/ARNc/hPvUmBl4qb/XiPqQAA
@@ -996,12 +993,12 @@
q11CD3et4kixnDRLW4nPdgAA4ymxDIXyVUESDyLIcICrGWQAA
-9JS131H/4US3bVVB0X+RIAAA
-I8zAzIUs30G8GAyGAkzPOAAA
+I8zAzIUs30G8GAyGAkzPOAAA
+9JS131H/4US3bVVB0X+RIAAAitBAlqtdlUK0IXNYnX3+mQAA
-
+createsNmvwO09X4Uu7xy6qNwdIDQAA4
@@ -1016,8 +1013,8 @@
rDKOyCdZEkCOx+oFSF1RfgAA4hIeXX5pEhk+9J80xff/Z2QAA
-Jn/ACJad8kOY5lGCpXLetQAA
-USMA9tEXpkGY+pAIVRjLHAAA
+USMA9tEXpkGY+pAIVRjLHAAA
+Jn/ACJad8kOY5lGCpXLetQAAWNomTSYdhk6j1wGMK0aBMQAA
@@ -1025,24 +1022,24 @@
JQvuxGbsdE2jFadShkxqKgAA4vMwGVXrxPkCKOvOAPR6ytQAA
-BAaRrPSiRkWfQQrnfeF5BQAA
-b6bOArvlz0+mgsrQHIOI8wAA
+b6bOArvlz0+mgsrQHIOI8wAA
+BAaRrPSiRkWfQQrnfeF5BQAArACoLZEoXESlgVdLXl1ocQAA
-
+SomePluginNmvwO09X4Uu7xy6qNwdIDQAA1xW95yby7XEChYzUI8UtliAAA
-
+ConENmvwO09X4Uu7xy6qNwdIDQAA1Nppn0CUEP0Stsi3DAR1qEQAA
-
+usesNmvwO09X4Uu7xy6qNwdIDQAA4
@@ -1057,8 +1054,8 @@
q11CD3et4kixnDRLW4nPdgAA4YQ4SH0PbkU6D2Ed6kFWZ3gAA
-au7s+O1a6EOhU92BZ9mTfAAA
-uC7b5/Ag8E+lVXijU0puEAAA
+uC7b5/Ag8E+lVXijU0puEAAA
+au7s+O1a6EOhU92BZ9mTfAAASutSAX/p70WlhiBCYP5mIQAA
@@ -1066,12 +1063,12 @@
3dlH2vm6sEayyvEaXZoCngAA4Rn+WUty/KE6o3UWIZm/++wAA
-7gOWzEGpb0KSajbXDeX03QAA
-e/X32+GrOUiRRJMneGhhrwAA
+e/X32+GrOUiRRJMneGhhrwAA
+7gOWzEGpb0KSajbXDeX03QAA1RN9/oe60kCHXG3xE2fYmQAA
-
+usesNmvwO09X4Uu7xy6qNwdIDQAA4
@@ -1086,8 +1083,8 @@
3dlH2vm6sEayyvEaXZoCngAA4Ao1mzGyZkUOXJ7iUZ+CxmQAA
-Mlo0JoqcnUWmKG46gdW/pgAA
-60bFmV8mJ02N5+zPFmP+cAAA
+60bFmV8mJ02N5+zPFmP+cAAA
+Mlo0JoqcnUWmKG46gdW/pgAAhQN6K9SliEunBHaWLwTWywAA
@@ -1095,8 +1092,8 @@
rDKOyCdZEkCOx+oFSF1RfgAA465oSMAg0mkmODMiMbf+UjQAA
-6vvMJYaqA0+EsdkZT8o6oAAA
-znikN5jxMkWgoTVeUx7U0wAA
+znikN5jxMkWgoTVeUx7U0wAA
+6vvMJYaqA0+EsdkZT8o6oAAAAnbfKLYaZ0qC8tWUwfnFkgAA
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/dev-plugin/example-plugin.rst
--- a/configurationengine/doc/plugins/dev-plugin/example-plugin.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/dev-plugin/example-plugin.rst Tue Aug 10 14:29:28 2010 +0300
@@ -12,9 +12,11 @@
- Implementation class
- Implementation model
- Using ``cone.public.utils`` for ConfML setting reference handling
+- Providing XML schema validation and model-level validation
- Unit tests:
- Testing the reader class, the implementation class and the model classes separately
- Output generation testing (plug-in scope integration test)
+ - Validation testing
The ExampleML language
----------------------
@@ -55,16 +57,19 @@
- ``ConeExamplePlugin/`` - Source for the example plug-in
- ``examplemlplugin/`` - Module directory containing all plug-in code
- ``tests/`` - Unit tests and test data for the plug-in
- - ``project/`` - Configuration project used in the tests
- - ``gen_expected/`` - Expected output for generation test case
+ - ``testdata/`` - Directory containing all test data needed by the test cases
- ``__init__.py`` - Test module initialization file
- ``runtests.py`` - Script for running all test cases
- ``unittest_exampleml_impl.py`` - File containing test cases
- ``unittest_exampleml_reader.py`` - File containing test cases
- ``unittest_exampleml_generation.py`` - File containing test cases
+ - ``unittest_exampleml_validation.py`` - File containing test cases
+ - ``xsd/`` - XML Schema files for schema validation
+ - ``exampleml.xsd`` - Schema file for schema validation
- ``__init__.py`` - Plug-in module initialization file
- ``exampleml_impl.py`` - Plug-in source file
- ``exampleml_reader.py`` - Plug-in source file
+ - ``exampleml_validators.py`` - Plug-in source file
- ``setup.py`` - Setup script for packaging the plug-in into an .egg file
- ``setup.cfg`` - Configuration file for ``setup.py``
- ``integration-test/`` - Integration tests for the example plug-in package
@@ -83,7 +88,10 @@
- *Implementation class*, works as the interface of the plug-in towards ConE and uses the model to do the actual work
- *Implementation reader*, converts the XML data into the logical model and creates a new implementation class instance
-In this case the *model* consists just of the class Output, which corresponds to the ``
+9
+
+imageml
+I0mGM2cIbES/2vP45srj7AAA
+4
+/Aq0TH5t8EiVzBQ4GkGa/AAA
+oo6cEQcGZkCg59IpDpoW1gAA
+ope+PrJaFkKCz0QZuJl2YAAA
+NS9a+EIZ60SAXPkpGONIZwAA
+1
+cR78ghIdUUaPftW/gFc/yAAA
+
+
+output
+I0mGM2cIbES/2vP45srj7AAA
+4
+2yz5/OUBRUKzrr3xYqPQ+AAA
+xT3UbHUMUE6tacvQOi3vFAAA
+tJ6YyShrb0qkaUZTlTqLRAAA
+LZMFamho/k+gl1zYCKOxLAAA
+2
+Z/WCj9Ir1Uua8nPwAz0BOAAA
+sJQEHCEx7kGDl0V2tep+ewAA
+5
+
+file
+CouoggW8r0OOBNQ9jNxO6wAA
+
+
+tool
+CouoggW8r0OOBNQ9jNxO6wAA
+
+
+palette
+CouoggW8r0OOBNQ9jNxO6wAA
+
+
+extraparams
+CouoggW8r0OOBNQ9jNxO6wAA
+
+
+tooldir
+CouoggW8r0OOBNQ9jNxO6wAA
+
+
+
+input
+I0mGM2cIbES/2vP45srj7AAA
+4
+3nJAwrIQQ02ZlQ/Rjto/1wAA
+H6NcM+PBwUShMknSOVID3QAA
+1Mo5wmxejE6FTM5akRaAdgAA
+TdFa+ERT2kaLfVN9wUnP8QAA
+3
+aOIUpy17wEu1onMvkPLDZwAA
+M1sojijAckaHORNZ6AKvSgAA
+cDxLP9sd7EqSP+9VET4kGgAA
+4
+
+dir
+NnSa/LdMlkaJlBQz+1Y2+AAA
+
+
+file
+NnSa/LdMlkaJlBQz+1Y2+AAA
+
+
+depth
+NnSa/LdMlkaJlBQz+1Y2+AAA
+
+
+optional
+NnSa/LdMlkaJlBQz+1Y2+AAA
+
+
+
+include
+I0mGM2cIbES/2vP45srj7AAA
+4
+faGCnxpYz0SvcMgXl5/tzgAA
+kn38iT7TP0G49oA5OMx2cwAA
+qFlX0PRVlkKchtOy4x8UYQAA
+I25jxMkN8kamWC8cZlMWkQAA
+1
+3PfRfm/wr02VIWBqM76erwAA
+1
+
+pattern
+mgS5RRx5dkWAWIQMpavygAAA
+
+
+
+exclude
+I0mGM2cIbES/2vP45srj7AAA
+4
+iajjxaOU7E+x5X6fMy+ongAA
+0jE4q+Le8U65zLfiG9DybAAA
+KkuKK1ExWUqNI4Js4lFGVwAA
+pmgGrKsDo0iaj680s/M4SgAA
+1
+69rEKoPGI0mo75lP5BvwtAAA
+1
+
+pattern
+NJ7DLEDyw0+w4FnIFdtdCQAA
+
+
+
+I0mGM2cIbES/2vP45srj7AAA
+4
+2AbWyaJex0OAE4+eJk3TZAAA
+nz/ZuAL35UCRaeXVyhOpjAAA
+V4ilVpQd7EWyZKf5QVnbWQAA
+M/sNRWrTkkaPJFYpWFee9AAA
+2
+
+0..*
+0q7RIUYseEewHATv7QqdaQAA
+mgS5RRx5dkWAWIQMpavygAAA
+4
+2eQMCtC1LUSQLYX64dgcRwAA
+c1dxawLR7EGpg2ol4F4xKgAA
+E+2944gbJ02FZkYrAvDtcgAA
+OZTqZxmCcke/+xkjwB/JoQAA
+
+
+akAggregate
+0q7RIUYseEewHATv7QqdaQAA
+NnSa/LdMlkaJlBQz+1Y2+AAA
+4
+gB3opu8rBESXdIQhV59XVgAA
+1DClOyS2OEWUiH4oKwzpiAAA
+U7rCMTFn7UeJoGquwrxotAAA
+E6QllHCf30Onm2SAzLaLXgAA
+
+
+
+I0mGM2cIbES/2vP45srj7AAA
+4
+m8gZrs5j0kStnzfQ61UrrgAA
+4/fEL3oefk6PU+0Nze5S8wAA
+5vqa4svcc0Comg+i8yQQxQAA
+U366XjrXzESRB/Bieu6tmgAA
+2
+
+0..*
+IFIQQJ7iSEO69Wh+e5lJygAA
+NJ7DLEDyw0+w4FnIFdtdCQAA
+4
+RdOeRaBBGkWsnreusrvSfwAA
+mlyfdg+wL0q/0vLzXffvCQAA
+wRtRzltGBUK1inpq/EC8egAA
+w2KVtQGYrE+EMx8cVRcgugAA
+
+
+akAggregate
+IFIQQJ7iSEO69Wh+e5lJygAA
+NnSa/LdMlkaJlBQz+1Y2+AAA
+4
+EaPwhC1GhkG4oL0wGBBZ1AAA
+SPMybHF1eUSsFaKxqWSp3AAA
+6j00UUyF8UevCPsWi8kQ8AAA
+5Rj3LCxAVEWJ8f/S+pUdHQAA
+
+
+
+I0mGM2cIbES/2vP45srj7AAA
+4
+nVRV8yqOakqLSBoMvGN3XQAA
+AfGmb0HBA0itzUbEcTS/DgAA
+RQXCZc+TbUiTJrp+ECPS3QAA
+8mRCB/h06UqRKV2aY+W3vQAA
+2
+
+1..*
+POtOWRvYQ0WO9SQIvdJpeQAA
+NnSa/LdMlkaJlBQz+1Y2+AAA
+4
+Yb5TsbsoPEuXLv0a1Oa1VgAA
+DgdfsZ/1EUaPJtwrv9oObgAA
+vRJPlJAtMEa1WsFNfA8DIgAA
+S+RFAzInsE6oZfmlKXcr5gAA
+
+
+akAggregate
+POtOWRvYQ0WO9SQIvdJpeQAA
+CouoggW8r0OOBNQ9jNxO6wAA
+4
+gWzPC9cNGk2YkCCxvmViMwAA
+8LRKIYEdMUKDivgFqolYewAA
+CSH1BjC5Aky2/PkypiyIHQAA
+o8D1LCtfO0KT5LUKf/6RXwAA
+
+
+
+I0mGM2cIbES/2vP45srj7AAA
+4
+NzRfVxtFpkSA1aniBttYKgAA
+3oDW+x67KkKJoi/dFuoELgAA
+8mmjDm5UV0+QfL8hYUtWmQAA
+8niOI1RfT0O1WPjJpU0O9wAA
+2
+
+0..*
+rbj+IedETU6G6PuTN46nBAAA
+CouoggW8r0OOBNQ9jNxO6wAA
+4
+FswOCQPKf0OKYV9XBXU70wAA
+kgoOqeIDPUix8ry7KlL4IgAA
+kKyrpkZo0Eie9EpreVwklgAA
+/eclq88P0Ui5/jTyRxj/3gAA
+
+
+akAggregate
+rbj+IedETU6G6PuTN46nBAAA
+CRuOLYF7gU2l1tg34dY6bgAA
+4
+b9ayalGDS0arYeNwSxzJPAAA
+4bpVhzadBUuAYszaNIVSawAA
+D6kl60xIk0OMxRE54qI91wAA
+2ziLW5/dfkmoaaRaHu0/gwAA
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/ruleml-plugin/ruleplugin.rst
--- a/configurationengine/doc/plugins/ruleml-plugin/ruleplugin.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/ruleml-plugin/ruleplugin.rst Tue Aug 10 14:29:28 2010 +0300
@@ -1,163 +1,262 @@
User guide for Rule Plugin usage in ConE
-----------------------------------------
+========================================
+
+.. note::
+ RuleML v3 is now the officially supported RuleML version.
+ Support for versions 1 and 2 is still present in ConE, but they will not
+ be maintained anymore. If you have e.g. a RuleML v2 file and require some
+ new functionality, the new functionality will be added to RuleML v3 and
+ you will need to update your RuleML file to use version 3.
+
+ Updating should be easy, since the biggest change is setting reference
+ syntax. Simply add ``${}`` around all setting references in the rules.
Introduction
-'''''''''''''
-This page describes how to use ConE Rule plugin. With rule plugin one may set rule configuration
-for the values in the confml. So for ex. one may have a case where is one confml value is been setted
-and one may create a rule configuration that if this value is for ex. 'foo' then some other value is
-'bar'. Value may be required or configures.
+------------
+This page describes how to use the ConE Rule plugin. The plug-in provides
+support for RuleML files, which can be used to execute rules during output
+generation. The main use for RuleML is modifying the values of ConfML settings
+on run-time based on the values of other settings.
+The rule plug-in registers the ImplML namespace for defining rules, and the
+RuleML-specific file extension:
-Creating a rule configuration file
-''''''''''''''''''''''''''''''''''
-Create a new file a example.ruleml and set it's file encoding to UTF-8.
-Place the file in the impml folder in configuration project.
-The file is a XML base file.
-First set the encoding tag
+ * Namespace: ``http://www.s60.com/xml/ruleml/3``
+ * File extension: ``ruleml``
+
+.. note::
+
+ More information about :ref:`file extensions `.
+
+Usage
+-----
+
+A RuleML file is simply an XML file that defines a set of rules. For example:
.. code-block:: xml
- *
+
+
+ ${SomeFeature.SomeSetting} == 'testing' configures ${SomeFeature.SomeOtherSetting} = 5
+ ${SomeFeature.SomeSetting} == 'xyz' configures ${SomeFeature.SomeOtherSetting} = 6
+
-and then create a root tag
+The above example sets the value of the setting ``SomeFeature.SomeOtherSetting``
+to the integer value ``5`` or ``6`` if the value of ``SomeFeature.SomeSetting`` is
+one of the strings ``testing`` or ``xyz``.
+
+Rules can also contain multiple operations in a single rule, and can span
+multiple lines to make the rule more readable. For example:
.. code-block:: xml
- *
-
-give a set of rules for ex.
-
-.. code-block:: xml
+
+
+
+ ${SomeFeature.SomeSetting} == 'testing' configures
+ ${SomeFeature.SomeOtherSetting} = 5 and
+ ${SomeFeature.SomeOtherSetting2} = 6 and
+ ${SomeFeature.SomeOtherSetting3} = 7
+
+
- mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True*
-
-and close the ruleml tag.
-
-One may say use several boolean operators for the configuration rule like for ex.
-
-.. code-block:: xml
-
- and, or, ==, !=*
-
-Like for ex.
+Sometimes the case is that the rule should be executed always, regardless of
+the values of any other settings. To do this you can simply specify ``True``
+as the left-hand side expression:
.. code-block:: xml
- mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True*
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = 'Hello!'
+
+
+Python expressions in rules
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+RuleML has an extension to the basic rule syntax, which allows any `Python `_
+expressions to be used. These can be used to create more complex logic into
+rules than is possible with standard rule expressions. The Python expressions
+are defined between ``{%`` and ``%}``, and can be used in place of normal
+value expressions.
+
+You can access global ruleml namespace, from which you can find Configuration and Generation Context of the active execution.
+
+ * ruleml.configuration - links to `Configuration <../../../docbuild/epydoc/cone.public.api.Configuration-class.html>`_ object.
+ * ruleml.context - links to `Generation Context <../../../docbuild/epydoc/cone.public.plugin.GenerationContext-class.html>`_ object.
-means that if reference link mms/imagesize in some confml file is set to large then reference
-link pd/ref1 value is true and pd/ref2 value is set to true also.
-**All in all one may create a dependency like project configuration with ruleml files.**
-
-Ruleml version 2 adds support for calling `Python `_ expressions from rules. Python expression are defined between ``{%`` and ``%}``:
+*Examples of using Python scripts inside ruleml files:*
.. code-block:: xml
- feat1.setting2 == True configures feat2.setting2 = {% ${feat3.setting2} %}
-
-Expression return a result, that can be used in rule e.g. to set a value to some setting in configuration. These expression can be used to create more complex logic into rules that is not possible with standard rule expressions. Inside eval expressions features and feature's values can be accessed by following syntax:
-
-Accesses to the value::
+
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = {% 2 ** 16 %}
+
+
- ${Feature.Setting}
-
-Accesses to the feature object::
+This sets the value of ``SomeFeature.SomeOtherSetting`` to the evaluated value
+of the Python expression ``2 ** 16``, which is 65536.
- @{Feature.Setting}
-
-Python functions or constants that can be accessed inside expressions can be defined by ```` elements:
+Obviously, simple expressions like this cannot do much, but an expression can
+also be a function call, and functions can do almost anything. Functions (and
+also any other globals) can be specified using ```` elements.
+For example:
.. code-block:: xml
-
- def my_function1(attribute):
- return attribute + 1
-
-
- CONST_1 = "my constant"
-
-
-
-Definitions can be inside elements or definitions can be in separate file referenced with ``file`` attribute.
-The path specified in this attribute is relative to the RuleML implementation file. So, for example, if your implementation
-file's location is ``some/layer/implml/my_rules.ruleml``, the actual path specified in the above example would be
-``some/layer/implml/.scripts/evals_in_file.py``. It is recommended to place the scripts under a directory beginning
-with a dot, so that the plug-in loader does not attempt to load the .py file as an implementation (files and directories beginning
-with a dot are ignored in the implementation loading phase).
+
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
+
+
+ def power(x, y):
+ result = 1
+ for i in xrange(y):
+ result *= x
+ return result
+
+
+
+This does the same thing as the previous example, except that it uses a custom
+function to do it.
+
+It is also possible to use standard Python libraries or the
+`ConE API <../../epydoc/index.html>`_ from ````, and also
+some RuleML-specific things. Ruleml has all data from
+Configuration and Generation Context classes of the active execution. For example:
+
+.. code-block:: xml
-Running
-'''''''''''''''''''''
-
-::
-
- cone generate -p someproject.cpf -o c:/temp/coneoutput -i rulemlfile.ruleml
+
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = {% power(2, 16) %}
+
+
+ # Import the standard library urllib2 to do operations on URLs
+ import urllib2
+
+ # Import the ConE API
+ from cone.public import api
+
+ def get_project_path():
+ # The current configuration is available in ruleml.configuration
+ config = ruleml.configuration
+
+ # Return the path of the storage the current project is in
+ project = config.get_project()
+ return project.storage.get_path()
+
+
+
-Generates files out of configuration file and takes the implementation rulemlfile.ruleml in concern,
-and the output is to been set to -o given folder
-
-for more example see the cone documentation
+In this example configuration is got from ruleml. Generation Context can be
+accessed in the same way, ruleml.context will have all data stored in the
+Generation Context object.
-Examples
-'''''''''
+Generation Context values can be accessed inside the Python expressions using the
+ruleml.context like ruleml.context.output.
-
-**Ruleml version 1 file example**
+This example uses the Generation Context to get defined output folder.
+See how to access the data from the code example below.
.. code-block:: xml
-
-
- imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
- mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True
- mms.imagesize == 'small' configures pd.ref1 = False and pd.ref2 = True
- mms.imagesize == 'extrasmall' configures pd.ref1 = False and pd.ref2 = False
- mms.imagesize == 'extralarge' configures pd.ref1 = True and pd.ref2 = False
-
-
-**What do the example ruleml file means**
-
-The example file set the values upon the image size. First it sets the iMaker output
-location target and then it starts to set the mms message image size settings. So if for ex.
-*mms/imagesize* refence link value in confml file is set to *extralarge* then the value of
-*pd/ref1* is set to *true* and the value *pd/ref2* is set to false.
+
+
+
+ True configures ${SomeFeature.output} = {% get_output_folder() %}
+
+
+
+ def get_output_folder():
+ output = ruleml.context.output
+ return output
+
+
-**Ruleml version 2 file example**
+Accessing ConfML values inside Python expressions
+'''''''''''''''''''''''''''''''''''''''''''''''''
+
+ConfML setting values can be accessed inside the Python expressions using the
+same notation as elsewhere in the rules, i.e. using ``${`` and ``}``.
+For example:
+
+.. code-block:: xml
+
+
+
+
+ ${SomeFeature.SomeSetting} == 'testing' configures ${SomeFeature.SomeOtherSetting} = {% ${SomeFeature.SomeSetting}.upper() %}
+
+
+
+This sets the value of ``SomeFeature.SomeOtherSetting`` to 'TESTING'.
+
+Accessing feature objects inside Python expressions
+'''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Sometimes it is necessary to access the actual feature (or setting) object that
+ConE uses internally to perform more complex operations. This can be done
+similarly to accessing the setting values, the only difference is that the
+setting reference needs to be surrounded by ``@{}``. For example:
.. code-block:: xml
-
-
- feat1.setting1 == 'somevalue' configures feat2.setting1 = {% len( ${feat3.setting1} ) %}
- feat1.setting2 == True configures feat2.setting2 = {% my_function1( ${feat3.setting2} ) %}
- feat1.setting3 == True configures feat2.setting3 = {% CONST_1 %}
- {% my_function2( ${feat1.setting4} ) %} configures feat2.setting4 = False
- {% @{feat1.setting5}.get_type() %} == 'int' configures feat2.setting5 = 'integer'
- feat1.setting6 == True configures feat2.setting6 = {% '0x%08X' % ${feat2.setting6} %}
-
- def my_function1(attribute):
- return attribute + 1
- def my_function2(attribute):
- if attribute == 'abc':
- return True
- else:
- return False
-
-
- CONST_1 = "my constant"
-
-
-
+
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = {% get_location(@{SomeFeature.SomeSetting}) %}
+
+
+ from cone.public import api
+
+ def get_location(setting):
+ parent_config = setting._find_parent(type=api.Configuration)
+ return parent_config.get_path()
+
+
+
+This example uses the ConE API to find the location (ConfML file) where the
+given setting is defined.
+
+
+Defining functions in a separate .py file
+'''''''''''''''''''''''''''''''''''''''''
+
+Defining the Python functions used in the rules in an ```` element
+can quickly become unwieldy for larger functions:
-XSD
-'''''''''
+- Things like ``<`` need to escaped using the corresponding XML entity references
+- Syntax highlighting is not available
+- Writing and running unit tests for the functions is not possible
+
+For these reasons, the code of an ```` element can also be
+specified in a separate Python file using the ``file`` attribute. For example:
+
+.. code-block:: xml
-Ruleml version 1: :download:`ruleml.xsd `
+
+
+
+ True configures ${SomeFeature.SomeOtherSetting} = {% some_very_complex_operation(
+ @{SomeFeature.SomeSetting1},
+ ${SomeFeature.SomeSetting2},
+ ${SomeFeature.SomeSetting3}) %}
+
+
+
-Ruleml version 2: :download:`ruleml2.xsd `
+The path specified in the ``file`` attribute is relative to the implementation
+file where the rule is specified, so if the RuleML file in this example was
+located in ``assets/example/implml/some_rule.ruleml``, the referenced Python
+file would be ``assets/example/implml/scripts/complex_function.py``.
FAQ
-'''''''''
-This will be updated based on the questions.
+---
+This will be updated based on any questions.
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/plugins/templateml-plugin/templatemlplugin.rst
--- a/configurationengine/doc/plugins/templateml-plugin/templatemlplugin.rst Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/plugins/templateml-plugin/templatemlplugin.rst Tue Aug 10 14:29:28 2010 +0300
@@ -72,7 +72,7 @@
output element
**************************
-Output element describes how one output file is generated. Output has one mandatory attribute 'file' that defines filename for output file. If you want to generate output file to some other than default folder, it can be done by defining a output directory to 'dir' attribute. Default encoding for output file is 'UTF-8', if some other encoding is wanted, it can be defined by 'encoding' attribute. This encoding should be one of the standard Python codecs encoding (see http://docs.python.org/library/codecs.html#standard-encodings).
+Output element describes how one output file is generated. Output has one mandatory attribute 'file' that defines filename for output file. If you want to generate output file to some other than default folder, it can be done by defining a output directory to 'dir' attribute. Default encoding for output file is 'UTF-8', if some other encoding is wanted, it can be defined by 'encoding' attribute. This encoding should be one of the standard Python codecs encoding (see http://docs.python.org/library/codecs.html#standard-encodings). By 'newline' attribute the output file's newline characters can be defined. The default value is 'unix' that use LF (Line feed, '\n', 0x0A) in output file. LF is used Unix-like systems and web applications. If output file has to use CR (Carriage Return) followed by LF (CR+LF, '\r\n', 0x0D 0x0A) as newline characters, 'newline' attribute should have value 'win'. CR+LF is used in non-Unix systems like DOS, Windows and Symbian OS.
Template element is mandatory child element for output element. One output element can have only one template element.
Output element can also contain optional filter elements that are specific just for this output file. Global filters that are common for all output files should be defined under root templateml element.
@@ -81,7 +81,7 @@
.. code-block:: xml
-
+
Hello world!
lambda a,b: a+blambda a,b: a*b
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/doc/xsd/confml2.xsd
--- a/configurationengine/doc/xsd/confml2.xsd Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/doc/xsd/confml2.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -1,274 +1,274 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/linux.properties
--- a/configurationengine/linux.properties Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/linux.properties Tue Aug 10 14:29:28 2010 +0300
@@ -1,1 +1,4 @@
-os.linux.userbin = /home/hudson/bin
\ No newline at end of file
+os.linux.name = Linux
+os.linux.userbin = /home/hudson/bin
+os.linux.cmdname = sh
+os.linux.cmdswitch = -c
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone.cmd
--- a/configurationengine/source/cone.cmd Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone.cmd Tue Aug 10 14:29:28 2010 +0300
@@ -29,30 +29,33 @@
set CONE_CMDARG=%*
set CONE_BASEDIR=%~dp0
+set CONE_BASEDIR=%CONE_BASEDIR%configurationengine\win\
set PYTHONCASEOK=1
+set PYTHONDONTWRITEBYTECODE=x
+
+if not exist "%CONE_BASEDIR%" (
+echo Cannot run ConE, the ConE base directory does not exist:
+echo %CONE_BASEDIR%
+exit /b 1
+)
@rem Check that Python is available
-call python -h >nul 2>&1
+call python -c None >nul 2>&1
if %errorlevel% neq 0 (
echo Python is required to run ConE!
exit /b 1
)
@REM Find out Python version
-set VERFILE=%TEMP%\cone_version_check.tmp
-python -c "import sys; print sys.version[:3]" > %VERFILE%
-set varNUM=0
-for /f "tokens=*" %%T in (%VERFILE%) do call :varSET %%T
-if exist %VERFILE% del %VERFILE%
-
+FOR /F "tokens=*" %%i in ('PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"') do SET VER1=%%i
@REM Set the used base directory based on the version
if %VER1%==2.5 (
-set CONE_BASEDIR=%CONE_BASEDIR%cone\2.5\
+set CONE_BASEDIR=%CONE_BASEDIR%2.5\
goto EndVersionCheck
)
if %VER1%==2.6 (
-set CONE_BASEDIR=%CONE_BASEDIR%cone\2.6\
+set CONE_BASEDIR=%CONE_BASEDIR%2.6\
goto EndVersionCheck
)
echo You are using an unsupported Python version (%VER1%)
@@ -67,19 +70,26 @@
exit /b 1
)
+@rem Set the egg cache dir to be unique to avoid egg extraction clashes
+@rem when running multiple parallel ConE instances
+FOR /F "tokens=*" %%i in ('PYTHON -c "import tempfile; d = tempfile.mkdtemp(); print d"') do SET EGG_CACHE_DIR=%%i
+@rem echo Egg cache dir: %EGG_CACHE_DIR%
+set PYTHON_EGG_CACHE=%EGG_CACHE_DIR%
@rem Set environment variables and run cone_tool.py
set CONE_LIBDIR=%CONE_BASEDIR%\lib
set CONE_SCRIPTDIR=%CONE_BASEDIR%\scripts
set PATH=%CONE_SCRIPTDIR%;%PATH%
set PYTHONPATH=%CONE_LIBDIR%;%PYTHONPATH%
-call python "%CONE_SCRIPTDIR%\cone_tool.py" %CONE_CMDARG%
-exit /b %ERRORLEVEL%
+REM The cone_tool will parse the arguments from the environment variable
+call python "%CONE_SCRIPTDIR%\cone_tool.py"
+set CONE_ERROR_CODE=%ERRORLEVEL%
+@rem Delete the egg cache dir
+call rd /S /Q "%EGG_CACHE_DIR%"
+
+if 0%CONE_EXITSHELL% equ 0 exit /b %CONE_ERROR_CODE%
+exit %CONE_ERROR_CODE%
endlocal
-:VarSET
-set /a varNUM=%varNUM%+1
-set VER%varNUM%=%1
-
:: END OF cone.cmd
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone.sh
--- a/configurationengine/source/cone.sh Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone.sh Tue Aug 10 14:29:28 2010 +0300
@@ -7,17 +7,15 @@
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
-# Initial Contributors:
+# Contributors:
# Nokia Corporation - initial contribution.
#
-# Contributors:
-#
-# Description:
+# Description:
# ConE tool wrapper for Unix
# Check that Python is available
# ------------------------------
-python --version &> /dev/null
+python -c None &> /dev/null
if [ $? -ne 0 ]
then
echo "Python is required to run ConE!"
@@ -28,19 +26,19 @@
# Determine the path where ConE is installed
# ------------------------------------------
-# Try to derefence a symlink
-SCRIPT_FILE=`readlink $0`
-if [ "$SCRIPT_FILE" = "" ]
+SCRIPT_FILE=`readlink -f $0`
+CONE_BASEDIR=`dirname "$SCRIPT_FILE"`/configurationengine/linux
+
+if [ ! -e "$CONE_BASEDIR" ]
then
- # Not a symlink, the first command line parameter can be used
- SCRIPT_FILE=$0
+ echo "Cannot run ConE, the ConE base directory does not exist:"
+ echo $CONE_BASEDIR
+ exit 1
fi
-CONE_BASEDIR=`dirname "$SCRIPT_FILE"`/cone
-
# Find out the Python version
# ---------------------------
-PYTHON_VERSION=`python -c "import sys; print sys.version[:3]"`
+PYTHON_VERSION=`python -c "import sys; sys.stdout.write(sys.version[:3])"`
#echo "Python version: $PYTHON_VERSION"
@@ -80,4 +78,4 @@
# Run cone_tool.py
# ----------------
-python $CONE_BASEDIR/scripts/cone_tool.py $@
+python $CONE_BASEDIR/scripts/cone_tool.py "$@"
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/__init__.py
--- a/configurationengine/source/cone/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,6 +13,5 @@
#
# Description:
#
-
-__version__ = "1.1.5"
+__version__ = "1.2.11"
_svnrevision = ""
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,22 @@
+#
+# 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:
+#
+
+import sys,os
+
+__all__ = ['resources','filestorage','zipstorage','stringstorage','webstorage']
+
+storages = ['filestorage','zipstorage','stringstorage','webstorage']
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/configroot2flat.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/configroot2flat.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,169 @@
+#
+# 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:
+#
+#!/usr/bin/env python
+##
+# @author Teemu Rytkonen
+
+import os, re, fnmatch, logging
+from cone.public import api, utils, exceptions
+from cone.confml import model as confml_model
+
+logger = logging.getLogger('cone')
+
+def get_config_list_from_project(project, configs, config_wildcards, config_regexes):
+ """
+ Return a list of configuration root names based on the given parameters.
+ @param project: The project from which to get the configuration list.
+ @param configs: List of configuration names to add. All of these should exist
+ in the project, or a ConfigurationNotFoundError is raised.
+ @param config_wildcards: List of wildcard patterns for including configurations.
+ @param config_regexs: List of regular expression patters for including configurations.
+ @return: A distinct list of configuration names matched by the given parameters. The
+ list contains matched configurations in the following order:
+ 1. Configurations specified in configs
+ 2. Configurations matched by wildcard patterns
+ 3. Configurations matched by regular expressions
+ If a configuration is matched by more than one of these, the first match determines
+ its placement in the list.
+ @raise Exception: A configuration specified in configs is not
+ actually found in the project.
+ """
+ config_list = []
+
+ # Handle configurations specified with --configuration first
+ for config in configs:
+ if not project.get_storage().is_resource(utils.resourceref.norm(config)):
+ raise Exception("No such configuration: %s" % config)
+ if config not in config_list:
+ config_list.append(config)
+
+ # Then handle wildcards
+ #print "wilds %s" % config_wildcards
+ if config_wildcards:
+ for path in project.get_storage().list_resources('.', recurse=True):
+ for wildcard in config_wildcards:
+ if fnmatch.fnmatch(path, wildcard):
+ if path not in config_list:
+ config_list.append(path)
+
+ # Lastly handle regexes
+ #print "regexes %s" % config_regexes
+ if config_regexes:
+ for path in project.get_storage().list_resources('.', recurse=True):
+ for pattern in config_regexes:
+ if re.search(pattern, path) is not None:
+ if path not in config_list:
+ config_list.append(path)
+
+ return config_list
+
+def get_flat_includes(config):
+ """
+ get a flat list of configuration in which each include of configuration root is expanded.
+ The mechanism assumes all includes that end with /root.confml to be layer includes that
+ are layers that are not expanded
+ @param config: the configuration object to process.
+ """
+ includes = []
+ for include in config.list_configurations():
+ if include.endswith('/root.confml'):
+ includes.append(utils.resourceref.remove_begin_slash(include))
+ else:
+ subconfig = config.get_configuration(include)
+ includes += get_flat_includes(subconfig)
+ return includes
+
+def get_nested_meta(config, recursion_depth=-1):
+ """
+ Get the nested meta data for the given configuration constructed from metadata of all sub configuration meta.
+ @param config: the configuration object to fetch the metadata for
+ @param recursion_depth: the depth of the recursive nested metadata calls. default value -1 will go through
+ all configurations.
+ @return: a ConfmlMeta object
+ """
+
+ meta = confml_model.ConfmlMeta()
+ if recursion_depth != 0:
+ # First recurse through all subconfigurations to get their meta
+ for subconfig_name in config.list_configurations():
+ subconfig = config.get_configuration(subconfig_name)
+ submeta = get_nested_meta(subconfig, recursion_depth-1)
+
+ meta.update( submeta )
+
+ # lastly, update the meta data of the root configuration
+ if config.meta:
+ meta.update(config.meta)
+ return meta
+
+
+class Configroot2FlatFailed(exceptions.ConeException):
+ pass
+
+class ConeConfigroot2FlatAction(object):
+ def __init__(self, **kwargs):
+ self.project = kwargs.get('project')
+ self.configs = kwargs.get('configs')
+ self.config_wildcards = kwargs.get('config_wildcards')
+ self.config_regexes = kwargs.get('config_regexes')
+ self._project = None
+
+ def run(self):
+ self._project = api.Project(api.Storage.open(self.project, 'a'))
+ prj = self._project
+
+ configs = []
+ if self.configs or self.config_wildcards or self.config_regexes:
+ configs = get_config_list_from_project(
+ project = prj,
+ configs = self.configs,
+ config_wildcards = self.config_wildcards,
+ config_regexes = self.config_regexes)
+
+ if not configs:
+ raise Configroot2FlatFailed("At least one configuration must be given!")
+
+ print "Processing configurations %s" % configs
+ for source_config in configs:
+ target_config= os.path.basename(source_config)
+ if source_config == target_config:
+ print "Cannot flatten configuration because the source path is the same as target!"
+ config = prj.get_configuration(source_config)
+
+ print "opened %s for flattening" % source_config
+
+ print "Creating a new configuration root '%s' for flattening" % target_config
+ tconf = prj.create_configuration(target_config, True)
+ # add the includes
+ for config_include in get_flat_includes(config):
+ tconf.include_configuration(config_include)
+ # add the metadata with hardcoded recursion depth count
+ newmeta = get_nested_meta(config, 2)
+ tconf.meta = newmeta
+ tconf.name = config.name
+ tconf.save()
+
+ return True
+
+ def save(self):
+ if self._project: self._project.save()
+
+ def close(self):
+ if self._project: self._project.close()
+
+
+def get_class():
+ return ConeConfigroot2FlatAction
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/fix.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/fix.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,81 @@
+
+#
+# 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:
+#
+
+"""
+Test the configuration
+"""
+import logging
+
+from cone.public import api, exceptions
+from cone.validation import confmlvalidation
+from cone.validation.problem_type_filter import ProblemTypeFilter
+
+logger = logging.getLogger('cone')
+
+class ConeFixAction(object):
+ def __init__(self, **kwargs):
+ # all action attributes are given as keyword arguments
+ self.include_filter = kwargs.get('include_filter',[])
+ self.exclude_filter = kwargs.get('exclude_filter',[])
+ self.username = kwargs.get('username',None)
+ self.password = kwargs.get('password',None)
+ self.project_name = kwargs.get('project_name', '.')
+ self.configuration_name = kwargs.get('configuration_name', None)
+ self.project = kwargs.get('project', None)
+ self.config = kwargs.get('configuration', None)
+
+
+ def run(self):
+ filter = ProblemTypeFilter(includes = self.include_filter,
+ excludes = self.exclude_filter)
+
+ # Open the project if it is not already opened
+ if self.project == None:
+ storage = api.Storage.open(self.project_name,
+ "a",
+ username=self.username,
+ password=self.password)
+ self.project = api.Project(storage)
+ if self.config == None:
+ if not self.configuration_name:
+ logging.getLogger('cone').error("No configuration given! Use -c / --configuration")
+ return False
+ try:
+ self.config = self.project.get_configuration(self.configuration_name)
+ except exceptions.NotFound:
+ logging.getLogger('cone').error("No such configuration: %s" % self.configuration_name)
+ return False
+
+ fixers = confmlvalidation.get_fixer_classes(filter)
+
+ vc = confmlvalidation.fix_configuration(self.config, None, fixers)
+
+ if vc.fixes:
+ print "Fixed %d problem(s). See log for details" % len(vc.fixes)
+ else:
+ print "No problems to fix found. See log for details"
+ return True
+
+ def save(self):
+ self.project.save()
+
+ def close(self):
+ self.project.close()
+
+
+def get_class():
+ return ConeFixAction
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/loader.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/loader.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,38 @@
+#
+# 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:
+#
+
+import os
+import sys
+import fnmatch
+import re
+import logging
+
+
+def get_class(action_name):
+ """
+ Try to get the SubAction class if it is available
+ """
+ module = get_module(action_name)
+ return module.get_class()
+
+def get_module(action_name):
+ """
+ Try to get the SubAction class if it is available
+ """
+ # trust that the scripts are all in scripts module
+ _temp = __import__('cone.action', globals(), locals(), [action_name], -1)
+ module = _temp.__getattribute__(action_name)
+ return module
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,22 @@
+#
+# 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:
+#
+
+import sys,os
+
+__all__ = ['resources','filestorage','zipstorage','stringstorage','webstorage']
+
+storages = ['filestorage','zipstorage','stringstorage','webstorage']
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/tests/unittest_configroot2flat.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/tests/unittest_configroot2flat.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,64 @@
+#
+# 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:
+#
+#!/usr/bin/env python
+##
+# @author Teemu Rytkonen
+
+import os
+
+import unittest
+from cone.action import configroot2flat
+from cone.public import api
+
+ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+
+
+class TestConfigRootFlat(unittest.TestCase):
+ def test_get_flat_configuration_with_empty_config(self):
+ conf = api.Configuration('foo.confml')
+ self.assertEquals(configroot2flat.get_flat_includes(conf), [])
+
+ def test_get_flat_configuration_with_single_config_hierarchy(self):
+ conf = api.Configuration('foo.confml')
+ conf.include_configuration('test1/root.confml')
+ conf.include_configuration('test2/root.confml')
+ conf.include_configuration('test3/root.confml')
+ self.assertEquals(configroot2flat.get_flat_includes(conf), ['test1/root.confml',
+ 'test2/root.confml',
+ 'test3/root.confml'])
+
+ def test_get_flat_configuration_with_two_level_config_hierarchy(self):
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp'), 'w'))
+ rootconf1 = prj.create_configuration('product1_root.confml', True)
+ rootconf2 = prj.create_configuration('product2_root.confml', True)
+ prj.create_configuration('test/one/root.confml', True)
+ fooconf = prj.create_configuration('test/foo.confml', True)
+ rootconf1.create_configuration('layer1/root.confml')
+ rootconf1.create_configuration('layer2/root.confml')
+ rootconf1.create_configuration('layer3/root.confml')
+ fooconf.include_configuration('/product1_root.confml')
+ fooconf.include_configuration('/product2_root.confml')
+ fooconf.include_configuration('/test/one/root.confml')
+ rootconf1.create_configuration('layer5/root.confml')
+ rootconf1.create_configuration('layer6/root.confml')
+ prj.save()
+ self.assertEquals(configroot2flat.get_flat_includes(fooconf), ['layer1/root.confml',
+ 'layer2/root.confml',
+ 'layer3/root.confml',
+ 'layer5/root.confml',
+ 'layer6/root.confml',
+ 'test/one/root.confml'])
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/tests/unittest_fix.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/tests/unittest_fix.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,34 @@
+#
+# 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:
+#
+
+"""
+Test the configuration
+"""
+import unittest
+import os
+from cone.action import fix
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class TestConeFixAction(unittest.TestCase):
+
+ def test_create_fix_action(self):
+ fixer = fix.ConeFixAction()
+ self.assertEquals(fixer.include_filter,[])
+ self.assertEquals(fixer.exclude_filter,[])
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/action/tests/unittest_loader.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/action/tests/unittest_loader.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,32 @@
+#
+# 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:
+#
+
+"""
+Test the configuration
+"""
+import unittest
+from cone.action import loader
+
+
+class TestGetAction(unittest.TestCase):
+
+ def test_create_fix_action(self):
+
+ self.assertTrue(loader.get_module('fix'))
+ self.assertTrue(loader.get_class('fix'))
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/model.py
--- a/configurationengine/source/cone/carbon/model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/model.py Tue Aug 10 14:29:28 2010 +0300
@@ -27,6 +27,7 @@
"""
from cone.public import api, exceptions, container, utils
from cone.confml import model as confmlmodel
+from cone.carbon import resourcemapper
class ResourceList(object):
def __init__(self):
@@ -120,10 +121,10 @@
super(CarbonConfiguration, self).__init__(ref, **kwargs)
if self.meta == None:
self.meta = {}
-
- self.name = kwargs.get('name') or utils.resourceref.remove_ext(utils.resourceref.psplit_ref(self.path)[-1])
- self.meta.add('type',kwargs.get('type', 'configurationroot'))
- self._version_identifier = kwargs.get('version_identifier', None)
+ self.name = kwargs.get('name') or utils.resourceref.remove_ext(utils.resourceref.psplit_ref(self.path)[-1])
+ if self.type == None:
+ self.type = 'configurationroot'
+ self._version_identifier = kwargs.get('version_identifier', None)
@property
def version_identifier(self):
@@ -132,21 +133,54 @@
self._version_identifier = "%dwk%02d" % dt.isocalendar()[0:2]
return self._version_identifier
- @property
- def type(self):
+ def get_type(self):
if self.meta and self.meta.get('type'):
- return self.meta['type']
+ return self.meta.get_property_by_tag('type').value
else:
return 'configurationroot'
+
+ def set_type(self, type):
+ if not self.meta:
+ self.meta = {}
+ self.meta.set_property_by_tag('type',type)
+
+ def del_type(self):
+ del self.meta['type']
+ type = property(get_type, set_type, del_type)
+
+ def get_version_identifier(self):
+ if self._version_identifier == None:
+ dt = datetime.datetime.today()
+ self._version_identifier = "%dwk%02d" % dt.isocalendar()[0:2]
+ return self._version_identifier
+
+ def set_version_identifier(self, value):
+ self._version_identifier = value
+
+ def del_version_identifier(self):
+ del self._version_identifier
+
+ version_identifier = property(get_version_identifier, set_version_identifier, del_version_identifier)
+
class FeatureList(CarbonConfiguration):
def __init__(self, ref='', **kwargs):
if not kwargs.get('path'):
- kwargs['path'] = str(kwargs.get('name', '')+'.confml')
- kwargs['type'] = 'featurelist'
+ if kwargs.get('name'):
+ kwargs['path'] = str(kwargs.get('name', '')+'.confml')
+ else:
+ kwargs['path'] = ref
+
+ pathmapper = resourcemapper.CarbonResourceMapper()
+ tpath = pathmapper.map_confml_resource("featurelist",kwargs['path'])
+ kwargs['path'] = pathmapper.map_carbon_resource(tpath)
+
super(FeatureList, self).__init__(ref, **kwargs)
- self.name = kwargs.get('name', '')
- self._version_identifier = kwargs.get('version_identifier', 'WORKING')
+ self._version_identifier = kwargs.get('version_identifier', 'working')
+ self.type = 'featurelist'
+
+ def _default_object(self, name):
+ return CarbonFeature(name)
class CarbonFeature(CarbonElement, confmlmodel.ConfmlSetting):
def __init__(self, ref,**kwargs):
@@ -155,16 +189,24 @@
class CarbonSetting(CarbonFeature, confmlmodel.ConfmlSetting):
- pass
+ def __init__(self, ref,**kwargs):
+ super(CarbonSetting,self).__init__(ref,**kwargs)
+ self.type = 'boolean'
class CarbonIntSetting(CarbonFeature, confmlmodel.ConfmlIntSetting):
- pass
+ def __init__(self, ref,**kwargs):
+ super(CarbonIntSetting,self).__init__(ref,**kwargs)
+ self.type = 'int'
class CarbonBooleanSetting(CarbonFeature, confmlmodel.ConfmlBooleanSetting):
- pass
+ def __init__(self, ref,**kwargs):
+ super(CarbonBooleanSetting,self).__init__(ref,**kwargs)
+ self.type = 'boolean'
class CarbonSelectionSetting(CarbonFeature, confmlmodel.ConfmlSelectionSetting):
- pass
+ def __init__(self, ref,**kwargs):
+ super(CarbonSelectionSetting,self).__init__(ref,**kwargs)
+ self.type = 'selection'
class CarbonStringSetting(CarbonFeature, confmlmodel.ConfmlSetting):
def __init__(self, ref,**kwargs):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/persistentjson.py
--- a/configurationengine/source/cone/carbon/persistentjson.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/persistentjson.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
""" cone specific imports """
from cone.public import persistence, exceptions, api, utils, container
from cone.carbon import model
+from cone.carbon.resourcemapper import CarbonResourceMapper
MODEL = model
@@ -37,50 +38,6 @@
return CarbonReader().loads(jsonstr)
-class CarbonResourceMapper(object):
- def __init__(self):
- self.CARBON_RESOURCE_TYPE_MAP = {'configurationroot' : self.map_carbon_configurationroot,
- 'configurationlayer' : self.map_carbon_configurationlayer,
- 'featurelist' : self.map_carbon_featurelist}
- self.CONFML_RESOURCE_TYPE_MAP = {'configurationroot' : self.map_confml_configurationroot,
- 'configurationlayer' : self.map_confml_configurationlayer,
- 'featurelist' : self.map_confml_featurelist}
-
- def map_carbon_resource(self, resourcepath):
- for resourceext in self.CARBON_RESOURCE_TYPE_MAP:
- if resourcepath.endswith(resourceext):
- return self.CARBON_RESOURCE_TYPE_MAP[resourceext](resourcepath)
- return resourcepath
-
- def map_confml_resource(self, resourcetype, resourcepath):
- return self.CONFML_RESOURCE_TYPE_MAP[resourcetype](resourcepath)
-
- def map_carbon_configurationroot(self, resourcepath):
- return resourcepath.replace('.configurationroot', '.confml')
-
- def map_carbon_configurationlayer(self, resourcepath):
- return resourcepath.replace('.configurationlayer', '/root.confml')
-
- def map_carbon_featurelist(self, resourcepath):
- return "featurelists/%s" % resourcepath.replace('.featurelist', '.confml')
-
- def map_confml_configurationroot(self, resourcepath):
- return resourcepath.replace('.confml', '.configurationroot')
-
- def map_confml_configurationlayer(self, resourcepath):
- return resourcepath.replace('/root.confml', '.configurationlayer')
-
- def map_confml_featurelist(self, resourcepath):
- path = resourcepath.replace('featurelists/','').replace('.confml', '')
- version_identifier = 'WORKING'
- m = re.match('^(.*) \((.*)\)', path)
- # if the resourcepath does not have version information
- # use default WORKING
- if m:
- path = m.group(1)
- version_identifier = m.group(2)
- return '%s (%s).featurelist' % (path, version_identifier)
-
class ResourceListReader(persistence.ConeReader):
"""
"""
@@ -230,7 +187,7 @@
@param obj: The Configuration object
"""
configuration_dict = {'version_identifier': obj.version_identifier}
-
+
datawriter = DataWriter()
data = datawriter.dumps(obj)
configuration_dict['data'] = data
@@ -295,7 +252,7 @@
@param obj: The Configuration object
"""
name = dict.get('configuration_name')
- path = name + ".confml"
+ path = name + "/root.confml"
conf = model.CarbonConfiguration(dict.get('ref'), path=path, type='configurationlayer')
conf.name = name
@@ -304,10 +261,7 @@
""" Last read the data of this configuration and add it as a configuration """
data_reader = DataReader()
datacont = data_reader.loads(dict.get('data', {}))
- proxy = api.ConfigurationProxy(datacont.path)
- conf.add_configuration(proxy)
- proxy._set_obj(datacont)
-
+ conf.add_configuration(datacont)
return conf
class FeatureListCreateWriter(CarbonWriter):
@@ -455,7 +409,7 @@
'value_type' : self.CONFML_TO_CARBON_TYPE[mobj.type],
'children' : []}
if featuredict['value_type'] != None:
- featuredict['type_object'] = 'carbon_feature_type_normal'
+ featuredict['type_object'] = 's60_feature'
if mobj.type == 'selection':
featuredict['options'] = mobj.options.keys()
@@ -504,8 +458,8 @@
fea = model.CarbonStringSetting(ref, type=value_type)
elif value_type == 'selection':
fea = model.CarbonSelectionSetting(ref, type=value_type)
- for option in dict.get('options'):
- fea.add_option(option,option)
+ for option_name in dict.get('options'):
+ fea.create_option(option_name, option_name)
elif value_type == '':
fea = model.CarbonFeature(ref, type=value_type)
else:
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/resourcemapper.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/carbon/resourcemapper.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,63 @@
+#
+# 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:
+#
+##
+# @author Teemu Rytkonen
+import re
+import logging
+
+class CarbonResourceMapper(object):
+ def __init__(self):
+ self.CARBON_RESOURCE_TYPE_MAP = {'configurationroot' : self.map_carbon_configurationroot,
+ 'configurationlayer' : self.map_carbon_configurationlayer,
+ 'featurelist' : self.map_carbon_featurelist}
+ self.CONFML_RESOURCE_TYPE_MAP = {'configurationroot' : self.map_confml_configurationroot,
+ 'configurationlayer' : self.map_confml_configurationlayer,
+ 'featurelist' : self.map_confml_featurelist}
+
+ def map_carbon_resource(self, resourcepath):
+ for resourceext in self.CARBON_RESOURCE_TYPE_MAP:
+ if resourcepath.endswith(resourceext):
+ return self.CARBON_RESOURCE_TYPE_MAP[resourceext](resourcepath)
+ return resourcepath
+
+ def map_confml_resource(self, resourcetype, resourcepath):
+ return self.CONFML_RESOURCE_TYPE_MAP[resourcetype](resourcepath)
+
+ def map_carbon_configurationroot(self, resourcepath):
+ return resourcepath.replace('.configurationroot', '.confml')
+
+ def map_carbon_configurationlayer(self, resourcepath):
+ return resourcepath.replace('.configurationlayer', '/root.confml')
+
+ def map_carbon_featurelist(self, resourcepath):
+ return "featurelists/%s" % resourcepath.replace('.featurelist', '.confml')
+
+ def map_confml_configurationroot(self, resourcepath):
+ return resourcepath.replace('.confml', '.configurationroot')
+
+ def map_confml_configurationlayer(self, resourcepath):
+ return resourcepath.replace('/root.confml', '.configurationlayer')
+
+ def map_confml_featurelist(self, resourcepath):
+ path = resourcepath.replace('featurelists/','').replace('.confml', '')
+ version_identifier = 'working'
+ m = re.match('^(.*) \((.*)\)', path)
+ # if the resourcepath does not have version information
+ # use default WORKING
+ if m:
+ path = m.group(1)
+ version_identifier = m.group(2)
+ return '%s (%s).featurelist' % (path, version_identifier)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/tests/__init__.py
--- a/configurationengine/source/cone/carbon/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,33 +14,3 @@
# Description:
#
-import unittest, os, sys
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../..'))
-if SOURCE_ROOT not in sys.path:
- sys.path.append(SOURCE_ROOT)
-
-# Find all unittest_*.py files in this folder
-import re
-__all__ = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(ROOT_PATH))
-# Strip .py endings
-__all__ = map(lambda name: name[:-3], __all__)
-
-def collect_suite():
- sys.path.insert(0, ROOT_PATH)
- try:
- suite = unittest.TestSuite()
- for test_module in __all__:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- del sys.path[0]
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/tests/runtests.py
--- a/configurationengine/source/cone/carbon/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,6 +16,6 @@
##
# @author Teemu Rytkonen
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/tests/unittest_mapping.py
--- a/configurationengine/source/cone/carbon/tests/unittest_mapping.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/tests/unittest_mapping.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import sys
import os
import shutil
-import __init__
from cone.public import api, exceptions
from cone.confml import model as confmlmodel
@@ -62,7 +61,7 @@
c1.namespace = "com.nokia"
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, confmlmodel.ConfmlConfiguration))
- self.assertEquals(c2.name, "test")
+ self.assertEquals(c2.name, "test.confml")
self.assertEquals(c2.namespace, "com.nokia")
self.assertEquals(c2.path, "test")
@@ -71,15 +70,7 @@
c1 = model.CarbonSetting("test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, confmlmodel.ConfmlSetting))
- self.assertEquals(c2.name, "test")
- self.assertEquals(c2.ref, "test")
-
- def test_map_carbon_setting_with_data(self):
- mapper = model.get_mapper('confml')
- c1 = model.CarbonSetting("test")
- c2 = mapper.map_object(c1)
- self.assertTrue(isinstance(c2, confmlmodel.ConfmlSetting))
- self.assertEquals(c2.name, "test")
+ self.assertEquals(c2.name, None)
self.assertEquals(c2.ref, "test")
def test_map_carbon_int_setting_with_data(self):
@@ -87,21 +78,21 @@
c1 = model.CarbonIntSetting("test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, confmlmodel.ConfmlIntSetting))
- self.assertEquals(c2.name, "test")
+ self.assertEquals(c2.name, None)
self.assertEquals(c2.ref, "test")
- def test_map_carbon_setting_with_data(self):
+ def test_map_carbon_boolean_setting_with_data(self):
mapper = model.get_mapper('confml')
c1 = model.CarbonBooleanSetting("test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, confmlmodel.ConfmlBooleanSetting))
- self.assertEquals(c2.name, "test")
+ self.assertEquals(c2.name, None)
self.assertEquals(c2.ref, "test")
- def test_map_carbon_setting_with_data(self):
+ def test_map_carbon_selection_setting_with_data(self):
mapper = model.get_mapper('confml')
c1 = model.CarbonSelectionSetting("test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, confmlmodel.ConfmlSelectionSetting))
- self.assertEquals(c2.name, "test")
+ self.assertEquals(c2.name, None)
self.assertEquals(c2.ref, "test")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/tests/unittest_model.py
--- a/configurationengine/source/cone/carbon/tests/unittest_model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/carbon/tests/unittest_model.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import sys
import os
import shutil
-import __init__
import datetime
from cone.public import api, exceptions
@@ -80,11 +79,12 @@
class TestCarbonConfiguration(unittest.TestCase):
def test_create_carbon_configuration(self):
- config = model.CarbonConfiguration(path='foo/bar/test.confml', version_identifier='testing')
+ config = model.CarbonConfiguration(path='foo/bar/test.confml', version_identifier='testing', type="confroot")
self.assertEquals(config.version_identifier,'testing')
self.assertEquals(config.path,'foo/bar/test.confml')
self.assertEquals(config.ref,'foo__bar__test_confml')
self.assertEquals(config.name,'test')
+ self.assertEquals(config.type,'confroot')
config = model.CarbonConfiguration(ref='foo/bar/test.confml')
self.assertEquals(config.path,'foo/bar/test.confml')
@@ -125,19 +125,28 @@
self.assertTrue(c)
self.assertEquals(c.name, 'test')
self.assertEquals(c.meta.get('type'), 'featurelist')
- self.assertEquals(c.path, 'test.confml')
+ self.assertEquals(c.path, 'featurelists/test (working).confml')
+ self.assertEquals(c.get_ref(), 'featurelists__test_working__confml')
+
+ def test_create_with_ref(self):
+ c = model.FeatureList('test_foo.confml')
+ self.assertTrue(c)
+ self.assertEquals(c.name, 'test_foo (working)')
+ self.assertEquals(c.meta.get('type'), 'featurelist')
+ self.assertEquals(c.path, 'featurelists/test_foo (working).confml')
+ self.assertEquals(c.get_ref(), 'featurelists__test_foo_working__confml')
def test_create_with_path(self):
c = model.FeatureList(path='featurelists/test.confml')
self.assertTrue(c)
- self.assertEquals(c.name, '')
+ self.assertEquals(c.name, 'test (working)')
self.assertEquals(c.meta.get('type'), 'featurelist')
- self.assertEquals(c.path, 'featurelists/test.confml')
- self.assertEquals(c.version_identifier, 'WORKING')
+ self.assertEquals(c.path, 'featurelists/test (working).confml')
+ self.assertEquals(c.version_identifier, 'working')
class TestFeature(unittest.TestCase):
def test_create(self):
- c = model.CarbonFeature(ref='test')
+ c = model.CarbonFeature(ref='test', name="test1")
self.assertTrue(c)
- self.assertEquals(c.name, 'test')
+ self.assertEquals(c.name, 'test1')
self.assertEquals(c.ref, 'test')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/carbon/tests/unittest_resourcemapper.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/carbon/tests/unittest_resourcemapper.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,40 @@
+#
+# 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:
+#
+
+
+import unittest
+import string
+import sys
+import os
+import shutil
+import datetime
+
+from cone.public import api, exceptions
+from cone.carbon import resourcemapper, model
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class TestCarbonResourceMapper(unittest.TestCase):
+ def test_map_confmL_configuration_to_carbon_path(self):
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_confml_resource("configurationroot","test.confml"),"test.configurationroot")
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_confml_resource("configurationlayer","test/root.confml"),"test.configurationlayer")
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_confml_resource("featurelist","featurelists/test (WORKING).confml"),"test (WORKING).featurelist")
+
+ def test_map_carbon_configuration_to_confml_path(self):
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_carbon_resource("test.configurationroot"),"test.confml")
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_carbon_resource("foobar_test_one.configurationroot"),"foobar_test_one.confml")
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_carbon_resource("foobar (WORKING).featurelist"),"featurelists/foobar (WORKING).confml")
+ self.assertEquals(resourcemapper.CarbonResourceMapper().map_carbon_resource("foobar.featurelist"),"featurelists/foobar.confml")
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/model.py
--- a/configurationengine/source/cone/confml/model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/model.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,9 +21,15 @@
All Confml element attributes become attributes of this instance.
"""
import types
+import sys
+import re
from cone.public import api, exceptions, container, utils
class ConfmlElement(api.Base):
+ def __init__(self, ref="", **kwargs):
+ super(ConfmlElement,self).__init__(ref, **kwargs)
+ self.lineno = None
+
def _get_mapper(self,modelname):
"""
Return a instance of appropriate mapper for given model.
@@ -48,6 +54,18 @@
pass
""" The description as a property """
desc = property(get_desc,set_desc,del_desc)
+
+class ConfmlData(api.Data):
+ """
+ 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):
+ super(ConfmlData,self).__init__(**kwargs)
+ self.lineno = None
+
class ConfmlConfiguration(ConfmlElement, api.Configuration):
"""
Confml configuration class.
@@ -59,6 +77,14 @@
if kwargs.get('desc'):
self.desc = kwargs.get('desc')
+ def _view_class(self):
+ return ConfmlView
+
+ def _feature_class(self):
+ return ConfmlFeature
+
+ def _configuration_class(self):
+ return ConfmlConfiguration
def get_desc(self):
"""
@@ -84,7 +110,7 @@
def get_meta(self):
"""
- @return: The description of the Configuration.
+ @return: The meta element of the Configuration.
"""
try:
meta = getattr(self,ConfmlMeta.refname)
@@ -104,88 +130,13 @@
""" The meta element as a property """
meta = property(get_meta,set_meta,del_meta)
-
-class ConfmlGroup(ConfmlElement, api.Group):
- """
- Confml view.
+class ConfmlSettingAttributes(ConfmlElement):
"""
- def __init__(self, ref="", **kwargs):
- super(ConfmlGroup,self).__init__(ref,**kwargs)
- if kwargs.get('icon'):
- self.icon = kwargs.get('icon')
- if kwargs.get('desc'):
- self.desc = kwargs.get('desc')
-
- def get_icon(self):
- try:
- icon = getattr(self,ConfmlIcon.refname)
- return icon.href
- except AttributeError:
- return None
- def set_icon(self,value): self._add(ConfmlIcon(value))
- def del_icon(self):
- try:
- self._remove(ConfmlIcon.refname)
- except exceptions.NotFound:
- pass
- """ The icon as a property """
- icon = property(get_icon,set_icon,del_icon)
-
- def get_desc(self):
- try:
- desc = getattr(self,ConfmlDescription.refname)
- return desc.text
- except AttributeError:
- return None
- def set_desc(self,value): self._add(ConfmlDescription(value))
- def del_desc(self):
- try:
- self._remove(ConfmlDescription.refname)
- except exceptions.NotFound:
- pass
- """ The description as a property """
- desc = property(get_desc,set_desc,del_desc)
-
-
-class ConfmlView(api.View):
+ Abstract base class for setting attributes. This is used as
+ a base in actual ConfmlSetting and ConfmlFeatureLink.
"""
- Confml view.
- """
- def __init__(self, ref="", **kwargs):
- super(ConfmlView,self).__init__(ref,**kwargs)
- if kwargs.get('desc'):
- self.desc = kwargs.get('desc')
-
-
- def get_desc(self):
- try:
- desc = getattr(self,ConfmlDescription.refname)
- return desc.text
- except AttributeError:
- return None
- def set_desc(self,value): self._add(ConfmlDescription(value))
- def del_desc(self):
- try:
- self._remove(ConfmlDescription.refname)
- except exceptions.NotFound:
- pass
- """ The description as a property """
- desc = property(get_desc,set_desc,del_desc)
-
-class ConfmlFeature(ConfmlElement, api.Feature):
- pass
-
-class ConfmlSetting(ConfmlElement, api.Feature):
- """
- Confml setting class. Attribute 'options' contains options of this setting.
- """
- supported_types = ['int',
- 'string',
- 'boolean',
- 'selection']
def __init__(self, ref,**kwargs):
- super(ConfmlSetting,self).__init__(ref,**kwargs)
- self.type = kwargs.get('type',None)
+ super(ConfmlSettingAttributes,self).__init__(ref,**kwargs)
if kwargs.get('desc'):
self.desc = kwargs.get('desc')
if kwargs.get('minOccurs'):
@@ -196,10 +147,10 @@
self.maxLength = kwargs.get('maxLength')
if kwargs.get('minLength'):
self.minLength = kwargs.get('minLength')
- if kwargs.get('mapKey'):
- self.mapKey = kwargs.get('mapKey')
- if kwargs.get('mapValue'):
- self.mapValue = kwargs.get('mapValue')
+ self.mapKey = kwargs.get('mapKey')
+ self.mapValue = kwargs.get('mapValue')
+ self.displayName = kwargs.get('displayName')
+
self.readOnly = kwargs.get('readOnly',None)
self.constraint = kwargs.get('constraint',None)
@@ -212,39 +163,6 @@
"""
return api.ValueRe('.*')
- def add_property(self, **kwargs):
- """
- @param name=str: property name
- @param value=str: property value
- @param unit=str: property unit, e.g. kB
- """
- self._add(ConfmlProperty(**kwargs), container.APPEND)
-
- def get_property(self, name):
- """
- @param name: The name of the property
- """
- for property in utils.get_list(self._get(ConfmlProperty.refname)):
- if property.name == name:
- return property
- raise exceptions.NotFound("ConfmlProperty with name %s not found!" % name)
-
- def remove_property(self, name):
- """
- remove a given option from this feature by name.
- @param name:
- """
- for property in self._get(ConfmlProperty.refname):
- if property.name == name:
- return self._remove(property.get_fullref())
- raise exceptions.NotFound("ConfmlProperty with name %s not found!" % name)
-
- def list_properties(self):
- """
- Return a array of all Feature children references under this object.
- """
- return [obj.name for obj in utils.get_list(self._get(ConfmlProperty.refname))]
-
def get_maxlength(self):
try:
return getattr(self,ConfmlMaxLength.refname).value
@@ -259,7 +177,7 @@
self._remove(ConfmlMaxLength.refname)
except exceptions.NotFound:
pass
- """ The description as a property """
+ """ The maxLength as a property """
maxLength = property(get_maxlength,set_maxlength,del_maxlength)
def get_minlength(self):
@@ -276,8 +194,25 @@
self._remove(ConfmlMinLength.refname)
except exceptions.NotFound:
pass
- """ The description as a property """
+ """ The minLength as a property """
minLength = property(get_minlength,set_minlength,del_minlength)
+
+ def get_length(self):
+ try:
+ return getattr(self,ConfmlLength.refname).value
+ except AttributeError:
+ return None
+
+ def set_length(self,value):
+ self._add(ConfmlLength(value))
+
+ def del_length(self):
+ try:
+ self._remove(ConfmlLength.refname)
+ except exceptions.NotFound:
+ pass
+ """ The length as a property """
+ length = property(get_length,set_length,del_length)
def get_minInclusive(self):
try:
@@ -390,22 +325,112 @@
@property
def properties(self):
- dict = {}
- for property in utils.get_list(self._get(ConfmlProperty.refname)):
- dict[property.name] = property
- return dict
+ propdict = {}
+ for prop in self._objects(type=api.Property):
+ propdict[prop.name] = prop
+ return propdict
- def get_rfs(self,):
- return super(ConfmlSetting,self).get_value('rfs')
+ def get_rfs(self):
+ return super(ConfmlSettingAttributes,self).get_value('rfs')
def set_rfs(self, value):
- super(ConfmlSetting,self).set_value('rfs',value)
+ super(ConfmlSettingAttributes,self).set_value('rfs',value)
def del_rfs(self):
- super(ConfmlSetting,self).del_value('rfs')
+ super(ConfmlSettingAttributes,self).del_value('rfs')
rfs = property(get_rfs,set_rfs,del_rfs)
+
+class ConfmlGroup(ConfmlElement, api.Group):
+ """
+ Confml view.
+ """
+ def __init__(self, ref="", **kwargs):
+ super(ConfmlGroup,self).__init__(ref,**kwargs)
+ if kwargs.get('icon'):
+ self.icon = kwargs.get('icon')
+ if kwargs.get('desc'):
+ self.desc = kwargs.get('desc')
+
+ def _group_class(self):
+ return ConfmlGroup
+
+ def _featurelink_class(self):
+ return ConfmlFeatureLink
+
+ def get_icon(self):
+ try:
+ icon = getattr(self,ConfmlIcon.refname)
+ return icon.href
+ except AttributeError:
+ return None
+ def set_icon(self,value): self._add(ConfmlIcon(value))
+ def del_icon(self):
+ try:
+ self._remove(ConfmlIcon.refname)
+ except exceptions.NotFound:
+ pass
+ """ The icon as a property """
+ icon = property(get_icon,set_icon,del_icon)
+
+ def get_desc(self):
+ try:
+ desc = getattr(self,ConfmlDescription.refname)
+ return desc.text
+ except AttributeError:
+ return None
+ def set_desc(self,value): self._add(ConfmlDescription(value))
+ def del_desc(self):
+ try:
+ self._remove(ConfmlDescription.refname)
+ except exceptions.NotFound:
+ pass
+ """ The description as a property """
+ desc = property(get_desc,set_desc,del_desc)
+
+
+class ConfmlView(api.View, ConfmlGroup):
+ """
+ Confml view.
+ """
+ def __init__(self, ref="", **kwargs):
+ super(ConfmlView,self).__init__(ref,**kwargs)
+ if kwargs.get('desc'):
+ self.desc = kwargs.get('desc')
+
+ def get_desc(self):
+ try:
+ desc = getattr(self,ConfmlDescription.refname)
+ return desc.text
+ except AttributeError:
+ return None
+ def set_desc(self,value): self._add(ConfmlDescription(value))
+ def del_desc(self):
+ try:
+ self._remove(ConfmlDescription.refname)
+ except exceptions.NotFound:
+ pass
+ """ The description as a property """
+ desc = property(get_desc,set_desc,del_desc)
+
+
+class ConfmlFeature(ConfmlElement, api.Feature):
+ def _feature_class(self):
+ return ConfmlSetting
+
+class ConfmlSetting(ConfmlSettingAttributes, api.Feature):
+ """
+ Confml setting class. Attribute 'options' contains options of this setting.
+ """
+ supported_types = ['int',
+ 'string',
+ 'boolean',
+ 'selection']
+ def __init__(self, ref,**kwargs):
+ super(ConfmlSetting,self).__init__(ref,**kwargs)
+ self.type = kwargs.get('type',None)
+
def get_value_cast(self, value, attr=None):
"""
A function to perform the value type casting in get operation
@@ -425,13 +450,17 @@
@param value: the value to cast
@param attr: the attribute which is fetched from model (normally in confml either None='data' or 'rfs')
"""
+ # Add a exception case for None value, because the data casting will always fail for it
+ if value == None:
+ return value
+
if not attr or attr == 'data':
return self.set_data_cast(value)
elif attr == 'rfs':
return self.set_rfs_cast(value)
else:
return value
-
+
def get_data_cast(self, value):
"""
A function to perform the data type casting in get operation
@@ -600,48 +629,78 @@
"""
Confml setting class for multiSelection type.
"""
-
+
+ # Pattern for checking whether a data value should be interpreted
+ # in the old style (e.g. '"opt1" "opt2" "opt3"')
+ OLD_STYLE_DATA_PATTERN = re.compile(r'"[^"]*([^"]*" ")*[^"]*"')
+
def __init__(self, ref,**kwargs):
kwargs['type'] = 'multiSelection'
ConfmlSetting.__init__(self,ref,**kwargs)
-
+ def add_data(self, data):
+ """
+ Add a data value.
+ @param data: A Data object
+ """
+ # If there are existing data objects added to the proxy, and they
+ # are not in the same DataContainer (ConfML data section), change the
+ # policy to replace
+ if self.dataproxy.datas.get(data.attr):
+ existing_data_obj = self.dataproxy.datas[data.attr][-1]
+ existing_obj_parent = existing_data_obj._find_parent_or_default(type=api.DataContainer)
+ new_obj_parent = data._find_parent_or_default(type=api.DataContainer)
+
+ if existing_obj_parent is not new_obj_parent:
+ self.dataproxy.datas[data.attr] = []
+
+ self.dataproxy._add_data(data)
+
def get_valueset(self):
"""
Get the ValueSet object for this feature, that has the list of available values.
"""
return api.Feature.get_valueset(self)
-
- def get_data_cast(self, value):
- """
- A function to perform the value type casting in get operation
- """
- try:
- if not isinstance(value, types.ListType):
- values = value.split('" "')
- for i in range(len(values)):
- if values[i].startswith('"'):
- values[i] = values[i][1:]
- if values[i].endswith('"'):
- values[i] = values[i][:-1]
- return values
- return value
- except AttributeError:
- return None
- def set_data_cast(self, value):
- """
- A function to perform the value type casting in the set operation
- """
+ def convert_data_to_value(self, data_objects, cast=True, attr=None):
+ if len(data_objects) == 1:
+ d = data_objects[0]
+
+ # Special handling for cases where the data is in the old format
+ # (pre-2.88 ConfML spec)
+ if d.value is not None:
+ if self.OLD_STYLE_DATA_PATTERN.match(d.value):
+ return tuple([v.rstrip('"').lstrip('"') for v in d.value.split('" "')])
+
+ # Single data object with empty="true" means that nothing is selected
+ if d.empty: return ()
- if isinstance(value, list):
- value = " ".join(['"%s"' % elem for elem in value])
- return value
+ # Read each data value (or name-ID mapped value) into result
+ result = []
+ for data_obj in data_objects:
+ if data_obj.map:
+ value = self._resolve_name_id_mapped_value(data_obj.map, cast_value=cast)
+ else:
+ value = data_obj.value
+ result.append(value)
+ result = utils.distinct_array(result)
+
+ # Handle None in the result (data element with no text data)
+ if None in result:
+ # If the empty string is a valid option, change the None to that,
+ # otherwise ignore
+ index = result.index(None)
+ if '' in self.get_valueset(): result[index] = ''
+ else: del result[index]
+
+ return tuple(result)
- def set_value(self, value):
- if not isinstance(value, types.ListType):
- raise ValueError("Only list types are allowed.")
- self.value = value
+ def convert_value_to_data(self, value, attr=None):
+ if not isinstance(value, (types.ListType, types.TupleType, types.NoneType)):
+ raise ValueError("Only list, tuple and None types are allowed.")
+
+ if value: return [api.Data(fqr=self.fqr, value=v, attr=attr) for v in value]
+ else: return [api.Data(fqr=self.fqr, empty=True, attr=attr)]
class ConfmlDateSetting(ConfmlSetting):
"""
@@ -667,6 +726,32 @@
kwargs['type'] = 'dateTime'
ConfmlSetting.__init__(self,ref,**kwargs)
+class ConfmlHexBinarySetting(ConfmlSetting):
+ """
+ Confml setting class for hex-binary type.
+ """
+ def __init__(self, ref,**kwargs):
+ kwargs['type'] = 'hexBinary'
+ ConfmlSetting.__init__(self,ref,**kwargs)
+
+ def get_valueset(self):
+ return api.ValueRe(r'^([0123456789ABCDEF]{2})*$')
+
+ def get_data_cast(self, value):
+ value = value or '' # Handle None
+ if value not in self.get_valueset():
+ raise ValueError("Cannot convert value %r of setting '%s' into binary data: Not a valid hex string", value)
+
+ temp = []
+ for i in xrange(len(value) / 2):
+ start = i * 2
+ end = start + 2
+ temp.append(chr(int(value[start:end], 16)))
+ return ''.join(temp)
+
+ def set_data_cast(self, value):
+ return ''.join(['%02X' % ord(c) for c in value])
+
class ConfmlDurationSetting(ConfmlSetting):
"""
Confml setting class for date type.
@@ -711,10 +796,12 @@
class ConfmlLocalPath(ConfmlElement, api.Feature):
"""
- Confml file class. Attribute setting.
+ Confml file class. Attribute setting.
+ The localPath "name" is always the same as its ref 'localPath'
"""
def __init__(self, ref='localPath', **kwargs):
kwargs['type'] = 'string'
+ kwargs['name'] = ref
ConfmlElement.__init__(self, **kwargs)
api.Feature.__init__(self, ref, **kwargs)
self.readOnly = kwargs.get('readOnly', None)
@@ -723,14 +810,45 @@
class ConfmlTargetPath(ConfmlElement, api.Feature):
"""
Confml file class. Attribute setting.
+ The targetPath "name" is always the same as its ref 'targetPath'
"""
def __init__(self, ref='targetPath', **kwargs):
kwargs['type'] = 'string'
+ kwargs['name'] = ref
ConfmlElement.__init__(self, **kwargs)
api.Feature.__init__(self, ref, **kwargs)
self.readOnly = kwargs.get('readOnly', None)
+class ConfmlFeatureLink(ConfmlSettingAttributes, api.FeatureLink):
+ """
+ ConfmlFeatureLink object is the setting reference object inside confml
+ group / view. It can populate the actual FeatureProxy objects under the
+ particular group / view object.
+ """
+
+ """ the override_attributes explicitly states which feature link attributes can be overridden """
+ override_attributes = ['name',
+ 'desc',
+ 'minLength',
+ 'maxLength',
+ 'minOccurs',
+ 'maxOccurs',
+ 'minInclusive',
+ 'maxInclusive',
+ 'minExclusive',
+ 'maxExclusive',
+ 'pattern',
+ 'totalDigits',
+ 'options',
+ 'properties',
+ 'readOnly'
+ ]
+ def __init__(self, ref,**kwargs):
+ ConfmlSettingAttributes.__init__(self, ref,**kwargs)
+ api.FeatureLink.__init__(self, ref, **kwargs)
+ self.type = kwargs.get('type',None)
+
class ConfmlMeta(api.Base):
"""
Confml meta element
@@ -751,6 +869,9 @@
def __setitem__(self, key, value):
self.array[key] = value
+ def __len__(self):
+ return len(self.array)
+
def __str__(self):
tempstr = "ConfmlMeta object\n"
counter = 0
@@ -790,6 +911,16 @@
def replace(self, index, tag, value, ns=None, dict=None):
self.array[index] = ConfmlMetaProperty(tag, value, ns, attrs=dict)
+ def update(self, data):
+ """
+ Update this the ConfmlMeta object meta with the given data.
+ @param data: The input ConfmlMeta data to update for this object
+ """
+ if data:
+ for property in data.array:
+ self.set_property_by_tag(property.tag, property.value, property.ns, property.attrs)
+
+
def clear(self, value):
self.array = []
@@ -807,22 +938,38 @@
return -1
def find_by_attribute(self, name, value):
- for item in self.array:
- if item.attrs.has_key(name) and item.attrs[name] == value:
+ for item in self.array:
+ if item.attrs.has_key(name) and item.attrs[name] == value:
return self.array.index(item)
return -1
- def get_property_by_tag(self, tag):
+ def get_property_by_tag(self, tag, attrs={}):
"""
Try to find the element by its tag in the meta elem array.
@param tag: the tag that is searched
@return: the ConfmlMetaProperty object if it is found. None if element with tag is not found.
- """
+ """
for item in self.array:
if item.tag == tag:
- return item
+ if not item.attrs or (item.attrs.get("name", None) == attrs.get("name", None)):
+ return item
return None
+ def set_property_by_tag(self, tag, value, ns=None, attributes=None):
+ """
+ Try to find the element by its tag and set it the meta elem array.
+ This will either create a new element to the meta or replace first
+ encountered elem in array.
+ @param tag: the tag that is searched
+ @return: the ConfmlMetaProperty object if it is found. None if element with tag is not found.
+ """
+
+ if self.get_property_by_tag(tag, attributes):
+ property = self.get_property_by_tag(tag, attributes)
+ property.value = value
+ property.attrs = attributes or {}
+ else:
+ self.add(tag, value, ns, attributes)
class ConfmlDescription(api.Base):
"""
@@ -844,21 +991,6 @@
self.href = href
-class ConfmlProperty(api.Base):
- """
- Confml meta element
- """
- refname = "_property"
- def __init__(self, **kwargs):
- """
- @param name=str: name string
- @param value=str: value for the property, string
- @param unit=str: unit of the property
- """
- super(ConfmlProperty,self).__init__(self.refname)
- self.name = kwargs.get('name',None)
- self.value = kwargs.get('value',None)
- self.unit = kwargs.get('unit',None)
class ConfmlMetaProperty(api.Base):
@@ -873,10 +1005,7 @@
self.tag = tag
self.value = value
self.ns = ns
- if kwargs.has_key("attrs") and kwargs["attrs"] != None:
- self.attrs = dict(kwargs["attrs"])
- else:
- self.attrs = {}
+ self.attrs = dict(kwargs.get('attrs') or {})
def __cmp__(self, other):
try:
@@ -890,9 +1019,28 @@
def __str__(self):
return "Tag: %s Value: %s Namespace: %s Attributes: % s" % (self.tag, self.value, self.ns, repr(self.attrs))
-
-class ConfmlLength(api.Base):
+class ConfmlNumericValue(api.Base):
+ """
+ Confml base class for all float type properties.
+ Performs a simple value casting from string to int in value setting.
+ """
+ def __init__(self, ref="", **kwargs):
+ super(ConfmlNumericValue,self).__init__(ref, **kwargs)
+ self._value = None
+
+ def get_value(self): return self._value
+ def del_value(self): self._value = None
+ def set_value(self, value):
+ if utils.is_float(value):
+ self._value = float(value)
+ else:
+ self._value = int(value)
+ """ The value as a property """
+ value = property(get_value,set_value,del_value)
+
+
+class ConfmlLength(ConfmlNumericValue):
"""
Confml length element
"""
@@ -901,7 +1049,7 @@
super(ConfmlLength,self).__init__(self.refname)
self.value = value
-class ConfmlMaxLength(api.Base):
+class ConfmlMaxLength(ConfmlNumericValue):
"""
Confml max element
"""
@@ -910,7 +1058,7 @@
super(ConfmlMaxLength,self).__init__(self.refname)
self.value = value
-class ConfmlMinLength(api.Base):
+class ConfmlMinLength(ConfmlNumericValue):
"""
Confml min element
"""
@@ -919,7 +1067,7 @@
super(ConfmlMinLength,self).__init__(self.refname)
self.value = value
-class ConfmlMinInclusive(api.Base):
+class ConfmlMinInclusive(ConfmlNumericValue):
"""
Confml minInclusive element
"""
@@ -928,7 +1076,7 @@
super(ConfmlMinInclusive,self).__init__(self.refname)
self.value = value
-class ConfmlMaxInclusive(api.Base):
+class ConfmlMaxInclusive(ConfmlNumericValue):
"""
Confml minInclusive element
"""
@@ -937,7 +1085,7 @@
super(ConfmlMaxInclusive,self).__init__(self.refname)
self.value = value
-class ConfmlMinExclusive(api.Base):
+class ConfmlMinExclusive(ConfmlNumericValue):
"""
Confml minExclusive element
"""
@@ -946,7 +1094,7 @@
super(ConfmlMinExclusive,self).__init__(self.refname)
self.value = value
-class ConfmlMaxExclusive(api.Base):
+class ConfmlMaxExclusive(ConfmlNumericValue):
"""
Confml maxExclusive element
"""
@@ -964,7 +1112,7 @@
super(ConfmlPattern,self).__init__(self.refname)
self.value = value
-class ConfmlTotalDigits(api.Base):
+class ConfmlTotalDigits(ConfmlNumericValue):
"""
Confml totalDigits element
"""
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/persistentconfml.py
--- a/configurationengine/source/cone/confml/persistentconfml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/persistentconfml.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,9 +13,9 @@
#
# Description:
#
+import os
import re
import logging
-import xml.parsers.expat
try:
from cElementTree import ElementTree
except ImportError:
@@ -27,8 +27,8 @@
except ImportError:
from xml.etree import ElementTree
-""" cone specific imports """
-from cone.public import persistence, exceptions, api, utils, container
+# cone specific imports
+from cone.public import persistence, exceptions, api, utils, container, parsecontext
from cone.confml import model
CONFIGURATION_NAMESPACES = ["http://www.s60.com/xml/confml/2","http://www.s60.com/xml/confml/1"]
@@ -42,12 +42,29 @@
etree = ConfmlWriter().dumps(obj)
if indent:
persistence.indent(etree)
- return ElementTree.tostring(etree)
+ result = ElementTree.tostring(etree)
+
+ # To make the output the same in linux and windows
+ # (needed to make testing easier)
+ if os.linesep != '\r\n':
+ result = result.replace(os.linesep, '\r\n')
+
+ return result
def loads(xml):
return ConfmlReader().loads(xml)
+def add_parse_warning(msg, line, type='model.confml'):
+ parsecontext.get_confml_context().handle_problem(
+ api.Problem(msg,
+ severity = api.Problem.SEVERITY_WARNING,
+ type = type,
+ line = line))
+def add_unknown_element_warning(elem):
+ add_parse_warning("Unknown element '%s'" % elem.tag,
+ utils.etree.get_lineno(elem),
+ type='model.confml.unknown_element')
class ConfmlWriter(persistence.ConeWriter):
"""
@@ -69,7 +86,11 @@
@param xml: The xml which to read. reads only the first object.
"""
reader = get_reader_for_elem("configuration")
- etree = utils.etree.fromstring(xmlstr)
+ try:
+ etree = utils.etree.fromstring(xmlstr)
+ except exceptions.XmlParseError, e:
+ e.problem_type = 'xml.confml'
+ raise e
return reader.loads(etree)
@@ -105,7 +126,13 @@
elem.set("xmlns:xlink",self.xlink_namespace)
if self.schema_namespace:
elem.set("xmlns:xs",self.schema_namespace)
- elem.set("name",obj.get_name())
+ if obj.get_name():
+ elem.set("name", obj.get_name())
+ if obj.version != None:
+ elem.set("version", obj.version)
+ if obj.get_id():
+ elem.set('id', obj.get_id())
+
for child in obj._objects():
""" Make sure that the object is mapped to an object in this model """
mobj = child._get_mapper('confml').map_object(child)
@@ -137,8 +164,11 @@
self.schema_namespaces = SCHEMA_NAMESPACES
def loads(self, etree):
- configuration = model.ConfmlConfiguration("")
- configuration.set_name(etree.get("name") or 'unknown')
+ configuration = model.ConfmlConfiguration(name=etree.get("name"),
+ id=etree.get("id"),
+ version=etree.get("version"))
+ configuration.lineno = utils.etree.get_lineno(etree)
+ # configuration.set_name(etree.get("name") or 'unknown')
configuration.set_ref(etree.get("name") or 'unknown')
for elem in etree.getchildren():
# At the moment we ignore the namespace of elements
@@ -149,7 +179,7 @@
if obj:
configuration.add(obj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return configuration
@@ -202,6 +232,7 @@
def loads(self,etree):
metaelem = model.ConfmlMeta()
+ metaelem.lineno = utils.etree.get_lineno(etree)
for elem in etree.getchildren():
(namespace,elemname) = get_elemname(elem.tag)
attributes = {}
@@ -250,6 +281,7 @@
def loads(self,elem):
desc = model.ConfmlDescription(elem.text)
+ desc.lineno = utils.etree.get_lineno(elem)
return desc
class ConfigurationProxyWriter(ConfmlWriter):
@@ -295,8 +327,9 @@
"""
@param elem: The xml include elem
"""
-
- return api.ConfigurationProxy(self.parse_include(elem))
+ proxy = api.ConfigurationProxy(self.parse_include(elem))
+ # proxy.lineno = utils.etree.get_lineno(elem)
+ return proxy
def parse_include(self,include):
#print "Found include %s" % include.get('href').replace('#/','')
@@ -321,10 +354,17 @@
@param obj: The Configuration object
"""
elem = ElementTree.Element('feature',
- {'ref' : obj.get_ref(),
- 'name' : obj.get_name()})
+ {'ref' : obj.get_ref()})
+ if obj.get_name():
+ elem.set('name', obj.get_name())
if obj.get_type():
elem.set('type', obj.get_type())
+ if obj.get_id() != None:
+ elem.set('id', obj.get_id())
+ if obj.get_relevant() != None:
+ elem.set('relevant', obj.get_relevant())
+ if obj.get_constraint() != None:
+ elem.set('constraint', obj.get_constraint())
for child in obj._objects():
""" Make sure that the object is mapped to an object in this model """
mobj = child._get_mapper('confml').map_object(child)
@@ -360,7 +400,14 @@
feature = model.ConfmlFeature(elem.get('ref'))
if elem.get('name'):
feature.set_name(elem.get('name'))
+ if elem.get('id') != None:
+ feature.set_id(elem.get('id'))
+ if elem.get('relevant') != None:
+ feature.set_relevant(elem.get('relevant'))
+ if elem.get('constraint') != None:
+ feature.set_constraint(elem.get('constraint'))
feature.set_type(type)
+ feature.lineno = utils.etree.get_lineno(elem)
for elem in elem.getchildren():
# At the moment we ignore the namespace of elements
(namespace,elemname) = get_elemname(elem.tag)
@@ -369,7 +416,7 @@
obj = reader.loads(elem)
feature.add(obj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return feature
@@ -396,6 +443,9 @@
if obj.get_value() is not None: objdict['value'] = obj.get_value()
if obj.map is not None: objdict['map'] = obj.map
if obj.relevant is not None: objdict['relevant'] = obj.relevant
+ if obj.display_name is not None: objdict['displayName'] = obj.display_name
+ if obj.map_value is not None: objdict['mapValue'] = obj.map_value
+
elem = ElementTree.Element('option', objdict)
return elem
@@ -422,11 +472,16 @@
name = elem.get('name')
value = elem.get('value')
optmap = elem.get('map')
+
if value == None and optmap == None:
logging.getLogger('cone').warning("Encountered option with no value")
option = None
else:
- option = api.Option(name, value, map=optmap, relevant=elem.get('relevant'))
+ option = api.Option(name, value, map=optmap,
+ relevant=elem.get('relevant'),
+ map_value=elem.get('mapValue'),
+ display_name=elem.get('displayName'))
+ option.lineno = utils.etree.get_lineno(elem)
return option
@@ -471,6 +526,7 @@
"""
href = elem.get('{%s}href' % XLINK_NAMESPACES[0])
obj = model.ConfmlIcon(href)
+ obj.lineno = utils.etree.get_lineno(elem)
return obj
@@ -481,7 +537,7 @@
Class method to determine if this ConfmlWriter supports writing
of the given class name
"""
- if classname=="ConfmlProperty":
+ if classname=="Property":
return True
else:
return False
@@ -518,7 +574,8 @@
"""
@param elem: The xml include elem
"""
- option = model.ConfmlProperty(name=elem.get('name'),value=elem.get('value'), unit=elem.get('unit'))
+ option = api.Property(name=elem.get('name'),value=elem.get('value'), unit=elem.get('unit'))
+ option.lineno = utils.etree.get_lineno(elem)
return option
@@ -574,6 +631,7 @@
elem_name = utils.xml.split_tag_namespace(elem.tag)[1]
facet_class = self.MAPPING[elem_name]
obj = facet_class(elem.get('value'))
+ obj.lineno = utils.etree.get_lineno(elem)
return obj
@@ -584,9 +642,8 @@
Class method to determine if this ConfmlWriter supports writing
of the given class name
"""
- if classname=="Data":
- return True
- if classname=="DataContainer":
+ if classname=="Data" or \
+ classname=="DataContainer":
return True
else:
return False
@@ -597,14 +654,16 @@
"""
# Create a data hierarchy of the
elem = ElementTree.Element(obj.get_ref())
- if hasattr(obj,'get_value') and obj.get_value() and not obj.get_map():
+ if hasattr(obj,'get_map') and obj.get_map() is not None:
+ elem.set('map', obj.get_map())
+ elif hasattr(obj,'get_value') and obj.get_value() is not None:
elem.text = obj.get_value()
- elif hasattr(obj,'get_map') and obj.get_map():
- elem.set('map', obj.get_map())
if hasattr(obj,'template') and obj.template == True:
elem.set('template','true')
if hasattr(obj,'policy') and obj.policy != '':
elem.set('extensionPolicy',obj.policy)
+ if hasattr(obj,'empty') and obj.empty == True:
+ elem.set('empty','true')
for child in obj._objects():
writer = DataWriter()
childelem = writer.dumps(child)
@@ -634,13 +693,14 @@
(namespace,elemname) = get_elemname(elem.tag)
obj = api.DataContainer(elemname, container=True)
+ obj.lineno = utils.etree.get_lineno(elem)
for elem in elem.getchildren():
try:
reader = ElemReader(attr='data')
childobj = reader.loads(elem)
obj.add(childobj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return obj
@@ -663,8 +723,9 @@
@param obj: The Configuration object
"""
elem = ElementTree.Element('view',
- {'id' : obj.get_ref(),
- 'name' : obj.get_name()})
+ {'name' : obj.get_name()})
+ if obj.id != None:
+ elem.set('id', obj.id)
for child in obj._objects():
""" Make sure that the object is mapped to an object in this model """
mobj = child._get_mapper('confml').map_object(child)
@@ -696,6 +757,7 @@
vid = elem.get('id')
name = elem.get('name')
view = model.ConfmlView(name, id=vid)
+ view.lineno = utils.etree.get_lineno(elem)
for elem in elem.getchildren():
# At the moment we ignore the namespace of elements
(namespace,elemname) = get_elemname(elem.tag)
@@ -704,7 +766,7 @@
obj = reader.loads(elem)
view.add(obj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return view
@@ -727,6 +789,9 @@
"""
elem = ElementTree.Element('group',
{'name' : obj.get_name()})
+ if obj.get_id():
+ elem.set('id', obj.get_id())
+
for child in obj._objects():
""" Make sure that the object is mapped to an object in this model """
mobj = child._get_mapper('confml').map_object(child)
@@ -758,6 +823,9 @@
gname = elem.get('name')
gref = utils.resourceref.to_dref(gname).replace('.','_')
group = model.ConfmlGroup(gref, name=gname)
+ group.lineno = utils.etree.get_lineno(elem)
+ if elem.get('id'):
+ group.set_id(elem.get('id'))
for elem in elem.getchildren():
# At the moment we ignore the namespace of elements
(namespace,elemname) = get_elemname(elem.tag)
@@ -767,58 +835,11 @@
if obj != None:
group.add(obj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return group
-class GroupSettingWriter(ConfmlWriter):
- """
- """
- @classmethod
- def supported_class(cls, classname):
- """
- Class method to determine if this ConfmlWriter supports writing
- of the given class name
- """
- if classname=="FeatureLink":
- return True
- else:
- return False
-
- def dumps(self, obj):
- """
- @param obj: The Configuration object
- """
- ref = obj.fqr.replace('.','/')
- elem = ElementTree.Element('setting',
- {'ref' : ref})
- return elem
-
-class GroupSettingReader(ConfmlReader):
- """
- """
- @classmethod
- def supported_elem(cls, elemname, parent=None):
- """
- Class method to determine if this ConfmlWriter supports reading
- of the given elem name
- """
- if elemname=='setting' and parent=='group':
- return True
- else:
- return False
-
- def loads(self, elem):
- """
- @param elem: The xml include elem
- """
- ref = elem.get('ref') or ''
- ref = ref.replace('/','.')
- return api.FeatureLink(ref)
-
-
-
class ConfmlSettingWriter(ConfmlWriter):
@classmethod
def supported_class(cls, classname):
@@ -837,6 +858,7 @@
classname=="ConfmlTimeSetting" or \
classname=="ConfmlDateTimeSetting" or \
classname=="ConfmlDurationSetting" or \
+ classname=="ConfmlHexBinarySetting" or \
classname=="ConfmlFileSetting" or \
classname=="ConfmlFolderSetting" or \
classname=="FeatureSequence" or \
@@ -850,10 +872,20 @@
@param obj: The Configuration object
"""
elem = ElementTree.Element('setting',
- {'ref' : obj.get_ref(),
- 'name' : obj.get_name()})
+ {'ref' : obj.get_ref()})
+ self._set_setting_properties(elem, obj)
+ return elem
+
+ def _set_setting_properties(self, elem, obj):
+ """
+ Set the setting properties for the given elm from the given feature object
+ """
+ if obj.get_name():
+ elem.set('name', obj.get_name())
if obj.type:
elem.set('type', obj.get_type())
+ if obj.get_id():
+ elem.set('id', obj.get_id())
if hasattr(obj,'minOccurs'):
elem.set('minOccurs', str(obj.minOccurs))
if hasattr(obj,'maxOccurs'):
@@ -870,6 +902,8 @@
elem.set('mapKey', str(obj.mapKey))
if hasattr(obj,'mapValue') and obj.mapValue is not None:
elem.set('mapValue', str(obj.mapValue))
+ if hasattr(obj,'displayName') and obj.displayName is not None:
+ elem.set('displayName', str(obj.displayName))
for child in obj._objects():
""" Make sure that the object is mapped to an object in this model """
@@ -878,7 +912,6 @@
childelem = writer.dumps(child)
if childelem != None:
elem.append(childelem)
- return elem
class ConfmlSettingReader(ConfmlReader):
@@ -891,7 +924,7 @@
of the given elem name
"""
if parent and not (parent=='feature' or parent=='setting'):
- return False
+ return False
if elemname=='setting':
return True
else:
@@ -905,7 +938,8 @@
if typedef == 'sequence':
map_key = elem.get('mapKey')
map_value = elem.get('mapValue')
- feature = model.ConfmlSequenceSetting(elem.get('ref'), mapKey=map_key, mapValue=map_value)
+ display_name = elem.get('displayName')
+ feature = model.ConfmlSequenceSetting(elem.get('ref'), mapKey=map_key, mapValue=map_value, displayName=display_name)
elif typedef == 'int':
feature = model.ConfmlIntSetting(elem.get('ref'))
elif typedef == 'boolean':
@@ -930,14 +964,25 @@
feature = model.ConfmlDateTimeSetting(elem.get('ref'))
elif typedef == 'duration':
feature = model.ConfmlDurationSetting(elem.get('ref'))
+ elif typedef == 'hexBinary':
+ feature = model.ConfmlHexBinarySetting(elem.get('ref'))
else:
# Handle the default setting as int type
- feature = model.ConfmlSetting(elem.get('ref'), type=None)
+ feature = model.ConfmlSetting(elem.get('ref'), type=typedef)
+ feature.lineno = utils.etree.get_lineno(elem)
+ self._get_setting_properties(elem, feature)
+ return feature
+ def _get_setting_properties(self, elem, feature):
+ """
+ Get the setting properties for the given feature from the given xml elem
+ """
if elem.get('name'):
feature.set_name(elem.get('name'))
+ if elem.get('id'):
+ feature.set_id(elem.get('id'))
if elem.get('minOccurs'):
feature.minOccurs = int(elem.get('minOccurs'))
if elem.get('maxOccurs'):
@@ -960,12 +1005,63 @@
if obj != None:
feature.add(obj,container.APPEND)
else:
- logging.getLogger('cone').warning("Invalid child %s in %s" % (elem,feature.name))
+ add_parse_warning("Invalid child %s in %s" % (elem, feature.name),
+ utils.etree.get_lineno(elem))
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
- return feature
+
+
+class GroupSettingWriter(ConfmlSettingWriter):
+ """
+ """
+ @classmethod
+ def supported_class(cls, classname):
+ """
+ Class method to determine if this ConfmlWriter supports writing
+ of the given class name
+ """
+ if classname=="FeatureLink" or \
+ classname=="ConfmlFeatureLink":
+ return True
+ else:
+ return False
+ def dumps(self, obj):
+ """
+ @param obj: The Configuration object
+ """
+ ref = obj.fqr.replace('.','/')
+ elem = ElementTree.Element('setting',
+ {'ref' : ref})
+ self._set_setting_properties(elem, obj)
+ return elem
+
+
+class GroupSettingReader(ConfmlSettingReader):
+ """
+ """
+ @classmethod
+ def supported_elem(cls, elemname, parent=None):
+ """
+ Class method to determine if this ConfmlWriter supports reading
+ of the given elem name
+ """
+ if elemname=='setting' and parent=='group':
+ return True
+ else:
+ return False
+
+ def loads(self, elem):
+ """
+ @param elem: The xml include elem
+ """
+ ref = elem.get('ref') or ''
+ ref = ref.replace('/','.')
+ feature_link = model.ConfmlFeatureLink(ref)
+ feature_link.lineno = utils.etree.get_lineno(elem)
+ self._get_setting_properties(elem, feature_link)
+ return feature_link
class ConfmlLocalPathWriter(ConfmlWriter):
@classmethod
@@ -1007,7 +1103,9 @@
"""
@param elem: The xml include elem
"""
- return model.ConfmlLocalPath(readOnly=elem.get('readOnly'))
+ obj = model.ConfmlLocalPath(readOnly=elem.get('readOnly'))
+ obj.lineno = utils.etree.get_lineno(elem)
+ return obj
class ConfmlTargetPathWriter(ConfmlWriter):
@@ -1050,7 +1148,9 @@
"""
@param elem: The xml include elem
"""
- return model.ConfmlTargetPath(readOnly=elem.get('readOnly'))
+ obj = model.ConfmlTargetPath(readOnly=elem.get('readOnly'))
+ obj.lineno = utils.etree.get_lineno(elem)
+ return obj
class DummyWriter(ConfmlWriter):
@@ -1094,13 +1194,14 @@
(namespace,elemname) = get_elemname(elem.tag)
obj = api.DataContainer(elemname, container=True)
+ obj.lineno = utils.etree.get_lineno(elem)
for elem in elem.getchildren():
try:
reader = ElemReader(attr='rfs')
childobj = reader.loads(elem)
obj.add(childobj)
except exceptions.ConePersistenceError,e:
- logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
+ add_unknown_element_warning(elem)
continue
return obj
@@ -1118,10 +1219,15 @@
datavalue = None
if len(list(elem)) == 0:
datavalue = elem.text
- datatemplate = elem.get('template') == 'true' or self.template
- dataextensionpolicy = elem.get('extensionPolicy') or ''
- datamap = elem.get('map')
- obj = api.Data(ref=elemname,value=datavalue, template=datatemplate, attr=self.attr,policy=dataextensionpolicy,map=datamap)
+ obj = model.ConfmlData(
+ ref = elemname,
+ value = datavalue,
+ template = elem.get('template') == 'true' or self.template,
+ attr = self.attr,
+ policy = elem.get('extensionPolicy') or '',
+ map = elem.get('map'),
+ empty = elem.get('empty') == 'true')
+ obj.lineno = utils.etree.get_lineno(elem)
for elem in elem.getchildren():
try:
reader = ElemReader(**self.args)
@@ -1152,13 +1258,13 @@
def get_reader_for_elem(elemname, parent=None):
- for reader in ConfmlReader.__subclasses__():
+ for reader in utils.all_subclasses(ConfmlReader):
if reader.supported_elem(elemname,parent):
return reader()
raise exceptions.ConePersistenceError("No reader for given elem %s under %s found!" % (elemname, parent))
def get_writer_for_class(classname):
- for writer in ConfmlWriter.__subclasses__():
+ for writer in utils.all_subclasses(ConfmlWriter):
if writer.supported_class(classname):
return writer ()
raise exceptions.ConePersistenceError("No writer for given class found! %s" % classname)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/__init__.py
--- a/configurationengine/source/cone/confml/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,33 +14,3 @@
# Description:
#
-import unittest, os, sys
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../..'))
-if SOURCE_ROOT not in sys.path:
- sys.path.insert(0, SOURCE_ROOT)
-
-# Find all unittest_*.py files in this folder
-import re
-__all__ = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(ROOT_PATH))
-# Strip .py endings
-__all__ = map(lambda name: name[:-3], __all__)
-
-def collect_suite():
- sys.path.insert(0, ROOT_PATH)
- try:
- suite = unittest.TestSuite()
- for test_module in __all__:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- del sys.path[0]
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/data/multiselection.confml
--- a/configurationengine/source/cone/confml/tests/data/multiselection.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/data/multiselection.confml Tue Aug 10 14:29:28 2010 +0300
@@ -47,7 +47,7 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/runtests.py
--- a/configurationengine/source/cone/confml/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/basic_setting_types_test.confml
--- a/configurationengine/source/cone/confml/tests/testdata/read_write/basic_setting_types_test.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/testdata/read_write/basic_setting_types_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -36,6 +36,10 @@
+
+
+ A hex-binary setting
+
@@ -46,6 +50,7 @@
true1"opt 0" "opt 2" "opt 4"
+ 00112233445566778899AABBCCDDEEFF
@@ -57,6 +62,7 @@
truetruetrue
+ false
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/configuration_version_test.confml
Binary file configurationengine/source/cone/confml/tests/testdata/read_write/configuration_version_test.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/confml/tests/testdata/read_write/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/empty_attributes_test.confml
Binary file configurationengine/source/cone/confml/tests/testdata/read_write/empty_attributes_test.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/facets.confml
Binary file configurationengine/source/cone/confml/tests/testdata/read_write/facets.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/feature1.confml
--- a/configurationengine/source/cone/confml/tests/testdata/read_write/feature1.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/testdata/read_write/feature1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -96,6 +96,8 @@
1"opt 2"
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/name_id_mapping_test.confml
--- a/configurationengine/source/cone/confml/tests/testdata/read_write/name_id_mapping_test.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/testdata/read_write/name_id_mapping_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -5,7 +5,7 @@
-
+
@@ -25,7 +25,7 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/read_write/view.confml
--- a/configurationengine/source/cone/confml/tests/testdata/read_write/view.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/testdata/read_write/view.confml Tue Aug 10 14:29:28 2010 +0300
@@ -25,7 +25,7 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/seq_template/expected/complex_seq.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/confml/tests/testdata/seq_template/expected/complex_seq.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file lp
+ file tp
+
+
+ folder lp
+ folder tp
+
+ string
+ 0
+ 0.1
+ false
+ 2010-02-10
+
+ 2010-02-10-00:00:00
+ P5Y4M3DT12H25M15S
+
+
+
+ file lp1
+ file tp1
+
+
+ folder lp1
+ folder tp1
+
+ string1
+ 1
+ 1.1
+ true
+ 2009-02-01
+
+ 2009-02-01-01:00:00
+ PT1S
+
+
+
+ file lp2
+ file tp2
+
+
+ folder lp2
+ folder tp2
+
+ string2
+ 2
+ 1.2
+ false
+ 2009-02-02
+
+ 2009-02-02-02:00:00
+ PT2S
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/seq_template/expected/complex_seq_with_nones.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/confml/tests/testdata/seq_template/expected/complex_seq_with_nones.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file lp
+
+
+ folder tp
+
+ string
+ 0.1
+ 2010-02-10
+ 2010-02-10-00:00:00
+
+
+
+
+
+
+
+ file lp1
+
+
+
+
+ folder tp1
+
+ string1
+
+ 1.1
+
+ 2009-02-01
+
+ 2009-02-01-01:00:00
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/seq_template/expected/simple_seq.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/confml/tests/testdata/seq_template/expected/simple_seq.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c1
+
+ lp
+ tp
+
+ c2
+
+
+ row 1
+
+ lp1
+ tp1
+
+ x
+
+
+ row 2
+
+ lp2
+ tp2
+
+ y
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/testdata/seq_template/expected/simple_seq_no_template.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/confml/tests/testdata/seq_template/expected/simple_seq_no_template.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ row 1
+
+ lp1
+ tp1
+
+ x
+
+
+ row 2
+
+ lp2
+ tp2
+
+ y
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/unittest_confmlxml.py
--- a/configurationengine/source/cone/confml/tests/unittest_confmlxml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/unittest_confmlxml.py Tue Aug 10 14:29:28 2010 +0300
@@ -23,7 +23,6 @@
import sys
import os
import shutil
-import __init__
from cone.public import api, exceptions, persistence
from cone.storage import filestorage
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/unittest_implml.py
--- a/configurationengine/source/cone/confml/tests/unittest_implml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/unittest_implml.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,7 +16,6 @@
import unittest
import os
-import __init__
from cone.public.exceptions import NotSupportedException
from cone.confml import implml
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/unittest_mapping.py
--- a/configurationengine/source/cone/confml/tests/unittest_mapping.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/unittest_mapping.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import sys
import os
import shutil
-import __init__
from cone.public import api, exceptions
from cone.confml import model, mapping
@@ -84,7 +83,7 @@
def test_map_carbon_setting_with_data(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlSetting("test")
+ c1 = model.ConfmlSetting("test", name="test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonSetting))
self.assertEquals(c2.name, "test")
@@ -92,7 +91,7 @@
def test_map_carbon_setting_with_desc(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlSetting("test")
+ c1 = model.ConfmlSetting("test", name="test")
c1.desc = 'Testing man'
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonSetting))
@@ -102,7 +101,7 @@
def test_map_carbon_int_setting_with_data(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlIntSetting("test")
+ c1 = model.ConfmlIntSetting("test", name="test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonIntSetting))
self.assertEquals(c2.name, "test")
@@ -110,7 +109,7 @@
def test_map_carbon_setting_with_data(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlBooleanSetting("test")
+ c1 = model.ConfmlBooleanSetting("test", name="test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonBooleanSetting))
self.assertEquals(c2.name, "test")
@@ -118,7 +117,7 @@
def test_map_carbon_setting_with_data(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlSelectionSetting("test")
+ c1 = model.ConfmlSelectionSetting("test", name="test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonSelectionSetting))
self.assertEquals(c2.name, "test")
@@ -126,7 +125,7 @@
def test_map_carbon_feature(self):
mapper = model.get_mapper('carbon')
- c1 = model.ConfmlFeature("test")
+ c1 = model.ConfmlFeature("test", name="test")
c2 = mapper.map_object(c1)
self.assertTrue(isinstance(c2, carbonmodel.CarbonFeature))
self.assertEquals(c2.name, "test")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/unittest_model.py
--- a/configurationengine/source/cone/confml/tests/unittest_model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/unittest_model.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,10 +15,7 @@
#
import unittest
-import string
import sys
-import __init__
-
from cone.public import api, exceptions
from cone.confml import model
@@ -26,7 +23,7 @@
class TestConfmlMeta(unittest.TestCase):
def test_create_meta(self):
metaelem = model.ConfmlMeta()
- self.assertTrue(metaelem)
+ self.assertEquals(str(metaelem),"ConfmlMeta object\n")
def test_create_with_data(self):
prop1 = model.ConfmlMetaProperty("foo", 123)
@@ -37,6 +34,7 @@
attrs={"name":"name1", "value": "value1"})
metaelem = model.ConfmlMeta([prop1, prop2, prop3, prop4])
self.assertEquals(metaelem[0].tag, "foo")
+ self.assertEquals(metaelem[0].attrs, {})
self.assertEquals(metaelem[0].value, 123)
self.assertEquals(metaelem[1].tag, "bar")
self.assertEquals(metaelem[1].value, 312)
@@ -54,15 +52,50 @@
self.assertEquals(metaelem[0].ns, "abc")
self.assertEquals(metaelem[0].attrs, {"foo":"bar", "abc":1})
+ def test_update_data(self):
+ metaelem = model.ConfmlMeta()
+ metaelem.append(model.ConfmlMetaProperty('test', 123, "abc", attrs = {"foo":"bar", "abc":1}))
+ metaelem.set_property_by_tag('foo', 3)
+ metaelem.set_property_by_tag('bar', None, 'http://me.com', {'name':'me', 'value':1})
+ self.assertEquals(metaelem[0].tag, 'test')
+ self.assertEquals(metaelem[0].value, 123)
+ self.assertEquals(metaelem[0].ns, "abc")
+ self.assertEquals(metaelem[0].attrs, {"foo":"bar", "abc":1})
+ self.assertEquals(metaelem[1].tag, 'foo')
+ self.assertEquals(metaelem[1].value, 3)
+ self.assertEquals(metaelem[2].tag, "bar")
+ self.assertEquals(metaelem[2].attrs, {'name':'me', 'value':1})
+
+ metaelem1 = model.ConfmlMeta()
+ metaelem.set_property_by_tag('foo', 2)
+ metaelem.set_property_by_tag('bar', None, 'http://me.com', {'name':'me', 'value':2})
+ metaelem.update(metaelem1)
+ self.assertEquals(len(metaelem), 3)
+ self.assertEquals(metaelem[0].tag, 'test')
+ self.assertEquals(metaelem[0].value, 123)
+ self.assertEquals(metaelem[0].ns, "abc")
+ self.assertEquals(metaelem[0].attrs, {"foo":"bar", "abc":1})
+ self.assertEquals(metaelem[1].tag, 'foo')
+ self.assertEquals(metaelem[1].value, 2)
+ self.assertEquals(metaelem[2].tag, "bar")
+ self.assertEquals(metaelem[2].attrs, {'name':'me', 'value':2})
+
+
def test_find_data(self):
metaelem = model.ConfmlMeta()
metaelem.append(model.ConfmlMetaProperty('test', 123, "abc",\
attrs = {"foo":"bar", "abc":1}))
metaelem.append(model.ConfmlMetaProperty('abc', "efg", None,\
attrs = {"foo2":"bar2", "abc2":2}))
+ metaelem.append(model.ConfmlMetaProperty('test', None, "demons",\
+ attrs = {"name":"bar1", "value":"foo1"}))
+ metaelem.append(model.ConfmlMetaProperty('test', None, "demons",\
+ attrs = {"name":"bar2", "value":"foo2"}))
self.assertEquals(metaelem.find_by_tag("test"), 0)
self.assertEquals(metaelem.get_property_by_tag("test").tag, 'test')
self.assertEquals(metaelem.get_property_by_tag("test").value, 123)
+ self.assertEquals(metaelem.get_property_by_tag("test", {'name' : 'bar1'}).tag, 'test')
+ self.assertEquals(metaelem.get_property_by_tag("test", {'name' : 'bar1'}).attrs['value'], 'foo1')
self.assertEquals(metaelem.get("test"), 123)
self.assertEquals(metaelem.get("test", 'ddd'), 123)
# test get_value with not found elem
@@ -79,7 +112,20 @@
metaelem2 = metaelem1.clone()
self.assertEquals(metaelem1, metaelem2)
-
+ def test_meta_set_property_by_tag(self):
+ meta = model.ConfmlMeta()
+ meta.set_property_by_tag('test', 'fooval')
+ self.assertEquals(meta.get('test'), 'fooval')
+ self.assertEquals(meta.get_property_by_tag('test').attrs, {})
+ meta.set_property_by_tag('test', 'newval')
+ self.assertEquals(meta.get_property_by_tag('test').attrs, {})
+ self.assertEquals(meta.get('test'), 'newval')
+ meta.add('test', 'twoval')
+ self.assertEquals(meta.get_property_by_tag('test').attrs, {})
+ self.assertEquals(meta.get('test'), 'newval')
+ meta.set_property_by_tag('test', 'trheval')
+ self.assertEquals(meta.get('test'), 'trheval')
+
class TestConfmlDescription(unittest.TestCase):
def test_create_desc(self):
descelem1 = model.ConfmlDescription("testing")
@@ -141,19 +187,28 @@
self.assertEquals(elem.constraint, None)
self.assertEquals(elem.required, None)
self.assertEquals(elem.relevant, None)
+ self.assertEquals(elem.id, None)
+
+ def test_setting_id(self):
+ elem = model.ConfmlSetting('foo', id="test id")
+ self.assertEquals(elem.id,'test id')
+ elem.id = "new id"
+ self.assertEquals(elem.id,'new id')
+ del elem.id
+ self.assertEquals(elem.id,None)
def test_getters(self):
- elem = model.ConfmlSetting('foo')
- self.assertTrue(elem.get_ref(),'foo')
+ elem = model.ConfmlSetting('foo', name="foo")
+ self.assertEquals(elem.get_ref(),'foo')
self.assertEquals(elem.get_type(),None)
- self.assertTrue(elem.get_name(),'foo')
+ self.assertEquals(elem.get_name(),'foo')
def test_set_type(self):
- elem = model.ConfmlSetting('foo')
+ elem = model.ConfmlSetting('foo', name="bar")
elem.type = 'string'
- self.assertTrue(elem.ref,'foo')
- self.assertTrue(elem.type,'string')
- self.assertTrue(elem.name,'foo')
+ self.assertEquals(elem.ref,'foo')
+ self.assertEquals(elem.type,'string')
+ self.assertEquals(elem.name, "bar")
def test_setting_with_options(self):
elem = model.ConfmlSetting('foo',type='selection')
@@ -165,15 +220,20 @@
self.assertEquals(elem.options['1'].value, '1')
self.assertEquals(elem.options['bar'].name, 'bar')
+ def test_create_options(self):
+ elem = model.ConfmlSetting('foo',type='property', name='foo')
+ self.assertEquals(elem.name, 'foo')
+ self.assertEquals(elem.type, 'property')
+
def test_setting_create_with_nonetype(self):
elem = model.ConfmlSetting('foo',type=None)
self.assertEqual(elem.type,None)
def test_setting_with_properties(self):
elem = model.ConfmlSetting('foo')
- elem.add_property(name='foo',value='bar/foo')
- elem.add_property(name='bar',value='only/bar')
- elem.add_property(name='testing',value='1', unit='mB')
+ elem.create_property(name='foo',value='bar/foo')
+ elem.create_property(name='bar',value='only/bar')
+ elem.create_property(name='testing',value='1', unit='mB')
self.assertEquals(elem.list_properties(), ['foo','bar','testing'])
self.assertEquals(elem.get_property('foo').value, 'bar/foo')
elem.remove_property('foo')
@@ -190,11 +250,11 @@
def test_setting_with_properties_property(self):
elem = model.ConfmlSetting('foo')
- elem.add_property(name='foo',value='bar/foo')
- elem.add_property(name='bar',value='only/bar')
- elem.add_property(name='testing',value='1', unit='mB')
- self.assertEquals(elem.properties['foo'].value,'bar/foo')
- self.assertEquals(elem.properties['bar'].value,'only/bar')
+ elem.create_property(name='foo',value='bar/foo')
+ elem.create_property(name='bar',value='only/bar')
+ elem.create_property(name='testing',value='1', unit='mB')
+ self.assertEquals(elem.property_foo.value,'bar/foo')
+ self.assertEquals(elem.property_bar.value,'only/bar')
def test_setting_with_readOnly_value(self):
elem = model.ConfmlSetting('foo', readOnly=True)
@@ -235,6 +295,14 @@
elem.minLength = 20
self.assertEquals(elem.minLength,20)
self.assertTrue(elem._has(model.ConfmlMinLength.refname))
+
+ def test_setting_with_length(self):
+ elem = model.ConfmlSetting('foo', length=10)
+ self.assertEquals(elem.length,10)
+ elem.length = 20
+ self.assertEquals(elem.length,20)
+ self.assertTrue(elem._has(model.ConfmlLength.refname))
+ self.assertEquals(elem._get(model.ConfmlLength.refname).value, 20)
def test_setting_rfs_casting(self):
elem = model.ConfmlSetting('foo', minLength=10)
@@ -243,13 +311,63 @@
self.assertEquals(elem.set_rfs_cast(True),'true')
self.assertEquals(elem.set_rfs_cast(False),'false')
self.assertEquals(elem.set_rfs_cast(1),'true')
+
+ def test_get_rfs_with_no_value(self):
+ conf = api.Configuration("test.confml")
+ conf.add_feature(model.ConfmlSetting("foo"))
+
+ # Test that initially the RFS value is None
+ fea = conf.get_default_view().get_feature('foo')
+ self.assertEquals(fea.get_value(attr='rfs'), None)
+ self.assertEquals(fea.get_original_value(attr='rfs'), None)
+
+ def test_get_rfs_true(self):
+ conf = api.Configuration("test.confml")
+ conf.add_feature(model.ConfmlSetting("foo"))
+ conf.add_data(api.Data(ref='foo', attr='rfs', value='true'))
+
+ fea = conf.get_default_view().get_feature('foo')
+ self.assertEquals(fea.get_value(attr='rfs'), True)
+ self.assertEquals(fea.get_original_value(attr='rfs'), 'true')
+
+ def test_get_rfs_false(self):
+ conf = api.Configuration("test.confml")
+ conf.add_feature(model.ConfmlSetting("foo"))
+ conf.add_data(api.Data(ref='foo', attr='rfs', value='false'))
+
+ fea = conf.get_default_view().get_feature('foo')
+ self.assertEquals(fea.get_value(attr='rfs'), False)
+ self.assertEquals(fea.get_original_value(attr='rfs'), 'false')
+
+ def test_set_rfs(self):
+ conf = api.Configuration("test.confml")
+ conf.add_feature(model.ConfmlSetting("foo"))
+
+ def check_data_elements(expected):
+ actual = []
+ for d in conf._traverse(type=api.Data):
+ actual.append((d.fqr, d.attr, d.value))
+ self.assertEquals(actual, expected)
+
+ fea = conf.get_default_view().get_feature('foo')
+
+ fea.set_value(True, attr='rfs')
+ self.assertEquals(fea.get_value(attr='rfs'), True)
+ self.assertEquals(fea.get_original_value(attr='rfs'), 'true')
+ check_data_elements([('foo', 'rfs', 'true')])
+
+ fea.set_value(False, attr='rfs')
+ self.assertEquals(fea.get_value(attr='rfs'), False)
+ self.assertEquals(fea.get_original_value(attr='rfs'), 'false')
+ check_data_elements([('foo', 'rfs', 'false')])
class TestConfmlSelectionSetting(unittest.TestCase):
def test_create_selection_setting(self):
- elem = model.ConfmlSelectionSetting('foo')
+ elem = model.ConfmlSelectionSetting('foo', desc="Test desc", name="Foo fea")
self.assertTrue(elem)
self.assertEquals(elem.type, 'selection')
- self.assertEquals(elem.desc, None)
+ self.assertEquals(elem.name, 'Foo fea')
+ self.assertEquals(elem.desc, "Test desc")
self.assertEquals(elem.readOnly, None)
self.assertEquals(elem.constraint, None)
self.assertEquals(elem.required, None)
@@ -265,10 +383,11 @@
class TestConfmlMultiSelectionSetting(unittest.TestCase):
def test_create_multiselection_setting(self):
- elem = model.ConfmlMultiSelectionSetting('mset1')
+ elem = model.ConfmlMultiSelectionSetting('mset1', name="Setting 1", desc="de")
self.assertTrue(elem)
self.assertEquals(elem.type, 'multiSelection')
- self.assertEquals(elem.desc, None)
+ self.assertEquals(elem.name, "Setting 1")
+ self.assertEquals(elem.desc, "de")
self.assertEquals(elem.readOnly, None)
self.assertEquals(elem.constraint, None)
self.assertEquals(elem.required, None)
@@ -286,33 +405,19 @@
conf = model.ConfmlConfiguration('test.confml')
elem = model.ConfmlMultiSelectionSetting('mset2', type='multiSelection')
conf.add_feature(elem)
- elem.value = "\"sel1\" \"sel2\""
+ elem.value = ["sel1", "sel2"]
self.assertEquals(elem.type, 'multiSelection')
- self.assertEquals(elem.get_data_cast("\"sel1\" \"sel2\""), ["sel1", "sel2"])
- self.assertEquals(elem.get_value(), ["sel1", "sel2"])
-
- def test_set_data_cast(self):
- elem = model.ConfmlMultiSelectionSetting('mset3', type='multiSelection')
- self.assertEquals(elem.set_data_cast('"sel1" "sel2 with some spaces"'), '"sel1" "sel2 with some spaces"')
- self.assertEquals(elem.set_data_cast(["sel1", "sel2 with some spaces"]), '"sel1" "sel2 with some spaces"')
- self.assertEquals(elem.set_data_cast(["1", "1"]), '"1" "1"')
- self.assertEquals(elem.set_data_cast([1, 2, 3]), '"1" "2" "3"')
-
-
- def test_get_data_cast(self):
- elem = model.ConfmlMultiSelectionSetting('mset3', type='multiSelection')
- self.assertEquals(elem.get_data_cast('"sel1" "sel2 with some spaces"'), ["sel1", "sel2 with some spaces"])
- self.assertEquals(elem.get_data_cast('"sel1" "sel2 space" "foo bar"'), ["sel1", "sel2 space", "foo bar"])
+ self.assertEquals(elem.get_value(), ("sel1", "sel2"))
def test_setting_value_to_multiselection2(self):
conf = model.ConfmlConfiguration('test.confml')
elem = model.ConfmlMultiSelectionSetting('mset3', type='multiSelection')
conf.add_feature(elem)
- elem.value = '"sel1" "sel2 with some spaces"'
+ elem.value = ["sel1", "sel2 with some spaces"]
self.assertEquals(elem.type, 'multiSelection')
- self.assertEquals(elem.get_value(), ["sel1", "sel2 with some spaces"])
+ self.assertEquals(elem.get_value(), ("sel1", "sel2 with some spaces"))
elem.value = ["sel1", "sel2 with some spaces"]
- self.assertEquals(elem.get_value(), ["sel1", "sel2 with some spaces"])
+ self.assertEquals(elem.get_value(), ("sel1", "sel2 with some spaces"))
def test_setting_not_list_value_to_multiselection(self):
conf = model.ConfmlConfiguration('test.confml')
@@ -325,8 +430,119 @@
elem = model.ConfmlMultiSelectionSetting('mset5', type='multiSelection')
conf.add_feature(elem)
elem.set_value(["li1", "li2"])
- self.assertEquals(elem.get_value(), ["li1", "li2"])
- self.assertEquals(elem.get_data().get_value(), '"li1" "li2"')
+ self.assertEquals(elem.get_value(), ("li1", "li2"))
+ self.assertEquals(elem.get_datas()[0].get_value(), 'li1')
+ self.assertEquals(elem.get_datas()[1].get_value(), 'li2')
+
+ def test_get_value_from_old_style_data(self):
+ def check(data_value, expected):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlMultiSelectionSetting('multisel', type='multiSelection')
+ config.add_feature(fea)
+ config.add_data(api.Data(ref='multisel', value=data_value))
+
+ dview = config.get_default_view()
+ foofea = dview.get_feature('multisel')
+ self.assertEquals(foofea.value, expected)
+
+ check('x', ('x',))
+ check('"x"', ('x',))
+ check('"x" "y"', ('x', 'y'))
+ check('"x" "y" "" "z"', ('x', 'y', '', 'z'))
+
+ def test_get_value_with_new_style_data(self):
+ def check(data_object_values, expected_value, empty_option=False):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlMultiSelectionSetting('multisel', type='multiSelection')
+ if empty_option:
+ fea.add_option(api.Option('Empty option', ''))
+ config.add_feature(fea)
+ for dv in data_object_values:
+ config.add_data(api.Data(ref='multisel', value=dv), policy=api.container.APPEND)
+
+ dview = config.get_default_view()
+ foofea = dview.get_feature('multisel')
+ self.assertEquals(foofea.value, expected_value)
+
+ check([], ())
+ check(['x'], ('x',))
+ check(['x', 'y'], ('x', 'y'))
+ check(['y', 'x', 'y',], ('y', 'x'))
+ check(['"foo"', '"bar"'], ('"foo"', '"bar"'))
+ check(['foo bar'], ('foo bar',))
+ check(['foo bar', 'foo baz'], ('foo bar', 'foo baz'))
+ check(['foo "bar"'], ('foo "bar"',))
+
+ # Element with no data is interpreted as meaning the option ''
+ # if it is allowed, otherwise it is ignored
+ check([None], (), empty_option=False)
+ check([None], ('',), empty_option=True)
+
+ def test_get_value_from_data_with_empty_attribute(self):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlMultiSelectionSetting('multisel', type='multiSelection')
+ config.add_feature(fea)
+ config.add_data(api.Data(ref='multisel', empty=True))
+
+ dview = config.get_default_view()
+ foofea = dview.get_feature('multisel')
+ self.assertEquals(foofea.value, ())
+
+
+ def test_set_value(self):
+ def check(value, expected_data_object_values):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlMultiSelectionSetting('multisel', type='multiSelection')
+ config.add_feature(fea)
+
+ dview = config.get_default_view()
+ foofea = dview.get_feature('multisel')
+ self.assertEquals(foofea.value, ())
+
+ foofea.value = value
+ # Check that the value is visible directly after setting
+ # (the 'or' is because setting to None actually set the value
+ # to an empty tuple)
+ self.assertEquals(foofea.value, value or ())
+
+ # Check that the data elements have been set as expected
+ actual = []
+ for d in config._traverse(type=api.Data):
+ actual.append((d.fqr, d.value, d.empty))
+ expected = []
+ for val, empty in expected_data_object_values:
+ expected.append(('multisel', val, empty))
+ self.assertEquals(actual, expected)
+
+ # Setting empty should create a single data object with empty=True
+ check((), [(None, True)])
+ check([], [(None, True)])
+ check(None, [(None, True)])
+
+ check(('x',), [('x', False)])
+ check(('x', 'y'), [('x', False), ('y', False)])
+ check(('"foo"', '"bar"'), [('"foo"', False), ('"bar"', False)])
+ check(('foo bar',), [('foo bar', False)])
+ check(('foo bar', 'foo baz'), [('foo bar', False), ('foo baz', False)])
+ check(('foo "bar"',), [('foo "bar"', False)])
+
+ def test_old_style_data_pattern(self):
+ def check(value, expected):
+ m = model.ConfmlMultiSelectionSetting.OLD_STYLE_DATA_PATTERN.match(value)
+ self.assertEquals(m is not None, expected)
+
+ check('', False)
+ check('""', True)
+ check('foo', False)
+ check('foo bar', False)
+ check('"foo bar"', True)
+ check('"foo bar " " foo baz" " yeah " ""', True)
+ check('"foo"', True)
+ check('"foo" "bar"', True)
+ check('"foo" "bar" "baz"', True)
+ check('"a" "b" "c" "d" "e" "f" "g" "h"', True)
+ check('a b c d e f g h', False)
+ check('"a b c d e f g h"', True)
class TestConfmlIntSetting(unittest.TestCase):
def test_create_setting(self):
@@ -338,6 +554,8 @@
self.assertEquals(elem.constraint, None)
self.assertEquals(elem.required, None)
self.assertEquals(elem.relevant, None)
+ self.assertEquals(elem.get_valueset().fromvalue, 0)
+ self.assertEquals(elem.get_valueset().tovalue, sys.maxint)
def test_setting_value_to_int(self):
conf = model.ConfmlConfiguration('test.confml')
@@ -364,7 +582,7 @@
del elem.value
self.assertEquals(elem.value, None)
- def test_setting_value_to_int(self):
+ def test_setting_value_to_int_with_aritmethic_operations(self):
conf = model.ConfmlConfiguration('test.confml')
elem1 = model.ConfmlIntSetting('foo')
elem2 = model.ConfmlIntSetting('bar')
@@ -377,6 +595,79 @@
elem1.value = elem1.value + elem2.value + 5
self.assertEquals(elem1.value,8)
+class TestConfmlHexBinarySetting(unittest.TestCase):
+ def test_hexbinary_default_value_set(self):
+ setting = model.ConfmlHexBinarySetting('test')
+ vset = setting.get_valueset()
+ self.assertTrue('' in vset)
+ self.assertTrue('0123456789ABCDEF' in vset)
+ self.assertTrue('00112233445566778899AABBCCDDEEFF' in vset)
+
+ self.assertFalse('foobar' in vset)
+ self.assertFalse('1' in vset)
+ self.assertFalse('F' in vset)
+ self.assertFalse('1G' in vset)
+ self.assertFalse('0123456789abcdef' in vset)
+ self.assertFalse('00112233445566778899aabbccddeeff' in vset)
+
+ self.assertTrue('foobar' not in vset)
+
+ def test_hexbinary_get_value_none(self):
+ conf = model.ConfmlConfiguration('test.confml')
+ setting = model.ConfmlHexBinarySetting('foo')
+ conf.add_feature(setting)
+ self.assertEquals(setting.value, None)
+
+ def test_hexbinary_get_value_empty(self):
+ conf = model.ConfmlConfiguration('test.confml')
+ setting = model.ConfmlHexBinarySetting('foo')
+ conf.add_feature(setting)
+ conf.add_data(api.Data(ref='foo', value=None))
+ self.assertEquals(setting.value, '')
+
+ def test_hexbinary_get_value(self):
+ conf = model.ConfmlConfiguration('test.confml')
+ setting = model.ConfmlHexBinarySetting('foo')
+ conf.add_feature(setting)
+ conf.add_data(api.Data(ref='foo', value='0123456789ABCDEF'))
+ self.assertEquals(setting.value, '\x01\x23\x45\x67\x89\xab\xcd\xef')
+ self.assertEquals(setting.get_original_value(), '0123456789ABCDEF')
+
+ def test_hexbinary_set_value(self):
+ conf = model.ConfmlConfiguration('test.confml')
+ setting = model.ConfmlHexBinarySetting('foo')
+ conf.add_feature(setting)
+
+ setting.value = '\x01\xab'
+ self.assertEquals(setting.value, '\x01\xab')
+
+ data_list = conf.get_all_datas()
+ self.assertEquals(len(data_list), 1)
+ d = data_list[0]
+ self.assertEquals(d.attr, 'data')
+ self.assertEquals(d.fqr, 'foo')
+ self.assertEquals(d.value, '01AB')
+ self.assertEquals(d.empty, False)
+
+ def test_hexbinary_get_data_cast(self):
+ setting = model.ConfmlHexBinarySetting('foo')
+
+ self.assertEquals(setting.get_data_cast(''), '')
+ self.assertEquals(setting.get_data_cast(None), '')
+ self.assertEquals(setting.get_data_cast('0123456789ABCDEF'), '\x01\x23\x45\x67\x89\xab\xcd\xef')
+
+ self.assertRaises(ValueError, setting.get_data_cast, 'X')
+ self.assertRaises(ValueError, setting.get_data_cast, '1')
+ self.assertRaises(ValueError, setting.get_data_cast, 'XX')
+
+ def test_hexbinary_set_data_cast(self):
+ setting = model.ConfmlHexBinarySetting('foo')
+
+ self.assertEquals(setting.set_data_cast(''), '')
+ self.assertEquals(setting.set_data_cast('\x01'), '01')
+ self.assertEquals(setting.set_data_cast('x'), '78')
+ self.assertEquals(setting.set_data_cast('\x01\x23\x45\x67\x89\xab\xcd\xef'), '0123456789ABCDEF')
+
class TestConfmlBooleanSetting(unittest.TestCase):
def test_create_setting(self):
elem = model.ConfmlBooleanSetting('test')
@@ -438,17 +729,30 @@
class TestConfmlSequenceSetting(unittest.TestCase):
def test_create_setting(self):
- elem = model.ConfmlSequenceSetting('test')
+ elem = model.ConfmlSequenceSetting('test', name="testing fea", desc="Test desc")
self.assertTrue(elem)
- self.assertEquals(elem.desc, None)
+ self.assertEquals(elem.name, "testing fea")
+ self.assertEquals(elem.desc, "Test desc")
+ subfea = elem.create_feature("subfea")
+ self.assertEquals(subfea.is_sequence(), True)
+ subfea.is_sequence = lambda : False
+ self.assertEquals(subfea.is_sequence(), False)
+
+ def test_create_sequence_setting_with_mapping(self):
+ elem = model.ConfmlSequenceSetting('test', name="testing fea", desc="Test desc", mapKey="setting", mapValue="setval")
+ self.assertTrue(elem)
+ self.assertEquals(elem.name, "testing fea")
+ self.assertEquals(elem.desc, "Test desc")
+ self.assertEquals(elem.mapKey, "setting")
+ self.assertEquals(elem.mapValue, "setval")
def test_setting_with_properties_property(self):
elem = model.ConfmlSequenceSetting('foo')
- elem.add_property(name='foo',value='bar/foo')
- elem.add_property(name='bar',value='only/bar')
- elem.add_property(name='testing',value='1', unit='mB')
- self.assertEquals(elem.properties['foo'].value,'bar/foo')
- self.assertEquals(elem.properties['bar'].value,'only/bar')
+ elem.create_property(name='foo',value='bar/foo')
+ elem.create_property(name='bar',value='only/bar')
+ elem.create_property(name='testing',value='1', unit='mB')
+ self.assertEquals(elem.property_foo.value,'bar/foo')
+ self.assertEquals(elem.property_bar.value,'only/bar')
def test_setting_with_min_occurs(self):
elem = model.ConfmlSequenceSetting('foo', minOccurs=1)
@@ -462,9 +766,16 @@
elem.maxOccurs = 20
self.assertEquals(elem.maxOccurs,20)
- def test_create_feature_seq_with_int_bool_settings_access_feature_value_with_property(self):
+ def test_create_feature_seq_with_values(self):
+ import logging
+ logger = logging.getLogger('cone')
+ logger.setLevel(logging.DEBUG)
+ ch = logging.StreamHandler()
+ ch.setLevel(logging.DEBUG)
+ logger.addHandler(ch)
+
config = api.Configuration('foo.confml')
- fea= model.ConfmlSequenceSetting("foo")
+ fea= model.ConfmlSequenceSetting("foo", displayName='TestDisplayName')
fea.add_feature(model.ConfmlIntSetting('child1'))
fea.add_feature(model.ConfmlBooleanSetting('child2'))
fea.add_feature(model.ConfmlSetting('child3'))
@@ -472,26 +783,398 @@
dview = config.get_default_view()
foofea = dview.get_feature('foo')
# Test adding a data row with array
- foofea.set_value([['1','2','3'],
- ['4','5','6'],
- ['7','8','9']
+ foofea.set_value([[1,True,'foo'],
+ [2,False,'bar'],
+ [3,True,'sumthin']
])
- self.assertEquals(foofea.value, [['1','2','3'],
- ['4','5','6'],
- ['7','8','9']
+
+ self.assertEquals(foofea.displayName, 'TestDisplayName')
+ self.assertEquals(foofea.data[0][0].get_original_value(), '1')
+ self.assertEquals(foofea.data[0].get_original_value(), ['1', 'true', 'foo'])
+
+ self.assertEquals(foofea.value, [[1,True,'foo'],
+ [2,False,'bar'],
+ [3,True,'sumthin']
])
- foofea.value = [['1','2','3'],
- ['7','8','9']
+ self.assertEquals(foofea.get_original_value(), [['1','true','foo'],
+ ['2','false','bar'],
+ ['3','true','sumthin']
+ ])
+ self.assertEquals(foofea.data[0].get_original_value(), ['1','true','foo'])
+ self.assertEquals(foofea.data[1].get_original_value(), ['2','false','bar'])
+ self.assertEquals(foofea.data[2].get_original_value(), ['3', 'true', 'sumthin'])
+ self.assertEquals(foofea.child1.get_original_value(), ['1', '2', '3'])
+ self.assertEquals(foofea.child2.get_original_value(), ['true', 'false', 'true'])
+ self.assertEquals(foofea.child3.get_original_value(), ['foo', 'bar', 'sumthin'])
+
+ foofea.value = [[1,True,'foo'],
+ [2,False,'bar']
]
- self.assertEquals(foofea.data[0].value,['1','2','3'])
- self.assertEquals(foofea.data[1].value,['7','8','9'])
- self.assertEquals(foofea.data[1][1].value,'8')
- self.assertEquals(foofea.get_value(), [['1','2','3'],
- ['7','8','9']
+ self.assertEquals(foofea.data[0].value,[1,True,'foo'])
+ self.assertEquals(foofea.data[1].value,[2,False,'bar'])
+ self.assertEquals(foofea.data[1][1].value,False)
+ self.assertEquals(foofea.get_value(), [[1,True,'foo'],
+ [2,False,'bar']
])
- self.assertEquals(foofea.child1.value,['1','7'])
+ self.assertEquals(foofea.child1.value,[1,2])
+
+ def test_sequence_with_mapped_data(self):
+ config = api.Configuration('foo.confml')
+
+ fea = model.ConfmlSequenceSetting("SourceSequence", mapKey='KeySubSetting', mapValue="ValueSubSetting")
+ fea.add_feature(model.ConfmlIntSetting("KeySubSetting"))
+ fea.add_feature(model.ConfmlStringSetting("ValueSubSetting"))
+ config.add_feature(fea)
+
+ fea = model.ConfmlSelectionSetting('TargetSetting')
+ config.add_feature(fea)
+
+ data = api.Data(ref='SourceSequence')
+ data.add(api.Data(ref='KeySubSetting', value='1'))
+ data.add(api.Data(ref='ValueSubSetting', value='Value 1'))
+ config.add_data(data)
+
+ data = api.Data(ref='TargetSetting', map="SourceSequence[@key='1']")
+ config.add_data(data)
+
+ fea = config.get_default_view().get_feature('TargetSetting')
+ self.assertEquals(fea.get_value(), 'Value 1')
+
+ def test_sequence_with_mapped_data_in_sequence(self):
+ config = api.Configuration('foo.confml')
+
+ fea = model.ConfmlSequenceSetting("SourceSequence", mapKey='KeySubSetting', mapValue="ValueSubSetting")
+ fea.add_feature(model.ConfmlIntSetting("KeySubSetting"))
+ fea.add_feature(model.ConfmlStringSetting("ValueSubSetting"))
+ config.add_feature(fea)
+
+ fea = model.ConfmlSequenceSetting('TargetSequence')
+ fea.add_feature(model.ConfmlSelectionSetting("Setting"))
+ config.add_feature(fea)
+
+ data = api.Data(ref='SourceSequence')
+ data.add(api.Data(ref='KeySubSetting', value='1'))
+ data.add(api.Data(ref='ValueSubSetting', value='Value 1'))
+ config.add_data(data)
+
+ data = api.Data(ref='TargetSequence')
+ data.add(api.Data(ref='Setting', map="SourceSequence[@key='1']"))
+ config.add_data(data)
+
+ fea = config.get_default_view().get_feature('TargetSequence')
+ self.assertEquals(fea.get_value(), [['Value 1']])
+
+ def test_sequence_with_multiselection_set_value(self):
+ config = api.Configuration('foo.confml')
+
+ fea = model.ConfmlSequenceSetting("fooseq")
+ fea.add_feature(model.ConfmlMultiSelectionSetting("msel"))
+ config.add_feature(fea)
+
+ dview = config.get_default_view()
+ fea = dview.get_feature(fea.fqr)
+ self.assertEquals(fea.value, [])
+
+ def check_data_elements(expected_data_object_values):
+ actual = []
+ for d in config._traverse(type=api.Data):
+ actual.append((d.fqr, d.value, d.empty))
+ expected = []
+ for fqr, val, empty in expected_data_object_values:
+ expected.append((fqr, val, empty))
+ self.assertEquals(actual, expected)
+
+ fea.value = []
+ self.assertEquals(fea.value, [])
+ check_data_elements(
+ [('fooseq', None, False),])
+
+ fea.value = [[()]]
+ self.assertEquals(fea.value, [[()]])
+ check_data_elements(
+ [('fooseq', None, False),
+ ('fooseq.msel', None, True),])
+
+ fea.value = [[('x',)]]
+ self.assertEquals(fea.value, [[('x',)]])
+ check_data_elements(
+ [('fooseq', None, False),
+ ('fooseq.msel', 'x', False),])
+
+ fea.value = [[('x',)], [('y',)]]
+ self.assertEquals(fea.value, [[('x',)], [('y',)]])
+ check_data_elements(
+ [('fooseq', None, False),
+ ('fooseq.msel', 'x', False),
+ ('fooseq', None, False),
+ ('fooseq.msel', 'y', False),])
+
+ fea.value = [[('x', 'y')],
+ [('a', 'b', 'c')],
+ [()],
+ [('d', 'e', 'f')]]
+ self.assertEquals(fea.value, [[('x', 'y')],
+ [('a', 'b', 'c')],
+ [()],
+ [('d', 'e', 'f')]])
+ check_data_elements(
+ [('fooseq', None, False),
+ ('fooseq.msel', 'x', False),
+ ('fooseq.msel', 'y', False),
+ ('fooseq', None, False),
+ ('fooseq.msel', 'a', False),
+ ('fooseq.msel', 'b', False),
+ ('fooseq.msel', 'c', False),
+ ('fooseq', None, False),
+ ('fooseq.msel', None, True),
+ ('fooseq', None, False),
+ ('fooseq.msel', 'd', False),
+ ('fooseq.msel', 'e', False),
+ ('fooseq.msel', 'f', False),])
+
+ def test_sequence_with_multiselection_get_value(self):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlSequenceSetting("fooseq")
+ fea.add_feature(model.ConfmlMultiSelectionSetting("msel"))
+ config.add_feature(fea)
+
+ seqdata1 = api.Data(ref='fooseq')
+ seqdata1._add([api.Data(ref='msel', value='x'),
+ api.Data(ref='msel', value='y')])
+ seqdata2 = api.Data(ref='fooseq')
+ seqdata2._add([api.Data(ref='msel', empty=True)])
+ seqdata3 = api.Data(ref='fooseq')
+ seqdata3._add([api.Data(ref='msel', value='a'),
+ api.Data(ref='msel', value='b'),
+ api.Data(ref='msel', value='c')])
+ config.add_data([seqdata1, seqdata2, seqdata3])
+
+ dview = config.get_default_view()
+ fea = dview.get_feature(fea.fqr)
+ self.assertEquals(fea.value, [[('x', 'y')], [()], [('a', 'b', 'c')]])
+
+ def test_simple_name_id_mapping(self):
+ config = api.Configuration('foo.confml')
+ seq = model.ConfmlSequenceSetting('seq', mapKey='strsub', mapValue='strsub')
+ seq.add_feature(model.ConfmlStringSetting('strsub'))
+ seq.add_feature(model.ConfmlIntSetting('intsub'))
+ seq.add_feature(model.ConfmlRealSetting('realsub'))
+ seq.add_feature(model.ConfmlBooleanSetting('boolsub'))
+ config.add_feature(seq)
+ config.add_feature(api.Feature('target'))
+
+ config.add_data(api.Data(fqr='seq.strsub', value='foo'))
+ config.add_data(api.Data(fqr='seq.intsub', value='123'))
+ config.add_data(api.Data(fqr='seq.realsub', value='1.5'))
+ config.add_data(api.Data(fqr='seq.boolsub', value='true'))
+ config.add_data(api.Data(fqr='target', map="seq[@key='foo']"))
+
+ fea = config.get_default_view().get_feature('target')
+ self.assertEquals(fea.value, 'foo')
+ self.assertEquals(fea.get_original_value(), 'foo')
+
+ seq.mapValue = 'intsub'
+ self.assertEquals(fea.value, 123)
+ self.assertEquals(fea.get_original_value(), '123')
+
+ seq.mapValue = 'realsub'
+ self.assertEquals(fea.value, 1.5)
+ self.assertEquals(fea.get_original_value(), '1.5')
+
+ seq.mapValue = 'boolsub'
+ self.assertEquals(fea.value, True)
+ self.assertEquals(fea.get_original_value(), 'true')
+
+ def test_simple_name_id_mapping_with_multiselection(self):
+ config = api.Configuration('foo.confml')
+ seq = model.ConfmlSequenceSetting('seq', mapKey='strsub', mapValue='intsub')
+ seq.add_feature(model.ConfmlStringSetting('strsub'))
+ seq.add_feature(model.ConfmlIntSetting('intsub'))
+ config.add_feature(seq)
+ config.add_feature(model.ConfmlMultiSelectionSetting('target'))
+
+ d = api.Data(fqr='seq')
+ d.add(api.Data(ref='strsub', value='foo'))
+ d.add(api.Data(ref='intsub', value='123'))
+ config.add_data(d, api.container.APPEND)
+
+ d = api.Data(fqr='seq')
+ d.add(api.Data(ref='strsub', value='bar'))
+ d.add(api.Data(ref='intsub', value='321'))
+ config.add_data(d, api.container.APPEND)
+
+ d = api.Data(fqr='seq')
+ d.add(api.Data(ref='strsub', value='baz'))
+ d.add(api.Data(ref='intsub', value='456'))
+ config.add_data(d, api.container.APPEND)
+
+ config.add_data([api.Data(fqr='target', map="seq[@key='bar']"),
+ api.Data(ref='target', map="seq[@key='baz']"),
+ api.Data(ref='target', map="seq[@key='foo']")])
+
+ fea = config.get_default_view().get_feature('target')
+ self.assertEquals(fea.value, (321, 456, 123))
+ self.assertEquals(fea.get_original_value(), ('321', '456', '123'))
+
+ def test_simple_name_id_mapping_with_file_and_folder_setting(self):
+ def _run_test(subsetting_class):
+ config = api.Configuration('foo.confml')
+ seq = model.ConfmlSequenceSetting('seq')
+ seq.add_feature(subsetting_class('filefoldersub'))
+ config.add_feature(seq)
+ config.add_feature(model.ConfmlSelectionSetting('target'))
+
+ def _add_seq_data(local_path, target_path):
+ d = api.Data(fqr='seq')
+ subd = api.Data(ref='filefoldersub')
+ subd.add(api.Data(ref='localPath', value=local_path))
+ subd.add(api.Data(ref='targetPath', value=target_path))
+ d.add(subd)
+ config.add_data(d, api.container.APPEND)
+ _add_seq_data('local/path/1', 'target/path/1')
+ _add_seq_data('local/path/2', 'target/path/2')
+ _add_seq_data('local/path/3', 'target/path/3')
+ target_data = api.Data(fqr='target')
+ config.add_data(target_data)
+
+ fea = config.get_default_view().get_feature('target')
+
+ seq.mapKey = 'filefoldersub'
+ seq.mapValue = 'filefoldersub'
+ target_data.map = "seq[@key='local/path/1']"
+ self.assertEquals(fea.value, 'local/path/1')
+
+ seq.mapKey = 'filefoldersub/localPath'
+ seq.mapValue = 'filefoldersub/localPath'
+ target_data.map = "seq[@key='local/path/1']"
+ self.assertEquals(fea.value, 'local/path/1')
+
+ seq.mapKey = 'filefoldersub/targetPath'
+ seq.mapValue = 'filefoldersub/targetPath'
+ target_data.map = "seq[@key='target/path/2']"
+ self.assertEquals(fea.value, 'target/path/2')
+
+ seq.mapKey = 'filefoldersub/localPath'
+ seq.mapValue = 'filefoldersub/targetPath'
+ target_data.map = "seq[@key='local/path/3']"
+ self.assertEquals(fea.value, 'target/path/3')
+
+ _run_test(subsetting_class=model.ConfmlFileSetting)
+ _run_test(subsetting_class=model.ConfmlFolderSetting)
+
+ def test_simple_name_id_mapping_override_map_value_in_option(self):
+ config = api.Configuration('foo.confml')
+ fea = model.ConfmlFeature('fea')
+ config.add_feature(fea)
+ seq = model.ConfmlSequenceSetting('seq', mapKey='strsub', mapValue='strsub')
+ seq.add_feature(model.ConfmlStringSetting('strsub'))
+ seq.add_feature(model.ConfmlIntSetting('intsub'))
+ fea.add_feature(seq)
+ target = api.Feature('target')
+ target.add_option(api.Option(None, None, map='fea/seq', map_value='intsub'))
+ fea.add_feature(target)
+
+ config.add_data(api.Data(fqr='fea.seq.strsub', value='foo'))
+ config.add_data(api.Data(fqr='fea.seq.intsub', value='123'))
+ config.add_data(api.Data(fqr='fea.target', map="fea/seq[@key='foo']"))
+
+ fea = config.get_default_view().get_feature('fea.target')
+ self.assertEquals(fea.value, 123)
+ self.assertEquals(fea.get_original_value(), '123')
+
+ def _assert_raises(self, exception_class, func, *args, **kwargs):
+ try:
+ func(*args, **kwargs)
+ self.fail("No exception raised")
+ except exception_class, e:
+ return e
+
+ def test_name_id_mapping_errors(self):
+ config = api.Configuration('foo.confml')
+ seq = model.ConfmlSequenceSetting('seq')
+ seq.add_feature(model.ConfmlStringSetting('strsub'))
+ seq.add_feature(model.ConfmlIntSetting('intsub'))
+ config.add_feature(seq)
+
+ config.add_feature(model.ConfmlIntSetting('foosetting'), 'foofea')
+
+ target = api.Feature('target')
+ target_option = api.Option(None, None, map='seq')
+ target.add_option(target_option)
+ config.add_feature(target)
+
+ config.add_data(api.Data(fqr='seq.strsub', value='foo'))
+ config.add_data(api.Data(fqr='seq.intsub', value='123'))
+ target_data = api.Data(fqr='target', map="seq[@key='123']")
+ config.add_data(target_data)
+
+ fea = config.get_default_view().get_feature('target')
+
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Source sequence 'seq' must have both mapKey and mapValue specified")
+
+ seq.mapKey = 'strsub'
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Source sequence 'seq' must have both mapKey and mapValue specified")
+
+ seq.mapKey = None
+ seq.mapValue = 'strsub'
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Source sequence 'seq' must have both mapKey and mapValue specified")
+
+ seq.mapKey = 'intsub'
+ seq.mapValue = 'strsub'
+
+ target_data.map = "foobar"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Malformed mapping expression: foobar")
+
+ target_data.map = "foo/bar[key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Malformed mapping expression: foo/bar[key='321']")
+
+ target_data.map = "foo/bar[@key='321'"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Malformed mapping expression: foo/bar[@key='321'")
+
+ target_data.map = "foo/nonexistent[@key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Mapping source sequence 'foo.nonexistent' does not exist")
+
+ target_data.map = "foofea/foosetting[@key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Mapping source setting 'foofea.foosetting' is not a sequence setting")
+
+ target_data.map = "seq[@key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "No item-setting in source sequence 'seq' matches key '321'")
+
+ seq.mapKey = 'foo'
+ target_data.map = "seq[@key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Invalid mapKey in source sequence 'seq': no sub-setting with ref 'foo'")
+
+ seq.mapKey = 'intsub'
+ seq.mapValue = 'foo'
+ target_data.map = "seq[@key='321']"
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Invalid mapValue in source sequence 'seq': no sub-setting with ref 'foo'")
+
+ seq.mapValue = 'strsub'
+ target_data.map = "seq[@key='123']"
+ target_option.map_value = 'foobar'
+ e = self._assert_raises(exceptions.NameIdMappingError, fea.get_value)
+ self.assertEquals(str(e), "Invalid mapValue override in option: sub-setting 'foobar' does not exist under source sequence 'seq'")
+
+ # Test successful mapping for good measure
+ seq.mapKey = 'intsub'
+ seq.mapValue = 'strsub'
+ target_data.map = "seq[@key='123']"
+ target_option.map_value = 'intsub'
+ self.assertEquals(fea.get_value(), 123)
+ self.assertEquals(fea.get_original_value(), '123')
class TestConfmlFile(unittest.TestCase):
def test_create_localpath_elem(self):
@@ -511,6 +1194,8 @@
self.assertEquals(elem.list_features(), ['localPath','targetPath'])
self.assertEquals(elem.get_feature('localPath').fqr, 'test.localPath')
self.assertEquals(elem.get_feature('targetPath').fqr, 'test.targetPath')
+ self.assertEquals(elem.get_feature('localPath').name, 'localPath')
+ self.assertEquals(elem.get_feature('targetPath').name, 'targetPath')
def test_create_file_elem_and_set_value(self):
config = api.Configuration('test.confml')
@@ -529,6 +1214,31 @@
elem2 = elem1._clone(recursion=True)
+ def test_create_file_elem_to_a_sequence(self):
+ config = model.ConfmlConfiguration('foo.confml')
+ seq = model.ConfmlSequenceSetting('foo')
+ elem = model.ConfmlFileSetting('test')
+ seq.add_feature(elem)
+ config.add_feature(seq)
+ seq.value = [[['local file', 'targetfile']],
+ [['local file2', 'targetfile2']]]
+
+ self.assertEquals(seq.test.localPath.get_value(), ['local file',
+ 'local file2'])
+
+ def test_create_folder_elem_to_a_sequence(self):
+ config = model.ConfmlConfiguration('foo.confml')
+ seq = model.ConfmlSequenceSetting('foo')
+ elem = model.ConfmlFolderSetting('test')
+ seq.add_feature(elem)
+ config.add_feature(seq)
+ seq.value = [[['local file', 'targetfile']],
+ [['local file2', 'targetfile2']]]
+
+ self.assertEquals(seq.test.localPath.get_value(), ['local file',
+ 'local file2'])
+
+
class TestConfmlIcon(unittest.TestCase):
def test_create_icon(self):
icon = model.ConfmlIcon("test/foo/bar.jpg")
@@ -545,24 +1255,72 @@
class TestLengths(unittest.TestCase):
def test_create_maxLength(self):
max = model.ConfmlMaxLength('100')
- self.assertEquals(max.value, '100')
-
+ self.assertEquals(max.value, 100)
+ max.value = 10
+ self.assertEquals(max.value, 10)
+ max.value = '1000'
+ self.assertEquals(max.value, 1000)
+
def test_create_minLength(self):
min = model.ConfmlMinLength('100')
- self.assertEquals(min.value, '100')
+ self.assertEquals(min.value, 100)
+ min.value = 10
+ self.assertEquals(min.value, 10)
+ min.value = '1000'
+ self.assertEquals(min.value, 1000)
+
+ def test_create_length(self):
+ len = model.ConfmlLength('100')
+ self.assertEquals(len.value, 100)
+ len.value = 10
+ self.assertEquals(len.value, 10)
+ len.value = '1000'
+ self.assertEquals(len.value, 1000)
class TestConfmlFacets(unittest.TestCase):
+ def test_numeric_base_classs(self):
+ numeric = model.ConfmlNumericValue()
+ numeric.value = 3
+ self.assertEquals(numeric.value, 3)
+ numeric.value = 0.3
+ self.assertEquals(numeric.value, 0.3)
+ numeric.value = '22'
+ self.assertEquals(numeric.value, 22)
+ numeric.value = '0.1'
+ self.assertEquals(numeric.value, 0.1)
+ try:
+ numeric.value = 'foo'
+ self.fail("setting string to float property succeeded!")
+ except ValueError:
+ pass
+
def test_create_inclusive(self):
min = model.ConfmlMinInclusive('-10')
max = model.ConfmlMaxInclusive('10')
- self.assertEquals(min.value, '-10')
- self.assertEquals(max.value, '10')
+ self.assertEquals(min.value, -10)
+ self.assertEquals(max.value, 10)
+ min.value = 10
+ self.assertEquals(min.value, 10)
+ min.value = '1000'
+ self.assertEquals(min.value, 1000)
+ max.value = 10
+ self.assertEquals(max.value, 10)
+ max.value = '1000'
+ self.assertEquals(max.value, 1000)
def test_create_exclusive(self):
min = model.ConfmlMinExclusive('0')
max = model.ConfmlMaxExclusive("9")
- self.assertEquals(min.value, '0')
- self.assertEquals(max.value, '9')
+ self.assertEquals(min.value, 0)
+ self.assertEquals(max.value, 9)
+ max.value = 10
+ self.assertEquals(max.value, 10)
+ max.value = '1000'
+ self.assertEquals(max.value, 1000)
+ min.value = 10
+ self.assertEquals(min.value, 10)
+ min.value = '1000'
+ self.assertEquals(min.value, 1000)
def test_create_pattern(self):
pattern = model.ConfmlPattern("[a-zA-Z]")
@@ -570,7 +1328,11 @@
def test_create_totalDigits(self):
digits = model.ConfmlTotalDigits("3")
- self.assertEquals(digits.value, '3')
+ self.assertEquals(digits.value, 3)
+ digits.value = 10
+ self.assertEquals(digits.value, 10)
+ digits.value = '1000'
+ self.assertEquals(digits.value, 1000)
class TestConfmlConfiguration(unittest.TestCase):
def test_create_configuration(self):
@@ -581,14 +1343,24 @@
self.assertEquals(config.ref, 'test__foo__bar_jpg')
self.assertEquals(config.path, 'test/foo/bar.jpg')
-# def test_configuration_access_meta(self):
-# config = model.ConfmlConfiguration("test/foo/bar.jpg", meta={'test':'foo','bar':' hd dd'})
-# self.assertEquals(config.meta.dict, {'test':'foo','bar':' hd dd'})
-# self.assertEquals(config.meta['test'],'foo')
-# config.meta = {'test':'123'}
-# self.assertEquals(config.meta['test'],'123')
-# del config.meta
-# self.assertEquals(config.meta, None)
+ def test_create_configuration_and_features(self):
+ conf = model.ConfmlConfiguration("simple.confml")
+ fea = conf.create_feature("test")
+ self.assertTrue(isinstance(fea, model.ConfmlFeature))
+ self.assertEquals(conf.get_feature('test'), fea)
+ fea = conf.create_feature("test1", name="test name")
+ self.assertEquals(conf.get_feature('test1').name, 'test name')
+ subfea = fea.create_feature("subfea", name="subfea name")
+ self.assertTrue(isinstance(subfea, model.ConfmlSetting))
+ self.assertEquals(conf.list_all_features(), ['test','test1','test1.subfea'])
+
+ def test_configuration_get_default_view(self):
+ config = model.ConfmlConfiguration("test/foo/bar.jpg")
+ config.add_feature(model.ConfmlFeature("test"))
+ view = config.create_view("testview")
+ group = view.create_group("group1")
+ group.create_featurelink("test")
+ self.assertEquals(config.list_all_features(), ['test'])
def test_configuration_access_desc(self):
config = model.ConfmlConfiguration("test/foo/bar.jpg", desc="testing description")
@@ -598,14 +1370,107 @@
del config.desc
self.assertEquals(config.desc, None)
-class TestConfmlProperty(unittest.TestCase):
- def test_create_property(self):
- property = model.ConfmlProperty(name='test',value='foo', unit='kB')
- self.assertEquals(property.name, 'test')
- self.assertEquals(property.value, 'foo')
- self.assertEquals(property.unit, 'kB')
- property.name = 'testnew'
- property.value = 'foo faa'
- self.assertEquals(property.name, 'testnew')
- self.assertEquals(property.value, 'foo faa')
-
\ No newline at end of file
+ def test_use_create_configuration(self):
+ config = model.ConfmlConfiguration("test/foo/bar.jpg")
+ subconfig = config.create_configuration("sub/jee.confml")
+ self.assertEquals(subconfig.get_full_path(),'test/foo/sub/jee.confml')
+ self.assertTrue(isinstance(subconfig,model.ConfmlConfiguration))
+
+
+class TestConfmlView(unittest.TestCase):
+ def test_create_view(self):
+ view = model.ConfmlView("test", id="test")
+ self.assertTrue(view)
+ self.assertEquals(view.get_ref(),'test')
+ self.assertEquals(view.id,"test")
+
+ def test_create_view_with_create_view(self):
+ config = model.ConfmlConfiguration("test")
+ view = config.create_view("test")
+ group = view.create_group("group1")
+ fl = group.create_featurelink("intset1")
+ self.assertTrue(isinstance(view, model.ConfmlView))
+ self.assertTrue(isinstance(group, model.ConfmlGroup))
+ self.assertTrue(isinstance(fl, model.ConfmlFeatureLink))
+
+ def test_create_confml_featurelink(self):
+ fealink = model.ConfmlFeatureLink("test")
+ self.assertTrue(fealink)
+ self.assertEquals(fealink.get_ref(),'link_test')
+
+ def test_create_confml_featurelink_with_overrides(self):
+ fealink = model.ConfmlFeatureLink("test")
+ fealink.desc = "test desc"
+ self.assertEquals(fealink.desc,'test desc')
+ self.assertEquals(fealink._has('_desc'),True)
+ self.assertEquals(fealink.get_attributes(),{'properties': {},'options': {}, 'desc' : 'test desc'})
+
+ def test_create_confml_featurelink_with_option_overrides(self):
+ fealink = model.ConfmlFeatureLink("test")
+ fealink.add(api.Option('opt2', '2'))
+ self.assertEquals(fealink.options['2'].name,'opt2')
+
+ def test_create_view_with_groups(self):
+ view = model.ConfmlView("test")
+ view.create_group("group1")
+ view.create_group("group2")
+ self.assertEquals(view.list_groups(),['group1','group2'])
+
+ def test_create_configuration_with_featurelinks(self):
+ config = model.ConfmlConfiguration("test")
+ config.add_feature(model.ConfmlFeature("fea1", name="Feature 1"))
+ intset1 = model.ConfmlIntSetting("intset1", name="Setting 1")
+ intset1.desc = "int setting desc"
+ config.add_feature(intset1, "fea1")
+
+ view = config.create_view("test")
+ group = view.create_group("group1")
+ fl = group.create_featurelink("intset1")
+ self.assertTrue(isinstance(fl, model.ConfmlFeatureLink))
+ self.assertTrue(len(config.get_default_view().get_features('**')), 2)
+
+
+ def test_create_configuration_with_view_and_featurelink_overrides(self):
+ config = model.ConfmlConfiguration("test")
+ config.add_feature(model.ConfmlFeature("fea1", name="Feature 1"))
+ intset1 = model.ConfmlIntSetting("intset1", name="Setting 1")
+ intset1.desc = "int setting desc"
+ config.add_feature(intset1, "fea1")
+
+ view = config.create_view("test")
+ view.create_group("group1")
+ fl = model.ConfmlFeatureLink("fea1.intset1", name="override name")
+ fl.desc = "override desc"
+ fl.minLength = 2
+ fl.maxLength = 10
+ fl.minOccurs = 2
+ fl.maxOccurs = 10
+
+ fl.pattern = '^.*@.*$'
+ fl.totalDigits = 10
+ fl.minInclusive = 0
+ fl.maxInclusive = 10
+ fl.minExclusive = 0
+ fl.maxExclusive = 10
+
+ fl.add(api.Option('opt1', '1'))
+
+ view.get_group('group1').add(fl)
+ view.populate()
+ self.assertEquals(view.list_all_features(),['group1.proxy_fea1_intset1'])
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').desc, "override desc")
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').name, "override name")
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').minLength, 2)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').maxLength, 10)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').minOccurs, 2)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').maxOccurs, 10)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').pattern, '^.*@.*$')
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').totalDigits, 10)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').minInclusive, 0)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').maxInclusive, 10)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').minExclusive, 0)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').maxExclusive, 10)
+ self.assertEquals(view.get_feature('group1.proxy_fea1_intset1').options['1'].name,'opt1')
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/confml/tests/unittest_persistentconfml.py
--- a/configurationengine/source/cone/confml/tests/unittest_persistentconfml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/confml/tests/unittest_persistentconfml.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,28 +19,18 @@
"""
import unittest
-import string
-import sys
import os
import shutil
-import __init__
-try:
- from cElementTree import ElementTree
-except ImportError:
- try:
- from elementtree import ElementTree
- except ImportError:
- try:
- from xml.etree import cElementTree as ElementTree
- except ImportError:
- from xml.etree import ElementTree
+
-from cone.public import api, exceptions, persistence
+from cone.public import api, persistence, utils
from cone.storage import filestorage
-from cone.confml import persistentconfml, model
+from cone.confml import persistentconfml, model, confmltree
from testautomation.base_testcase import BaseTestCase
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+ElementTree = utils.etree
+
testdata = os.path.join(ROOT_PATH,'data')
simplerootxml = \
@@ -65,7 +55,7 @@
morestuff='''
-
+
@@ -201,15 +191,239 @@
Image creation related settings
-
+ Sample Description
-
+
+
+
+
'''
+overrideview = \
+'''
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ myProduct
+ myProduct
+
+
+
+ Image creation related settings
+
+ Sample Description
+
+
+
+
+ test desc override
+
+
+
+
+
+
+'''
+
+
+option_overrideview = \
+'''
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ myProduct
+ myProduct
+
+
+
+ Image creation related settings
+
+ Sample Description
+
+
+
+
+
+ test desc override
+
+
+
+
+
+
+'''
+
+properties_overrideview = \
+'''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ myProduct
+ myProduct
+
+
+
+ Image creation related settings
+
+ Sample Description
+
+
+
+
+
+ test desc override
+
+
+
+
+
+
+'''
+
+selectionsetting = \
+'''
+GPRS connection method (CM) definitions
+
+
+ The access point name for this GPRS connection
+
+
+ The access point name that is visible to the user.
+
+
+ Select destination network for access point
+
+
+
+
+
+ Addressing that the network uses.
+
+
+
+
+
+
+
+ Confirm the internet access from user?
+
+
+
+
+
+
+
+
+ Internet
+ IPv4
+
+
+ Operator 1
+ Operator Internet
+ Internet
+ IPv4
+
+
+ Test
+ Test Connection
+ Internet
+ IPv4
+
+
+
+ true
+
+
+
+
+'''
+
+multiselection = \
+'''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+ foo
+ Real data is here!
+
+
+ 34
+ bar
+ I am not FOO!
+
+
+ 0
+
+
+
+
+
+
+
+'''
+
class TestModuleGetters(unittest.TestCase):
def test_get_reader_for_configuration(self):
confread = persistentconfml.get_reader_for_elem("configuration")
@@ -240,11 +454,16 @@
elem = ElementTree.fromstring(dump)
self.assertEquals(elem.get('name'),"test_confml")
-class TestConfigurationParser(unittest.TestCase):
+class TestConfigurationParser(unittest.TestCase):
+ def tearDown(self):
+ if os.path.exists(os.path.join(ROOT_PATH,'temp')):
+ shutil.rmtree(os.path.join(ROOT_PATH,'temp'))
+
def test_load_simple(self):
reader = persistentconfml.get_reader_for_elem("configuration")
obj = reader.loads(ElementTree.fromstring(simplerootxml))
self.assertEquals(obj.get_ref(),'simple')
+ self.assertEquals(obj.id,None)
self.assertEquals(obj._list(),['platform__s60__confml__test_confml'])
def test_load_new_include_confml(self):
@@ -263,6 +482,7 @@
def test_load_morestuff(self):
reader = persistentconfml.get_reader_for_elem("configuration")
obj = reader.loads(ElementTree.fromstring(morestuff))
+ self.assertEquals(obj.id, "conf_id")
self.assertEquals(obj._list(),['_meta','_desc','platform__s60__confml__root_confml', 'ncp11__confml__jallaa_confml', 'ncp11__prodX__confml__root_confml', 'regional__japan__confml__root_confml'])
met = obj.meta
self.assertEquals(obj.meta[2].value,'Variant1 creator')
@@ -311,8 +531,8 @@
self.assertEquals(obj.get_feature('CVC_OperatorMenu.CVC_OperatorMenuIconFile.localPath').get_value(),'UI/Customer Menu/Cache')
def test_create_features_with_rfs_data_and_dump_and_load(self):
- conf = api.Configuration("foo/foo.confml")
- conf.add_feature(api.Feature('feature1'))
+ conf = api.Configuration("foo/foo.confml", id="foo_conf")
+ conf.add_feature(api.Feature('feature1', id="feature1_id"))
conf.add_feature(api.Feature('child1'),'feature1')
conf.add_feature(api.Feature('child2'),'feature1')
conf.add_feature(api.Feature('child3'),'feature1')
@@ -326,11 +546,59 @@
dumped = persistentconfml.dumps(conf)
conf2 = persistentconfml.loads(dumped)
+ self.assertEquals(conf2.id, "foo_conf")
dview = conf2.get_default_view()
+ self.assertEquals(dview.get_feature('feature1').id, "feature1_id")
+ self.assertEquals(dview.get_feature('feature1.child1').id, None)
self.assertEquals(dview.get_feature('feature1.child1').get_value(), None)
self.assertEquals(dview.get_feature('feature1.child1').get_value('rfs'), 'true')
self.assertEquals(dview.get_feature('feature1.child2').get_value('rfs'), 'false')
+ def test_create_confml_features_and_dump_and_load(self):
+ conf = model.ConfmlConfiguration("foo/foo.confml", id="foo_conf")
+ fea = conf.create_feature('feature1', id="feature1_id")
+ fea.add_feature(model.ConfmlBooleanSetting("boolset", id="bool", name="testname", desc="desriptions"))
+ fea.add_feature(model.ConfmlIntSetting("intset", id="int"))
+ fea.add_feature(model.ConfmlStringSetting("stringset", id="string"))
+ fea.add_feature(model.ConfmlSelectionSetting("selset", id="sel"))
+ fea.add_feature(model.ConfmlSequenceSetting("seqset", id="seq"))
+ fea.add_feature(model.ConfmlFileSetting("fileset", id="file", desc="testdesc"))
+
+ dumped = persistentconfml.dumps(conf)
+ conf2 = persistentconfml.loads(dumped)
+ self.assertEquals(conf2.id, "foo_conf")
+ dview = conf2.get_default_view()
+ self.assertEquals(dview.get_feature('feature1').id, "feature1_id")
+ self.assertEquals(dview.get_feature('feature1.boolset').id, "bool")
+ self.assertEquals(dview.get_feature('feature1.boolset').desc, "desriptions")
+ self.assertEquals(dview.get_feature('feature1.intset').id, "int")
+ self.assertEquals(dview.get_feature('feature1.stringset').id, "string")
+ self.assertEquals(dview.get_feature('feature1.selset').id, "sel")
+ self.assertEquals(dview.get_feature('feature1.seqset').id, "seq")
+ self.assertEquals(dview.get_feature('feature1.fileset').id, "file")
+ self.assertEquals(dview.get_feature('feature1.fileset').desc, "testdesc")
+
+ def test_create_confml_view_and_dump_and_load(self):
+ conf = model.ConfmlConfiguration("foo/view.confml", id="view_conf")
+ view = conf.create_view('view1')
+ group1 = view.create_group("group one", id="g1")
+ group2 = view.create_group("group two", id="g2")
+ group2.create_featurelink("test/foo", id="fea1", name="Jee", desc="testdesc", readOnly="true")
+
+ dumped = persistentconfml.dumps(conf)
+ conf2 = persistentconfml.loads(dumped)
+ self.assertEquals(conf2.id, "view_conf")
+ v1 = conf2.get_view('view1')
+ self.assertEquals(v1.name, "view1")
+ self.assertEquals(v1.id, None)
+ self.assertEquals(v1.list_groups(), ['group one', 'group two'])
+ self.assertEquals(v1.get_group('group one').id, "g1")
+ self.assertEquals(v1.get_group('group two').id, "g2")
+ self.assertEquals(v1.get_group('group two').get_featurelink("test/foo").id, "fea1")
+ self.assertEquals(v1.get_group('group two').get_featurelink("test/foo").name, "Jee")
+ self.assertEquals(v1.get_group('group two').get_featurelink("test/foo").desc, "testdesc")
+ self.assertEquals(v1.get_group('group two').get_featurelink("test/foo").readOnly, True)
+
def test_load_actualconfml_test_rfs_settings(self):
reader = persistentconfml.get_reader_for_elem("configuration")
obj = reader.loads(ElementTree.fromstring(actualconfml))
@@ -364,8 +632,8 @@
obj = reader.loads(etree)
dview = obj.get_default_view()
dnsfea = dview.get_feature('DNs.DN')
- self.assertEquals(dnsfea.list_features(),['Name', 'DNId', 'Metadata', 'Protection', 'Hidden', 'HiddenAgent', 'Highlighted', 'Icon', 'EmbeddedDN', 'IAP', 'IAP2', 'IAP3', 'IAP4', 'IAP5', 'IAP6', 'IAP7', 'IAP8', 'IAP9', 'IAP10'])
- self.assertEquals(dnsfea.get_template(),['User Defined', '0', 'No', 'No', 'No', '11', None, None, None, None, None, None, None, None, None, None, None, None, None])
+ self.assertEquals(dnsfea.list_features(),['Name', 'DNId', 'Metadata', 'Protection', 'Hidden', 'HiddenAgent', 'Highlighted', 'Icon', 'EmbeddedDN', 'IAP', 'IAP2', 'IAP3', 'IAP4', 'IAP5', 'IAP6', 'IAP7', 'IAP8', 'IAP9', 'IAP10'])
+ self.assertEquals(dnsfea.get_template(), [None, None, 'User Defined', '0', 'No', 'No', 'No', '11', None, None, None, None, None, None, None, None, None, None, None])
self.assertEquals(dnsfea.get_value(),
[['Internet', '1', 'Internet', '2', 'No', 'No', 'Yes', '0', None, None, None, None, None, None, None, None, None, None, None],
['MMS', '2', 'MMS', '2', 'No', 'Yes', 'No', '2', None, None, None, None, None, None, None, None, None, None, None],
@@ -389,9 +657,8 @@
config = p.get_configuration('multiselection.confml')
dview = config.get_default_view()
multisel1 = dview.get_feature('MultiSelections.MultiSel1')
- self.assertEquals(multisel1.value,["first selection","second selection"])
- self.assertEquals(multisel1.get_data_cast(multisel1.get_value()),["first selection","second selection"])
- self.assertEquals(multisel1.get_value(),["first selection","second selection"])
+ self.assertEquals(multisel1.value,("first selection","second selection"))
+ self.assertEquals(multisel1.get_value(),("first selection","second selection"))
self.assertEquals(multisel1.get_data().get_value(),'"first selection" "second selection"')
@@ -401,20 +668,20 @@
config = p.get_configuration('multiselection.confml')
dview = config.get_default_view()
multisel1 = dview.get_feature('uda_selection.selectedfiles')
- self.assertEquals(multisel1.get_value(),None)
+ self.assertEquals(multisel1.get_value(), ())
self.assertEquals(multisel1.get_data().get_value(),None)
def test_add_sequence_data_to_separate_confml(self):
- prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'data'),"w"))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp'),"w"))
config = prj.create_configuration('test2.confml')
seqconfig = config.create_configuration('sequence.confml')
config.create_configuration('testdata.confml')
seqconfig.add_feature(api.FeatureSequence('feature1'))
- seqconfig.add_feature(api.Feature('child1'),'feature1')
- seqconfig.add_feature(api.Feature('child2'),'feature1')
- seqconfig.add_feature(api.Feature('child3'),'feature1')
+ seqconfig.add_feature(api.Feature('child1', name="child1"),'feature1')
+ seqconfig.add_feature(api.Feature('child2', name="child2"),'feature1')
+ seqconfig.add_feature(api.Feature('child3', name="child3"),'feature1')
dview = config.get_default_view()
self.assertEquals(dview.get_feature('feature1').get_type(),'sequence')
dview.get_feature('feature1').set_template(['c1','c2','c3'])
@@ -426,7 +693,7 @@
dview.get_feature('feature1').get_data()[1].set_value(['row 2 updated', 'foo', '56'])
config.save()
prj.close()
- prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'data')))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp')))
config = prj.get_configuration('test2.confml')
dview = config.get_default_view()
self.assertEquals(dview.get_feature('feature1').get_template(),['c1','c2','c3'])
@@ -440,14 +707,14 @@
def test_add_sequence_data_to_separate_confml_with_append_policy(self):
- prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'data'),"w"))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp'),"w"))
config = prj.create_configuration('test1.confml')
seqconfig = config.create_configuration('sequence.confml')
config.create_configuration('testdata.confml')
seqconfig.add_feature(api.FeatureSequence('feature1'))
- seqconfig.add_feature(api.Feature('child1'),'feature1')
- seqconfig.add_feature(api.Feature('child2'),'feature1')
- seqconfig.add_feature(api.Feature('child3'),'feature1')
+ seqconfig.add_feature(api.Feature('child1', name="child1"),'feature1')
+ seqconfig.add_feature(api.Feature('child2', name="child2"),'feature1')
+ seqconfig.add_feature(api.Feature('child3', name="child3"),'feature1')
dview = config.get_default_view()
self.assertEquals(dview.get_feature('feature1').get_type(),'sequence')
dview.get_feature('feature1').set_template(['c1','c2','c3'])
@@ -459,7 +726,7 @@
dview.get_feature('feature1').get_data()[1].set_value(['row 2 updated', 'foo', '56'])
config.save()
prj.close()
- prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'data')))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp')))
config = prj.get_configuration('test1.confml')
dview = config.get_default_view()
self.assertEquals(dview.get_feature('feature1').get_template(),['c1','c2','c3'])
@@ -475,23 +742,75 @@
reader = persistentconfml.get_reader_for_elem("configuration")
etree = ElementTree.fromstring(simpleview)
obj = reader.loads(etree)
- self.assertEquals(obj.get_name(), 'unknown')
+ self.assertEquals(obj.get_name(), None)
self.assertEquals(obj.list_views(), ['Image creation'])
self.assertEquals(obj.get_view('Image creation').get_name(),'Image creation')
self.assertEquals(obj.get_view('Image creation').desc,'Image creation related settings')
self.assertEquals(obj.get_view('Image creation').list_features(),[])
- self.assertEquals(obj.get_view('Image creation').list_groups(),['Imageproperties'])
- self.assertEquals(obj.get_view('Image creation').list_all_features(),['Imageproperties.imagetype',
- 'Imageproperties.rofs3version',
- 'Imageproperties.productname',
- 'Imageproperties.outputLocation',
- 'Imageproperties.imagetarget'])
- self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties.imagetype').get_value(), '0')
- self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties.rofs3version').get_value(), 'V .50.2009.04.0113 RND')
- self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties.productname').get_value(), 'myProduct')
- self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties.outputLocation').get_value(), 'myProduct')
- self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties.imagetarget').get_value(), '2')
+ self.assertEquals(obj.get_view('Image creation').list_groups(),['Imageproperties _ test'])
+ self.assertEquals(obj.get_view('Image creation').list_all_features(),['Imageproperties _ test.proxy_imakerapi_imagetype',
+ 'Imageproperties _ test.proxy_imakerapi_rofs3version',
+ 'Imageproperties _ test.proxy_imakerapi_productname',
+ 'Imageproperties _ test.proxy_imakerapi_outputLocation',
+ 'Imageproperties _ test.proxy_imaker_imagetarget'])
+ self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties _ test.proxy_imakerapi_imagetype').get_value(), '0')
+ self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties _ test.proxy_imakerapi_rofs3version').get_value(), 'V .50.2009.04.0113 RND')
+ self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties _ test.proxy_imakerapi_productname').get_value(), 'myProduct')
+ self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties _ test.proxy_imakerapi_outputLocation').get_value(), 'myProduct')
+ self.assertEquals(obj.get_view('Image creation').get_feature('Imageproperties _ test.proxy_imaker_imagetarget').get_value(), '2')
+
+ def test_load_view_with_overrides(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ etree = ElementTree.fromstring(overrideview)
+ obj = reader.loads(etree)
+ self.assertEquals(obj.get_name(), None)
+ self.assertEquals(obj.list_views(), ['Image creation'])
+ view = obj.get_view('Image creation')
+ self.assertEquals(view.get_name(),'Image creation')
+ self.assertEquals(view.list_all_features(),['Imageproperties.proxy_imakerapi_imagetype',
+ 'Imageproperties.proxy_imakerapi_productname',
+ 'Imageproperties.proxy_imakerapi_outputLocation'
+ ])
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').name, "New Product Name")
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').desc, "test desc override")
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_outputLocation').minOccurs, 2)
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').minLength, 2)
+
+ def test_load_view_with_option_overrides(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ etree = ElementTree.fromstring(option_overrideview)
+ obj = reader.loads(etree)
+ self.assertEquals(obj.get_name(), None)
+ self.assertEquals(obj.list_views(), ['Image creation'])
+ view = obj.get_view('Image creation')
+ self.assertEquals(view.get_name(),'Image creation')
+ self.assertEquals(view.list_all_features(),['Imageproperties.proxy_imakerapi_imagetype',
+ 'Imageproperties.proxy_imakerapi_productname',
+ 'Imageproperties.proxy_imakerapi_outputLocation'
+ ])
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_option('value_2').get_name(), 'prd2')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').options['2'].get_name(), 'prd2')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').list_options(), ['value_0', 'value_1', 'value_2', 'value_2', 'value_5'])
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_option('value_5').get_value(), '5')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_outputLocation').minOccurs, 2)
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').minLength, 2)
+
+ def test_load_view_with_properties_overrides(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ etree = ElementTree.fromstring(properties_overrideview)
+ obj = reader.loads(etree)
+ view = obj.get_view('Image creation')
+
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_property('mime').get_name(), 'mime')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_property('mime').get_value(), 'image/svgt image/jpg')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_property('mime2').name, 'mime2')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_property('mime2').value, 'image/svgt image/bmp')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').properties['mime'].get_name(), 'mime')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').properties['mime'].get_value(), 'image/svgt image/jpg')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').properties['mime2'].name, 'mime2')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').properties['mime2'].value, 'image/svgt image/bmp')
+
def test_load_cvc_view(self):
prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'data')))
config = prj.get_configuration('cvc_root.confml')
@@ -522,7 +841,7 @@
obj = reader.loads(etree)
fea = obj.get_feature('CVC_StartupAnimationSequence.CVC_StartupAnimationTone')
self.assertEquals(fea.list_properties(),['maxSize'])
- self.assertEquals(fea.properties['maxSize'].value,'100')
+ self.assertEquals(fea.property_maxSize.value,'100')
conffile = open(os.path.join(ROOT_PATH,"data/CVC_Preinstalled.confml"))
reader = persistentconfml.get_reader_for_elem("configuration")
@@ -530,7 +849,7 @@
obj = reader.loads(etree)
fea = obj.get_feature('CVC_PreinstalledContent.CVC_PreInstalledMMSs.CVC_PreInstalledMMS')
self.assertEquals(fea.list_properties(),['maxFileSize'])
- self.assertEquals(fea.properties['maxFileSize'].value,'35')
+ self.assertEquals(fea.property_maxFileSize.value,'35')
def test_load_voicemailbox_confml_from_file(self):
conffile = open(os.path.join(ROOT_PATH,"data/voicemailbox.confml"))
@@ -548,21 +867,55 @@
etree = ElementTree.fromstring(conffile.read())
obj = reader.loads(etree)
setting = obj.get_feature('Facets.MessageSize')
- self.assertEquals(setting.minInclusive,'0')
- self.assertEquals(setting.maxInclusive,'10')
+ self.assertEquals(setting.minInclusive,0)
+ self.assertEquals(setting.maxInclusive,10)
setting = obj.get_feature('Facets.MessageSize2')
- self.assertEquals(setting.minExclusive,'-1')
- self.assertEquals(setting.maxExclusive,'11')
+ self.assertEquals(setting.minExclusive,-1)
+ self.assertEquals(setting.maxExclusive,11)
setting = obj.get_feature('Facets.StringPattern')
self.assertEquals(setting.pattern,"[a-zA-Z]{5,10}")
setting = obj.get_feature('Facets.TotalDigits')
- self.assertEquals(setting.totalDigits,'3')
+ self.assertEquals(setting.totalDigits,3)
dview = obj.get_default_view()
intfea = dview.get_feature('Facets.MessageSize')
self.assertEquals(intfea.type,'int')
self.assertEquals(intfea.value,9)
-
-class TestConfigurationWriter(unittest.TestCase):
+
+ def test_load_sequence_setting_test_confml_from_file(self):
+ conffile = open(os.path.join(ROOT_PATH,"testdata/read_write/sequence_setting_test.confml"))
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ etree = ElementTree.fromstring(conffile.read())
+ obj = reader.loads(etree)
+ dview = obj.get_default_view()
+ fea = dview.get_feature('SequenceSettingTest.SequenceSetting')
+ self.assertEquals(fea.get_template(),
+ [['seq/default_folder', None],
+ '1.0',
+ ['seq/default_file.txt', None],
+ '1',
+ 'template',
+ 'false',
+ '0',
+ '"opt 0"',
+ '2009-02-02',
+ '07:30:15',
+ '2009-02-02-07:00:00',
+ 'P5Y4M3DT12H25M15S'])
+
+ def test_load_selection_with_name_id_mapping(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ obj = reader.loads(ElementTree.fromstring(selectionsetting))
+ self.assertEquals(obj._list(),['CTD_APs',
+ 'TestApplication',
+ 'data'])
+ self.assertEquals(obj.get_data('TestApplication.DefaultAP').get_map(), "CTD_APs/AP[@key='Operator 1']")
+
+ #
+class TestConfigurationWriter(unittest.TestCase):
+ def tearDown(self):
+ if os.path.exists(os.path.join(ROOT_PATH,'temp/configwriter')):
+ shutil.rmtree(os.path.join(ROOT_PATH,'temp/configwriter'))
+
def test_dump_simple_configuration(self):
config = api.Configuration("test.confml")
writer = persistentconfml.get_writer_for_class("Configuration")
@@ -645,12 +998,12 @@
def test_configuration_with_features_and_properties(self):
config = model.ConfmlConfiguration("test.confml")
config.add_feature(model.ConfmlSetting('testfea11'))
- config.testfea11.add_property(name='smaller',value='10')
- config.testfea11.add_property(name='bigger',value='1', unit='B')
+ config.testfea11.create_property(name='smaller',value='10')
+ config.testfea11.create_property(name='bigger',value='1', unit='B')
elem = persistentconfml.dumps(config)
config2 = persistentconfml.loads(elem)
- self.assertEquals(config2.testfea11.properties['smaller'].value,'10')
- self.assertEquals(config2.testfea11.properties['bigger'].value,'1')
+ self.assertEquals(config2.testfea11.property_smaller.value,'10')
+ self.assertEquals(config2.testfea11.property_bigger.value,'1')
def test_configuration_with_features_and_minoccurs(self):
config = model.ConfmlConfiguration("test.confml")
@@ -719,19 +1072,6 @@
self.assertEquals(config2.testfea2.maxLength,None)
self.assertEquals(config2.testfea3.maxLength,100)
- def test_configuration_with_features_and_maxlength(self):
- config = model.ConfmlConfiguration("test.confml")
- config.add_feature(model.ConfmlSetting('testfea1', type='int'))
- config.add_feature(model.ConfmlSetting('testfea2', type='int'))
- config.add_feature(model.ConfmlSetting('testfea3', type='int',minLength=100))
- config.testfea1.minLength = 10
-
- elem = persistentconfml.dumps(config)
- config2 = persistentconfml.loads(elem)
- self.assertEquals(config2.testfea1.minLength,'10')
- self.assertEquals(config2.testfea3.minLength,'100')
- self.assertEquals(config2.testfea2.minLength,None)
-
def test_configuration_with_features(self):
config = model.ConfmlConfiguration("test.confml")
config.add_feature(api.Feature('testfea1'))
@@ -746,7 +1086,7 @@
config.add_feature(api.Feature('testfea5'))
config.add_feature(api.Feature('testfea6'))
set1.set_value('pre')
- config.testfea1.set_value('foo:bar')
+ config.testfea1.testfea11.set_value('foo:bar')
config.testfea4.set_value('4')
writer = persistentconfml.get_writer_for_class("Configuration")
elem = writer.dumps(config)
@@ -777,11 +1117,12 @@
config.add_feature(api.Feature('testfea4'))
config.add_feature(api.Feature('testfea5'))
config.add_feature(api.Feature('testfea6'))
- set1.value = ["pre","post"]
- self.assertEquals(set1.get_data().get_value(), '"pre" "post"')
+ set1.value = ["pre","post"]
+ self.assertEquals(set1.get_datas()[0].get_value(), 'pre')
+ self.assertEquals(set1.get_datas()[1].get_value(), 'post')
writer = persistentconfml.get_writer_for_class("Configuration")
elem = writer.dumps(config)
- self.assertEquals(ElementTree.tostring(elem), '"pre" "post"')
+ self.assertEquals(ElementTree.tostring(elem), 'prepost')
etree = ElementTree.fromstring(ElementTree.tostring(elem))
fea1 = etree.find('{http://www.s60.com/xml/confml/2}feature')
self.assertEquals(fea1.get('ref'),'testfea1')
@@ -789,17 +1130,19 @@
config2 = persistentconfml.get_reader_for_elem('configuration').loads(etree)
self.assertEquals(config2.testfea2.list_features(),['testfea21'])
self.assertEquals(config2.testfea2.testfea21.get_type(),'multiSelection')
- self.assertEquals(config2.testfea2.testfea21.get_value(), ['pre', 'post'])
+ self.assertEquals(config2.testfea2.testfea21.get_value(), ('pre', 'post'))
def test_configuration_with_view(self):
- config = api.Configuration("view.confml")
- config.add_view('testing')
+ config = model.ConfmlConfiguration("view.confml")
+ config.create_view('testing')
view = config.get_view('testing')
- view.add_group('group1')
- view.add_group('group2')
- view.add_group('group3')
- view.group1.add(api.FeatureLink('test.foo'))
- view.group2.add(api.FeatureLink('foo.*'))
+ view.create_group('group1')
+ view.create_group('group2')
+ view.create_group('group3')
+ fl = model.ConfmlFeatureLink('test.foo')
+ fl.desc = "test desc"
+ view.group1.add(fl)
+ view.group2.create_featurelink('foo.*')
writer = persistentconfml.get_writer_for_class("Configuration")
elem = writer.dumps(config)
etree = ElementTree.fromstring(ElementTree.tostring(elem))
@@ -813,36 +1156,57 @@
settings = [elem for elem in etree.getiterator('{http://www.s60.com/xml/confml/2}setting')]
self.assertEquals(settings[0].get('ref'), 'test/foo')
self.assertEquals(settings[1].get('ref'), 'foo/*')
-
- def test_load_dump_reload_configuration_with_view(self):
+
+ def test_load_dump_reload_configuration_with_view_and_overrides(self):
reader = persistentconfml.get_reader_for_elem("configuration")
- etree = ElementTree.fromstring(simpleview)
+ etree = ElementTree.fromstring(overrideview)
obj = reader.loads(etree)
# Getting the view populates it and check that the writing still works
- self.assertEquals(obj.get_view('Image creation').get_name(),'Image creation')
- self.assertEquals(obj.get_view('Image creation').id,'imakerimage')
- self.assertEquals(obj.get_view('Image creation').list_groups(), ['Imageproperties'])
+ view = obj.get_view('Image creation')
+ self.assertEquals(view.get_name(),'Image creation')
+ self.assertEquals(view.id,'imakerimage')
+ self.assertEquals(view.list_groups(), ['Imageproperties'])
+ viewfea = view.get_feature('Imageproperties.proxy_imakerapi_productname')
+ self.assertEquals(viewfea.name, "New Product Name")
writer = persistentconfml.get_writer_for_class("Configuration")
elem = writer.dumps(obj)
# Reload the configuration with view after dumping it to ensure data stays the same
elemstr = ElementTree.tostring(elem)
etree = ElementTree.fromstring(elemstr)
obj = reader.loads(etree)
- self.assertEquals(obj.get_view('Image creation').get_name(),'Image creation')
- self.failUnlessEqual(obj.get_view('Image creation').id,'imakerimage', 'Known bug (#564)')
- self.assertEquals(obj.get_view('Image creation').id,'imakerimage')
+ view = obj.get_view('Image creation')
+ self.assertEquals(view.get_name(),'Image creation')
+ self.failUnlessEqual(view.id,'imakerimage')
+ self.assertEquals(view.id,'imakerimage')
+ # Check that the override parameters are also saved / loaded
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').name, 'New Product Name')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').has_attribute('name'), True)
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').desc, "test desc override")
+
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').get_option('value_2').get_name(), 'prd_renamed')
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_imagetype').list_options(), ['value_0', 'value_1', 'value_2', 'value_2'])
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_outputLocation').minOccurs, 2)
+ fea = view.get_feature('Imageproperties.proxy_imakerapi_outputLocation')
+ self.assertEquals(fea.has_attribute('name'), False)
+
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname').minLength, 2)
+ # check that the original attributes are still valid
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname')._obj.name, "PRODUCT_NAME")
+ self.assertEquals(view.get_feature('Imageproperties.proxy_imakerapi_productname')._obj.desc, None)
def test_load_configuration_and_create_copy_and_dump(self):
conffile = open(os.path.join(ROOT_PATH,"data/commsdatcreator.confml"))
#reader = persistentconfml.get_reader_for_elem("configuration")
#etree = ElementTree.fromstring(conffile.read())
obj = persistentconfml.loads(conffile.read())
- copyconfig = api.Configuration('data/copy_commsdatcreator.confml')
+ copyconfig = api.Configuration('temp/copy_commsdatcreator.confml')
for child in obj._objects():
copyconfig._add(child)
output = persistentconfml.dumps(copyconfig)
- ofile = open(os.path.join(ROOT_PATH,'data/copy_commsdatcreator.confml'),"wb")
+ if not os.path.exists(os.path.join(ROOT_PATH,'temp')):
+ os.mkdir(os.path.join(ROOT_PATH,'temp'))
+ ofile = open(os.path.join(ROOT_PATH,'temp/copy_commsdatcreator.confml'),"wb")
ofile.write(output)
ofile.close()
newconfig = persistentconfml.loads(output)
@@ -856,7 +1220,7 @@
def test_create_configuration_with_meta_and_dump(self):
prj = api.Project(api.Storage.open('dump','w'))
- testconf = prj.create_configuration('test.confml')
+ testconf = prj.create_configuration('test.confml', True)
testconf.include_configuration('test/foo.confml')
testconf.save()
prj.close()
@@ -883,6 +1247,65 @@
prj.close()
shutil.rmtree('dump')
+ def test_write_selection_with_nameid_mapping(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ obj = reader.loads(ElementTree.fromstring(selectionsetting))
+
+ self.assertEquals(obj.get_data('TestApplication.DefaultAP').get_map(), "CTD_APs/AP[@key='Operator 1']")
+ self.assertEquals(obj.get_data('TestApplication.DefaultAP').get_fearef(), "TestApplication.DefaultAP")
+
+ writer = persistentconfml.get_writer_for_class("Configuration")
+ elem = writer.dumps(obj)
+ etree = ElementTree.fromstring(ElementTree.tostring(elem))
+
+ self.assertEquals(
+ etree.find('{http://www.s60.com/xml/confml/2}data')
+ .find('{http://www.s60.com/xml/confml/2}TestApplication')
+ .find('{http://www.s60.com/xml/confml/2}DefaultAP')
+ .get('map'),
+ "CTD_APs/AP[@key='Operator 1']")
+
+ def test_write_multiselection_with_name_id_mapping(self):
+ reader = persistentconfml.get_reader_for_elem("configuration")
+ obj = reader.loads(ElementTree.fromstring(multiselection))
+
+ self.assertEquals(obj.get_data('aFeature.selectionSetting').get_map(), "aFeature/exampleSequence[@key='12']")
+ self.assertEquals(obj.get_data('aFeature.multiselectionSetting')[0].get_value(), '0')
+ self.assertEquals(obj.get_data('aFeature.multiselectionSetting')[1].get_map(), "aFeature/exampleSequence[@key='12']")
+ self.assertEquals(obj.get_data('aFeature.multiselectionSetting')[2].get_map(), "aFeature/exampleSequence[@key='34']")
+ self.assertEquals(obj.get_data('aFeature.multiselectionSettingOverride')[0].get_map(), "aFeature/exampleSequence[@key='12']")
+ self.assertEquals(obj.get_data('aFeature.multiselectionSettingOverride')[1].get_map(), "aFeature/exampleSequence[@key='34']")
+
+ writer = persistentconfml.get_writer_for_class("Configuration")
+ elem = writer.dumps(obj)
+ etree = ElementTree.fromstring(ElementTree.tostring(elem))
+
+ self.assertEquals(
+ etree.find('{http://www.s60.com/xml/confml/2}data')
+ .find('{http://www.s60.com/xml/confml/2}aFeature')
+ .find('{http://www.s60.com/xml/confml/2}selectionSetting')
+ .get('map'), "aFeature/exampleSequence[@key='12']")
+ self.assertEquals(
+ etree.find('{http://www.s60.com/xml/confml/2}data')
+ .find('{http://www.s60.com/xml/confml/2}aFeature')
+ .find('{http://www.s60.com/xml/confml/2}multiselectionSetting')
+ .text, "0")
+
+ mss = []
+ for data_elem in etree.getiterator('{http://www.s60.com/xml/confml/2}data'):
+ for mss_elem in data_elem.getiterator('{http://www.s60.com/xml/confml/2}multiselectionSetting'):
+ mss.append(mss_elem.get('map'))
+
+ self.assertEquals(mss, [None, "aFeature/exampleSequence[@key='12']", "aFeature/exampleSequence[@key='34']"])
+
+ msso = []
+ for data_elem in etree.getiterator('{http://www.s60.com/xml/confml/2}data'):
+ for msso_elem in data_elem.getiterator('{http://www.s60.com/xml/confml/2}multiselectionSettingOverride'):
+ msso.append(msso_elem.get('map'))
+
+ self.assertEquals(msso, ["aFeature/exampleSequence[@key='12']", "aFeature/exampleSequence[@key='34']"])
+
+
class TestMeta(unittest.TestCase):
def test_get_reader_for_meta(self):
reader = persistentconfml.get_reader_for_elem("meta")
@@ -955,7 +1378,7 @@
celem = api.Feature('testing')
etree = writer.dumps(celem)
self.assertEquals(etree.get('ref'),'testing')
- self.assertEquals(etree.get('name'),'testing')
+ self.assertEquals(etree.get('name'), None)
class TestSetting(unittest.TestCase):
@@ -980,7 +1403,7 @@
celem = model.ConfmlSetting('testing')
etree = writer.dumps(celem)
self.assertEquals(etree.get('ref'),'testing')
- self.assertEquals(etree.get('name'),'testing')
+ self.assertEquals(etree.get('name'), None)
self.assertEquals(etree.get('type'),None)
def test_write_setting_with_options(self):
@@ -993,7 +1416,7 @@
etree = writer.dumps(elem)
self.assertEquals(etree.get('ref'),'testing')
- self.assertEquals(etree.get('name'),'testing')
+ self.assertEquals(etree.get('name'), None)
self.assertEquals(etree.get('type'),'selection')
self.assertEquals(etree.find('option').get('name'),'one')
self.assertEquals(etree.find('option').get('value'),'1')
@@ -1008,13 +1431,15 @@
setting.totalDigits = 3
setting.pattern = "\d*{3}"
etree = writer.dumps(setting)
+ strxml = confmltree.tostring(etree, {'http://xs.com' : 'xs'} )
+ etree = ElementTree.fromstring(strxml)
- self.assertEquals(etree.find('xs:minInclusive').get('value'),'0')
- self.assertEquals(etree.find('xs:maxInclusive').get('value'),'10')
- self.assertEquals(etree.find('xs:minExclusive').get('value'),'0')
- self.assertEquals(etree.find('xs:maxExclusive').get('value'),'10')
- self.assertEquals(etree.find('xs:totalDigits').get('value'),'3')
- self.assertEquals(etree.find('xs:pattern').get('value'),'\d*{3}')
+ self.assertEquals(etree.find('{http://xs.com}minInclusive').get('value'),'0')
+ self.assertEquals(etree.find('{http://xs.com}maxInclusive').get('value'),'10')
+ self.assertEquals(etree.find('{http://xs.com}minExclusive').get('value'),'0')
+ self.assertEquals(etree.find('{http://xs.com}maxExclusive').get('value'),'10')
+ self.assertEquals(etree.find('{http://xs.com}totalDigits').get('value'),'3')
+ self.assertEquals(etree.find('{http://xs.com}pattern').get('value'),'\d*{3}')
conffile = open(os.path.join(ROOT_PATH,"data/facets.confml"))
obj = persistentconfml.loads(conffile.read())
@@ -1073,8 +1498,8 @@
'name': 'strme',
'type': 'string'}))
setobj = reader.loads(elem)
- self.assertEqual(setobj.get_map_key().name,"intme")
- self.assertEqual(setobj.get_map_value().name,"strme")
+ self.assertEqual(setobj.mapKey, "intsetting")
+ self.assertEqual(setobj.mapValue, "strsetting")
class TestSettingData(unittest.TestCase):
def test_get_reader_for_data(self):
@@ -1131,6 +1556,193 @@
obj = reader.loads(etree)
self.assertEquals(obj.meta.get('type'), 'featurelist')
+class TestWriteSequenceTemplates(BaseTestCase):
+ EXPECTED_DIR = os.path.join(ROOT_PATH, 'testdata/seq_template/expected')
+ TEMP_DIR = os.path.join(ROOT_PATH, 'temp/')
+
+ def _add_simple_sequence(self, config):
+ """
+ Add a feature with a simple sequence setting into the given
+ configuration.
+ @return: The added sequence setting object.
+ """
+ fea = api.Feature('TestFeature', name='Test feature')
+ seq_fea = model.ConfmlSequenceSetting('SequenceSetting', name='Sequence setting')
+ fea.add_feature(seq_fea)
+ config.add_feature(fea)
+
+ seq_fea.add_feature(model.ConfmlStringSetting('String1', name="String 1"))
+ seq_fea.add_feature(model.ConfmlFileSetting('File', name="File setting"))
+ seq_fea.add_feature(model.ConfmlStringSetting('String2', name="String 2"))
+
+ return seq_fea
+
+ def _add_complex_sequence(self, config):
+ """
+ Add a feature with a complex sequence setting into the given
+ configuration.
+ @return: The added sequence setting object.
+ """
+ fea = api.Feature('TestFeature', name='Test feature')
+ seq_fea = model.ConfmlSequenceSetting('SequenceSetting', name='Sequence setting')
+ fea.add_feature(seq_fea)
+ config.add_feature(fea)
+
+ seq_fea.add_feature(model.ConfmlFileSetting('File', name="File setting"))
+ seq_fea.add_feature(model.ConfmlFolderSetting('Folder', name="Folder setting"))
+ seq_fea.add_feature(model.ConfmlStringSetting('String', name="String setting"))
+ seq_fea.add_feature(model.ConfmlIntSetting('Int', name="Int setting"))
+ seq_fea.add_feature(model.ConfmlRealSetting('Real', name="Real setting"))
+ seq_fea.add_feature(model.ConfmlBooleanSetting('Boolean', name="Boolean setting"))
+ seq_fea.add_feature(model.ConfmlDateSetting('Date', name="Date setting"))
+ seq_fea.add_feature(model.ConfmlTimeSetting('Time', name="Time setting"))
+ seq_fea.add_feature(model.ConfmlDateTimeSetting('DateTime', name="Date-time setting"))
+ seq_fea.add_feature(model.ConfmlDurationSetting('Duration', name="Duration setting"))
+
+ return seq_fea
+
+ def test_write_simple_seq_no_template(self):
+ FILE_NAME = 'write_simple_seq_no_template.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+
+ seq = self._add_simple_sequence(config)
+
+ seq.add_sequence(['row 1', ['lp1', 'tp1'], 'x'])
+ seq.add_sequence(['row 2', ['lp2', 'tp2'], 'y'])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'simple_seq_no_template.confml'))
+
+ def test_write_simple_seq(self):
+ FILE_NAME = 'write_simple_seq.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+ config.name = 'foo'
+
+ seq = self._add_simple_sequence(config)
+
+ seq.set_template(['c1', ['lp', 'tp'], 'c2'])
+ seq.add_sequence(['row 1', ['lp1', 'tp1'], 'x'])
+ seq.add_sequence(['row 2', ['lp2', 'tp2'], 'y'])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'simple_seq.confml'))
+
+ def test_write_simple_seq_2(self):
+ FILE_NAME = 'write_simple_seq_2.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+ config.name = 'foo'
+
+ seq = self._add_simple_sequence(config)
+
+ # It shouldn't matter if the template is reset in the middle
+ seq.set_template(['x1', ['lp', 'tp'], 'x2'])
+ seq.add_sequence(['row 1', ['lp1', 'tp1'], 'x'])
+ seq.set_template(['c1', ['lp', 'tp'], 'c2'])
+ seq.add_sequence(['row 2', ['lp2', 'tp2'], 'y'])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'simple_seq.confml'))
+
+ def test_write_simple_seq_3(self):
+ FILE_NAME = 'write_simple_seq_3.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+ config.name = 'foo'
+
+ seq = self._add_simple_sequence(config)
+
+ # Add multiple templates into the data section to make
+ # sure that they are all replaced when set_template() is called
+ def create_template_data():
+ template_data = api.Data(fqr='TestFeature.SequenceSetting', template=True)
+ template_data.add(api.Data(ref='String1', value='t1'))
+ data_a1 = api.Data(ref='File')
+ data_a1.add(api.Data(ref='localPath', value='lp'))
+ data_a1.add(api.Data(ref='targetPath', value='tp'))
+ template_data.add(data_a1)
+ template_data.add(api.Data(ref='String2', value='t2'))
+ return template_data
+ from cone.public import container
+ config.add_data(create_template_data(), policy=container.APPEND)
+ config.add_data(create_template_data(), policy=container.APPEND)
+ config.add_data(create_template_data(), policy=container.APPEND)
+ seq = config.get_default_view().get_feature('TestFeature.SequenceSetting')
+ self.assertEquals(seq.get_template(), ['t1', ['lp', 'tp'], 't2'])
+
+ # Add some data and set the template
+ seq.add_sequence(['row 1', ['lp1', 'tp1'], 'x'])
+ seq.add_sequence(['row 2', ['lp2', 'tp2'], 'y'])
+ seq.set_template(['c1', ['lp', 'tp'], 'c2'])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'simple_seq.confml'))
+
+ def test_write_complex_seq(self):
+ FILE_NAME = 'write_complex_seq.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+
+ seq = self._add_complex_sequence(config)
+
+ seq.set_template([['file lp', 'file tp'], ['folder lp', 'folder tp'],
+ 'string', '0', '0.1', 'false',
+ '2010-02-10', '00:00:00', '2010-02-10-00:00:00', 'P5Y4M3DT12H25M15S'])
+
+ seq.add_sequence([['file lp1', 'file tp1'], ['folder lp1', 'folder tp1'],
+ 'string1', '1', '1.1', 'true',
+ '2009-02-01', '01:30:15', '2009-02-01-01:00:00', 'PT1S'])
+ seq.add_sequence([['file lp2', 'file tp2'], ['folder lp2', 'folder tp2'],
+ 'string2', '2', '1.2', 'false',
+ '2009-02-02', '02:30:15', '2009-02-02-02:00:00', 'PT2S'])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'complex_seq.confml'))
+
+ def test_write_complex_seq_with_nones(self):
+ FILE_NAME = 'write_complex_seq_with_nones.confml'
+ prj = api.Project(api.Storage.open(self.TEMP_DIR, "w"))
+ config = prj.create_configuration(FILE_NAME)
+
+ seq = self._add_complex_sequence(config)
+
+ seq.set_template([['file lp', None], [None, 'folder tp'],
+ 'string', None, 0.1, None,
+ '2010-02-10', None, '2010-02-10-00:00:00', None])
+
+ seq.add_sequence([['file lp1', None], [None, 'folder tp1'],
+ 'string1', None, 1.1, None,
+ '2009-02-01', None, '2009-02-01-01:00:00', None])
+
+ config.save()
+ prj.close()
+
+ self.assert_file_contents_equal(
+ os.path.join(self.TEMP_DIR, FILE_NAME),
+ os.path.join(self.EXPECTED_DIR, 'complex_seq_with_nones.confml'))
+
class TestReadWriteConfml(BaseTestCase):
"""
Test case for ensuring that reading in a ConfML file and then writing
@@ -1176,7 +1788,7 @@
write(PATH_ORIGINAL, original_data_normalized)
write(PATH_DUMPED, model_data_normalized)
- self.fail("Known bug (#506)")
+ #self.fail("Known bug (#506)")
self.fail("Read-write output for file '%s' is different, see the files in '%s'" % (file_name, output_dir))
else:
# Test was successful, remove any old files that might have been there,
@@ -1190,6 +1802,38 @@
file_name = os.path.basename(file_path),
input_dir = os.path.dirname(file_path),
output_dir = os.path.normpath(os.path.join(ROOT_PATH, 'temp/read_write_results')))
+
+ def test_create_configuration_with_view_includes_to_storage(self):
+ prj = api.Project(api.Storage.open("temp/testprojectviews", "w"))
+ test = prj.create_configuration("testview.confml")
+ fea1 = test.create_feature("fea1")
+ set1 = fea1.create_feature('set1', type="int")
+ view = test.create_view("Testing")
+ test1 = prj.create_configuration("testview1.confml")
+ view1 = test1.create_view("subview1")
+ test2 = prj.create_configuration("testview2.confml")
+ view2 = test2.create_view("subview2")
+ group = view.create_group("group1")
+ group.create_featurelink("fea1/set1")
+ group2 = view2.create_group("group2")
+ group2.create_featurelink("fea1/set1")
+ view.add(api.ConfigurationProxy("testview1.confml"))
+ group.add(api.ConfigurationProxy("testview2.confml"))
+ prj.save()
+ prj.close()
+
+ prj = api.Project(api.Storage.open("temp/testprojectviews", "w"))
+ test = prj.get_configuration("testview.confml")
+ self.assertEquals(test.list_views(), ['Testing',
+ 'Testing.group1.testview2_confml.subview2',
+ 'Testing.testview1_confml.subview1'])
+
+ view = test.get_view('Testing')
+
+ self.assertEquals(view.list_all_features(), ['group1.proxy_fea1_set1'])
+
+ self.assertTrue(os.path.exists("temp/testprojectviews"))
+ shutil.rmtree("temp")
# Create a separate test method for each ConfML file in the read-write test data
_READ_WRITE_TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata/read_write')
@@ -1205,7 +1849,7 @@
method.__name__ = test_method_name
setattr(TestReadWriteConfml, test_method_name, method)
_register_test_method(path)
-
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/__init__.py
--- a/configurationengine/source/cone/core/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,36 +14,4 @@
# Description:
#
-import unittest, os, sys
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../..'))
-TESTAUTO_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../testautomation'))
-if SOURCE_ROOT not in sys.path:
- sys.path.append(SOURCE_ROOT)
-if TESTAUTO_ROOT not in sys.path:
- sys.path.insert(0,TESTAUTO_ROOT)
-
-# Find all unittest_*.py files in this folder
-import re
-__all__ = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(ROOT_PATH))
-# Strip .py endings
-__all__ = map(lambda name: name[:-3], __all__)
-
-def collect_suite():
- sys.path.insert(0, ROOT_PATH)
- try:
- suite = unittest.TestSuite()
- for test_module in __all__:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- del sys.path[0]
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/runtests.py
--- a/configurationengine/source/cone/core/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
\ No newline at end of file
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/testdata/layered_res_test.zip
Binary file configurationengine/source/cone/core/tests/testdata/layered_res_test.zip has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/testdata/test_project.cpf
Binary file configurationengine/source/cone/core/tests/testdata/test_project.cpf has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration.py
--- a/configurationengine/source/cone/core/tests/unittest_configuration.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/unittest_configuration.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,19 +21,141 @@
import string
import sys,os
-import __init__
from cone.public import api, plugin
from cone.core import *
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
test_project = os.path.join(ROOT_PATH,"testdata/test_project.cpf")
multiroot_project = os.path.join(ROOT_PATH,"testdata/multiroot_test.zip")
+LAYERED_RES_PROJECT = os.path.join(ROOT_PATH,"testdata/layered_res_test.zip")
+
class TestConfiguration(unittest.TestCase):
def setUp(self):
pass
- # @test
+ def test_layered_resources_invalid_resource_type(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+ self.assertRaises(ValueError, config.layered_resources, resource_type='foo')
+
+ def test_layered_resource_invalid_params(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ # Both folder and resource_type specified
+ self.assertRaises(ValueError, config.layered_resources, folder='foo', resource_type='implml')
+
+ # Neither folder nor resource_type specified
+ self.assertRaises(ValueError, config.layered_resources, folder=None, resource_type=None)
+
+ def test_layered_resources(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ data = config.layered_resources(resource_type='confml').data
+ self.assertEquals(data, {'test.confml': ['layer1/confml/test.confml',
+ 'layer2/confml/test.confml']})
+
+ data = config.layered_resources(resource_type='implml').data
+ self.assertEquals(data, {'test.implml': ['layer1/implml/test.implml',
+ 'layer2/implml/test.implml']})
+
+ data = config.layered_resources(resource_type='content').data
+ self.assertEquals(data, {'foo.txt': ['layer1/content/foo.txt',
+ 'layer2/content/foo.txt']})
+
+ data = config.layered_resources(resource_type='doc').data
+ self.assertEquals(data, {'bar.txt': ['layer1/doc/bar.txt',
+ 'layer2/doc/bar.txt']})
+
+ def test_layered_resources_custom_folder(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ data = config.layered_resources(folder='foo').data
+ self.assertEquals(data, {'bar.txt': ['layer1/foo/bar.txt',
+ 'layer2/foo/bar.txt']})
+
+ def test_layered_resources_directly_from_layer(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('layer1/root.confml')
+
+ self.assertEquals(config.layered_resources(resource_type='confml').data,
+ {'test.confml': ['layer1/confml/test.confml']})
+
+ self.assertEquals(config.layered_resources(resource_type='implml').data,
+ {'test.implml': ['layer1/implml/test.implml']})
+
+ def test_layered_resources_with_empty_folders(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ data = config.layered_resources(empty_folders=True, resource_type='confml').data
+ self.assertEquals(data, {'test.confml': ['layer1/confml/test.confml',
+ 'layer2/confml/test.confml'],
+ 'empty': ['layer1/confml/empty',
+ 'layer2/confml/empty']})
+
+ data = config.layered_resources(empty_folders=True, resource_type='implml').data
+ self.assertEquals(data, {'test.implml': ['layer1/implml/test.implml',
+ 'layer2/implml/test.implml'],
+ 'empty': ['layer1/implml/empty',
+ 'layer2/implml/empty']})
+
+ data = config.layered_resources(empty_folders=True, resource_type='content').data
+ self.assertEquals(data, {'foo.txt': ['layer1/content/foo.txt',
+ 'layer2/content/foo.txt'],
+ 'empty': ['layer1/content/empty',
+ 'layer2/content/empty']})
+
+ data = config.layered_resources(empty_folders=True, resource_type='doc').data
+ self.assertEquals(data, {'bar.txt': ['layer1/doc/bar.txt',
+ 'layer2/doc/bar.txt'],
+ 'empty': ['layer1/doc/empty',
+ 'layer2/doc/empty']})
+
+ def test_layered_resources_specific_layers(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ self.assertEquals(config.layered_resources(layers=[-1], resource_type='confml').data,
+ {'test.confml': ['layer2/confml/test.confml']})
+ self.assertEquals(config.layered_resources(layers=[0], resource_type='confml').data,
+ {'test.confml': ['layer1/confml/test.confml']})
+
+ def test_layered_resources_shortcuts(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ data = config.layered_confml().data
+ self.assertEquals(data, {'test.confml': ['layer1/confml/test.confml',
+ 'layer2/confml/test.confml']})
+
+ data = config.layered_implml().data
+ self.assertEquals(data, {'test.implml': ['layer1/implml/test.implml',
+ 'layer2/implml/test.implml']})
+
+ data = config.layered_content().data
+ self.assertEquals(data, {'foo.txt': ['layer1/content/foo.txt',
+ 'layer2/content/foo.txt']})
+
+ data = config.layered_doc().data
+ self.assertEquals(data, {'bar.txt': ['layer1/doc/bar.txt',
+ 'layer2/doc/bar.txt']})
+
+
+ def test_implml_override(self):
+ p = api.Project(api.Storage.open(LAYERED_RES_PROJECT))
+ config = p.get_configuration('root.confml')
+
+ impl_set = plugin.get_impl_set(config)
+ self.assertEquals([impl.ref for impl in impl_set], ['layer2/implml/test.implml'])
+
+ impl_set = plugin.filtered_impl_set(config)
+ self.assertEquals([impl.ref for impl in impl_set], ['layer2/implml/test.implml'])
+
+
def test_create_configuration(self):
conf = api.Configuration("foobar/testmee.confml")
self.assertTrue(conf)
@@ -62,12 +184,13 @@
config = p.get_configuration('root5.confml')
view = config.get_default_view()
print "Fealist %s." % len(view.list_all_features())
- self.assertEquals(len(view.list_all_features()), 62)
+ self.assertEquals(len(view.list_all_features()), 99)
for feaname in view.list_all_features():
fea = view.get_feature(feaname)
if fea.get_type() == 'sequence':
print "%s" % feaname,
- print " = %s" % fea.get_value()
+ print "Value = %s" % fea.get_value()
+ print "RFS = %s" % fea.get_value(attr='rfs')
def test_get_implml_container(self):
fs = api.Storage.open(test_project)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration_project_edit_data.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/core/tests/unittest_configuration_project_edit_data.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,220 @@
+from __future__ import with_statement
+#
+# 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:
+#
+
+import unittest
+import os
+
+from cone.public import api
+from cone.storage.filestorage import FileStorage
+from testautomation import unzip_file
+from testautomation.base_testcase import BaseTestCase
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TEMP_DIR = os.path.join(ROOT_PATH, "temp/edit_data")
+TEST_CPF = os.path.join(ROOT_PATH, "testdata/test_project.cpf")
+
+class open_config_and_get_dview(object):
+ def __init__(self, project, mode, config):
+ self.project_path = project
+ self.mode = mode
+ self.config = config
+ self.project = None
+
+ def __enter__(self):
+ self.project = api.Project(FileStorage(self.project_path, self.mode))
+ conf = self.project.get_configuration(self.config)
+ dview = conf.get_default_view()
+ return dview
+ setting = dview.get_feature(self.setting_ref)
+ return setting
+
+ def __exit__(self, type, value, tb):
+ if self.project:
+ if self.mode == 'a':
+ self.project.save()
+ self.project.close()
+
+class open_config_and_get_setting(open_config_and_get_dview):
+ def __init__(self, project, mode, config, setting):
+ open_config_and_get_dview.__init__(self, project, mode, config)
+ self.setting_ref = setting
+
+ def __enter__(self):
+ dview = open_config_and_get_dview.__enter__(self)
+ setting = dview.get_feature(self.setting_ref)
+ return setting
+
+class TestEditConfigurationProjectData(BaseTestCase):
+
+ def test_edit_sequence_data_on_last_layer_with_dview(self):
+ PROJ = os.path.join(TEMP_DIR, "test_project_1")
+ CONF = 'root3.confml'
+ SETTING = 'Feature2.SequenceSetting'
+ unzip_file.unzip_file(TEST_CPF, PROJ, delete_if_exists=True)
+
+ # Open the temp project in append mode
+ with open_config_and_get_setting(PROJ, 'a', CONF, SETTING) as setting:
+ self.assertEquals(setting.value,
+ [[333, 'layer3 (1)'],
+ [1, 'default 1'],
+ [2, 'default 2'],
+ [222, 'layer2 (1)'],
+ [222, 'layer2 (2)'],
+ [222, 'layer2 (3)']])
+
+ # Change the value
+ setting.value = [[123, 'foo1'],
+ [456, 'foo2']]
+
+ # Reopen the project in read mode and check that the sequence data
+ # was modified correctly
+ with open_config_and_get_setting(PROJ, 'r', CONF, SETTING) as setting:
+ self.assertEquals(setting.value,
+ [[123, 'foo1'],
+ [456, 'foo2']])
+ self.assertEquals(setting.get_original_value(),
+ [['123', 'foo1'],
+ ['456', 'foo2']])
+
+ # Modify the sequence data again by setting it empty
+ with open_config_and_get_setting(PROJ, 'a', CONF, SETTING) as setting:
+ setting.value = []
+ self.assertEquals(setting.value, [])
+ self.assertEquals(setting.get_original_value(), [])
+
+ # Reopen and check again
+ with open_config_and_get_setting(PROJ, 'r', CONF, SETTING) as setting:
+ self.assertEquals(setting.value, [])
+ self.assertEquals(setting.get_original_value(), [])
+
+ # Do the same 'set empty' check with a more complex sequence setting
+ SETTING = 'SequenceSettingTest.SequenceSetting'
+ with open_config_and_get_setting(PROJ, 'a', CONF, SETTING) as setting:
+ setting.value = []
+ self.assertEquals(setting.value, [])
+ self.assertEquals(setting.get_original_value(), [])
+ with open_config_and_get_setting(PROJ, 'r', CONF, SETTING) as setting:
+ self.assertEquals(setting.value, [])
+ self.assertEquals(setting.get_original_value(), [])
+
+ def test_edit_complex_sequence_data_on_last_layer_with_dview(self):
+ PROJ = os.path.join(TEMP_DIR, "test_project_4")
+ CONF = 'root3.confml'
+ SETTING = 'SequenceSettingTest.SequenceSetting'
+ unzip_file.unzip_file(TEST_CPF, PROJ, delete_if_exists=True)
+
+ # Open the temp project in append mode
+ with open_config_and_get_setting(PROJ, 'a', CONF, SETTING) as setting:
+ self.assertEquals(setting.value,
+ [[['seq/layer2_folder2', None], 2.1000000000000001, ['seq/layer2_file2.txt', None], 222, 'L22', True, '1', ('opt 1', 'opt 3'), '\x22\x22'],
+ [['seq/layer2_folder', None], 2.0, ['seq/layer2_file.txt', None], 22, 'L21', True, '2', ('opt 2',), '\x22\x11'],
+ [['seq/def1_folder', None], 1.25, ['seq/def1_file.txt', None], 128, 'def1', False, '1', ('opt 1',), '\x00\x11'],
+ [['seq/def2_folder', None], 1.5, ['seq/def2_file.txt', None], 256, 'def2', False, '1', ('opt 2',), '\x00\x22'],
+ [['seq/layer3_folder', None], 3.0, ['seq/layer3_file.txt', None], 33, 'L31', False, '0', ('opt 3', 'opt 2'), '\x33\x11'],
+ [['seq/layer3_folder', None], 3.3500000000000001, [None, None], 1, 'L32', True, '2', ('opt 1', 'opt 2'), '\x33\x22']])
+
+ # Change the value
+ setting.value = [[['seq/foofolder1', None], 5.6, ['seq/foofile1.txt', None], 1010, 'Lfoo', False, '3', ('opt 4', 'opt 0'), '\xaa\xbb'],
+ [['seq/foofolder2', None], 6.5, ['seq/foofile2.txt', None], 2020, 'Lfoo', True, '3', (), ''],
+ [['seq/foofolder1', None], 5.6, ['seq/foofile1.txt', None], 1010, 'Lfoo', False, '3', ('opt 4', 'opt 0'), '\xaa\xbb']]
+
+ with open_config_and_get_setting(PROJ, 'r', CONF, SETTING) as setting:
+ self.assertEquals(setting.value,
+ [[['seq/foofolder1', None], 5.6, ['seq/foofile1.txt', None], 1010, 'Lfoo', False, '3', ('opt 4', 'opt 0'), '\xaa\xbb'],
+ [['seq/foofolder2', None], 6.5, ['seq/foofile2.txt', None], 2020, 'Lfoo', True, '3', (), ''],
+ [['seq/foofolder1', None], 5.6, ['seq/foofile1.txt', None], 1010, 'Lfoo', False, '3', ('opt 4', 'opt 0'), '\xaa\xbb']])
+ # Modify the sequence data again by setting it empty
+ with open_config_and_get_setting(PROJ, 'a', CONF, SETTING) as setting:
+ setting.value = []
+
+ # Reopen and check again
+ with open_config_and_get_setting(PROJ, 'r', CONF, SETTING) as setting:
+ self.assertEquals(setting.value, [])
+
+ def test_edit_data_on_last_layer_with_dview(self):
+ PROJ = os.path.join(TEMP_DIR, "test_project_2")
+ CONF = 'root3.confml'
+ unzip_file.unzip_file(TEST_CPF, PROJ, delete_if_exists=True)
+
+ # Open the temp project in append mode
+ with open_config_and_get_dview(PROJ, 'a', CONF) as dview:
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.IntSetting').value, 333)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.BooleanSetting').value, False)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.RealSetting').value, 3.1456)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.SelectionSetting').value, '3')
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.StringSetting').value, 'layer 3 string')
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.MultiSelectionSetting').value, ('opt 1', 'opt 3'))
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.HexBinarySetting').value, '\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff')
+
+ dview.get_feature('BasicSettingTypesTest.IntSetting').value = 1500
+ dview.get_feature('BasicSettingTypesTest.BooleanSetting').value = True
+ dview.get_feature('BasicSettingTypesTest.RealSetting').value = 15.15
+ dview.get_feature('BasicSettingTypesTest.SelectionSetting').value = '1'
+ dview.get_feature('BasicSettingTypesTest.StringSetting').value = 'edit data test'
+ dview.get_feature('BasicSettingTypesTest.MultiSelectionSetting').value = ('opt 4', 'opt 0')
+ dview.get_feature('BasicSettingTypesTest.HexBinarySetting').value = '\x12\x34'
+
+ # Reopen the project in read mode and check that the sequence data
+ # was modified correctly
+ with open_config_and_get_dview(PROJ, 'r', CONF) as dview:
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.IntSetting').value, 1500)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.BooleanSetting').value, True)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.RealSetting').value, 15.15)
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.SelectionSetting').value, '1')
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.StringSetting').value, 'edit data test')
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.MultiSelectionSetting').value, ('opt 4', 'opt 0'))
+ self.assertEquals(dview.get_feature('BasicSettingTypesTest.HexBinarySetting').value, '\x12\x34')
+
+ # Test that setting the multi-selection setting to empty works
+ SETTING = 'BasicSettingTypesTest.MultiSelectionSetting'
+ with open_config_and_get_setting(PROJ, 'a', 'root4.confml', SETTING) as setting:
+ self.assertEquals(setting.value, ('opt 0', 'opt 4'))
+ setting.value = ()
+ self.assertEquals(setting.value, ())
+ with open_config_and_get_setting(PROJ, 'r', 'root4.confml', SETTING) as setting:
+ self.assertEquals(setting.value, ())
+
+ def test_read_name_id_mapped_values(self):
+ PROJ = os.path.join(TEMP_DIR, "test_project_5")
+ CONF = 'root3.confml'
+ unzip_file.unzip_file(TEST_CPF, PROJ, delete_if_exists=True)
+
+ with open_config_and_get_dview(PROJ, 'r', CONF) as dview:
+ def check(setting, expected_value):
+ fea = dview.get_feature('NameIdMappingTestTargetSettings.' + setting)
+ self.assertEquals(fea.get_value(), expected_value)
+
+ check('Selection', 'seq1_item2')
+ check('Selection2', 12)
+ check('MultiSelection', ('seq1_item1', 'seq1_item2', 'seq2_item2', 'seq2_item3'))
+ check('MultiSelection2', (11, 12, True, False))
+ check('String', 'seq1_item2')
+ check('Int', 12)
+ check('Real', 1.2)
+ check('Boolean', False)
+
+ check('Sequence.Selection', ['seq1_item2'])
+ check('Sequence.Selection2', [12])
+ check('Sequence.MultiSelection', [('seq1_item1', 'seq1_item2', 'seq2_item2', 'seq2_item3')])
+ check('Sequence.MultiSelection2', [(11, 12, True, False)])
+ check('Sequence.String', ['seq1_item2'])
+ check('Sequence.Int', [12])
+ check('Sequence.Real', [1.2])
+ check('Sequence.Boolean', [False])
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration_project_export.py
--- a/configurationengine/source/cone/core/tests/unittest_configuration_project_export.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/unittest_configuration_project_export.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,8 +22,6 @@
import sys,os,shutil
import difflib, zipfile
-import __init__
-
from cone.public import exceptions,utils, api
from cone.storage.filestorage import FileStorage
from cone.storage.zipstorage import ZipStorage
@@ -184,17 +182,17 @@
# except exceptions.NotSupportedException:
# pass
- def test_export_to_filestorage_multiple_configurations(self):
+ def _test_export_to_filestorage_multiple_configurations(self):
fs = FileStorage(datafolder)
p = api.Project(fs)
- fs2 = FileStorage("temp/exported","w")
+ fs2 = FileStorage(os.path.join(temp_dir,"multiple"),"w")
p2 = api.Project(fs2)
conf = p.get_configuration('morestuff.confml')
conf_files = conf.list_resources()
p.export_configuration(conf,fs2)
conf = p.get_configuration('prodX.confml')
conf_files.extend(conf.list_resources())
-
+ fs2.save()
p.export_configuration(conf,fs2)
p2.close()
self.assertTrue(os.path.exists("temp/exported"))
@@ -204,8 +202,8 @@
files.sort()
conf_files.append('.metadata')
conf_files.sort()
- self.assertEquals(conf_files,files)
- shutil.rmtree("temp")
+ self.assertEquals(sorted(conf_files),sorted(files))
+ #shutil.rmtree("temp")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration_project_import.py
--- a/configurationengine/source/cone/core/tests/unittest_configuration_project_import.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/unittest_configuration_project_import.py Tue Aug 10 14:29:28 2010 +0300
@@ -32,7 +32,6 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
from testautomation import unzip_file
from cone.public import exceptions, utils, api
@@ -115,7 +114,7 @@
p2.import_configuration(conf)
p2.close()
self.assertTrue(os.path.exists("temp/imported"))
- files = fs2.list_resources("/",True)
+ files = fs2.list_resources("/",recurse=True)
conf_files = utils.distinct_array(conf_files)
conf_files.append('.metadata')
@@ -136,7 +135,7 @@
p.close()
self.assertTrue(os.path.exists(imported_folder))
store = api.Storage.open(imported_folder)
- files = store.list_resources('',True)
+ files = store.list_resources('',recurse=True)
conf_files.sort()
files.sort()
self.assertEquals(conf_files,files)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration_project_on_filestorage.py
--- a/configurationengine/source/cone/core/tests/unittest_configuration_project_on_filestorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/unittest_configuration_project_on_filestorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,7 +21,6 @@
import string
import sys,os
import shutil
-import __init__
from testautomation.base_testcase import BaseTestCase
from cone.public import exceptions, api
@@ -57,7 +56,7 @@
def test_list_configurations(self):
confs = self.project.list_configurations()
self.assertTrue(confs)
- self.assertEquals(confs[0],"morestuff.confml")
+ self.assertEquals(sorted(confs), sorted(['morestuff.confml', 'prodX.confml', 'simple.confml']))
def test_get_configuration(self):
conf = self.project.get_configuration("morestuff.confml")
@@ -75,8 +74,10 @@
conf = self.project.get_configuration("morestuff.confml")
layers = conf.list_configurations()
self.assertTrue(layers)
- self.assertEquals(layers[0],'platform/s60/root.confml')
- self.assertEquals(layers[1],'familyX/root.confml')
+ self.assertEquals(sorted(layers),
+ sorted(['platform/s60/root.confml',
+ 'familyX/root.confml',
+ 'familyX/prodX/root.confml']))
def test_get_is_configuration(self):
self.assertTrue(self.project.is_configuration("morestuff.confml"))
@@ -126,19 +127,20 @@
def test_get_all_resources(self):
conf = self.project.get_configuration("morestuff.confml")
resources = conf.get_all_resources()
- self.assertEquals(resources[0].get_path(),'morestuff.confml')
- self.assertEquals(resources[1].get_path(),'platform/s60/root.confml')
+ paths = [r.get_path() for r in resources]
+ self.assertTrue('morestuff.confml' in paths)
+ self.assertTrue('platform/s60/root.confml' in paths)
def test_list_confmls(self):
conf = self.project.get_configuration("morestuff.confml")
confmls = conf.list_resources()
- self.assertEquals(confmls[0],'morestuff.confml')
- self.assertEquals(confmls[1],'platform/s60/root.confml')
+ self.assertTrue('morestuff.confml' in confmls )
+ self.assertTrue('platform/s60/root.confml' in confmls)
def test_list_implmls(self):
conf = self.project.get_configuration("morestuff.confml")
implmls = conf.get_configuration('platform/s60/root.confml').get_layer().list_implml()
- self.assertEquals(implmls[0],'implml/accessoryserver_1020505A.crml')
+ self.assertTrue('implml/accessoryserver_1020505A.crml' in implmls)
# def test_list_content(self):
# conf = self.project.get_configuration("morestuff.confml")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/core/tests/unittest_configuration_project_on_zipstorage.py
--- a/configurationengine/source/cone/core/tests/unittest_configuration_project_on_zipstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/core/tests/unittest_configuration_project_on_zipstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import unittest
import string
import sys,os, shutil
-import __init__
from cone.public import exceptions, api
from cone.core import *
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/_etree_wrapper.py
--- a/configurationengine/source/cone/public/_etree_wrapper.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/_etree_wrapper.py Tue Aug 10 14:29:28 2010 +0300
@@ -32,8 +32,11 @@
def get_lineno(self, element):
raise NotImplementedError()
+ def get_elem_from_lineno(self, root, lineno):
+ raise NotImplementedError()
+
class ElementTreeBackendWrapper(ElementTreeBackendWrapperBase):
-
+
class CustomTreeBuilder(ElementTree.TreeBuilder):
"""
Custom TreeBuilder for ElementTree that records line numbers
@@ -42,7 +45,7 @@
def start(self, tag, attrs):
elem = ElementTree.TreeBuilder.start(self, tag, attrs)
lineno = self._xmltreebuilder._parser.CurrentLineNumber
- #print "Tag: %s, line: %r" % (tag, lineno)
+ # print "Tag: %s, line: %r" % (tag, lineno)
elem.sourceline = lineno
return elem
@@ -55,7 +58,8 @@
parser = ElementTree.XMLTreeBuilder(target=treebuilder)
treebuilder._xmltreebuilder = parser
parser.feed(text)
- return parser.close()
+ self.root = parser.close()
+ return self.root
except expat.ExpatError, e:
raise exceptions.XmlParseError(
"XML parse error on line %d: %s" % (e.lineno, e),
@@ -65,8 +69,16 @@
return ElementTree.tostring(etree, encoding)
def get_lineno(self, element):
- return element.sourceline
+ try:
+ return element.sourceline
+ except AttributeError:
+ return None
+ def get_elem_from_lineno(self, root, lineno):
+ for elem in root.getiterator():
+ if elem.sourceline == lineno:
+ return elem
+ return None
class CElementTreeBackendWrapper(ElementTreeBackendWrapperBase):
def __init__(self):
@@ -82,7 +94,8 @@
def fromstring(self, text):
try:
- return self.cElementTree.fromstring(text)
+ self.root = self.cElementTree.fromstring(text)
+ return self.root
except SyntaxError, e:
# cElementTree raises a SyntaxError, but does not set
# its lineno attribute, so look for the line number
@@ -103,6 +116,9 @@
# cElementTree does not support line numbers
return None
+ def get_elem_from_lineno(self, root, lineno):
+ # cElementTree does not support line numbers
+ return None
class LxmlBackendWrapper(ElementTreeBackendWrapperBase):
@@ -115,39 +131,48 @@
def fromstring(self, text):
try:
- elem = self.lxml.etree.fromstring(text)
-
- # lxml parses also comments, but ConE does not expect those,
- # so remove them to prevent any errors on that account
- def remove_comments(elem):
- # Find the comments under this element
- comments = []
- for x in elem:
- if isinstance(x, self.lxml.etree._Comment):
- comments.append(x)
-
- # Remove them
- for c in comments:
- elem.remove(c)
-
- # Recurse to sub-elements
- for subelem in elem:
- remove_comments(subelem)
-
- remove_comments(elem)
-
- return elem
+ self.root = self.lxml.etree.fromstring(text)
+ self.remove_comments(self.root)
+ return self.root
except self.lxml.etree.XMLSyntaxError, e:
raise exceptions.XmlParseError(
"XML parse error on line %d: %s" % (e.position[0], e),
e.position[0], str(e))
+ def remove_comments(self, elem):
+ """
+ lxml parses also comments, but ConE does not expect those,
+ so remove them to prevent any errors on that account
+ """
+ # Find the comments under this element
+ comments = []
+ for x in elem:
+ if isinstance(x, self.lxml.etree._Comment):
+ comments.append(x)
+
+ # Remove them
+ for c in comments:
+ elem.remove(c)
+
+ # Recurse to sub-elements
+ for subelem in elem:
+ self.remove_comments(subelem)
+
def tostring(self, etree, encoding=None):
return self.lxml.etree.tostring(etree, encoding=encoding)
def get_lineno(self, element):
- return element.sourceline
+ try:
+ return element.sourceline
+ except AttributeError:
+ return None
+ def get_elem_from_lineno(self, root, lineno):
+ for elem in root.getiterator():
+ if elem.sourceline == lineno:
+ return elem
+ return None
+
# ============================================================================
#
# ============================================================================
@@ -167,7 +192,8 @@
# Import order for the default back-end. The list is traversed
# top-down and the first back-end whose importing is successful is
# used as the default back-end
- DEFAULT_BACKEND_IMPORT_ORDER = [BACKEND_C_ELEMENT_TREE,
+ DEFAULT_BACKEND_IMPORT_ORDER = [BACKEND_LXML,
+ BACKEND_C_ELEMENT_TREE,
BACKEND_ELEMENT_TREE]
_backend_mapping = {BACKEND_ELEMENT_TREE: ElementTreeBackendWrapper,
@@ -229,6 +255,18 @@
"""
return self._get_backend().get_lineno(element)
+ def get_elem_from_lineno(self, root, lineno):
+ """
+ Return the element from the given line number of the given XML element.
+
+ @param root: the root element to search from
+ @param lineno: the line number to search for
+
+ Note that for the cElementTree parser this will always return
+ None, since that parser does not support line numbers.
+ """
+ return self._get_backend().get_elem_from_lineno(root, lineno)
+
def __getattribute__(self, attrname):
try:
# Try to get the attribute from this object (the top-level wrapper)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/_plugin_reader.py
--- a/configurationengine/source/cone/public/_plugin_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/_plugin_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,7 +16,8 @@
import copy
import logging
-import plugin, exceptions, api, utils
+from cone.public import exceptions, api, utils
+import plugin
import cone.confml.model
log = logging.getLogger('cone')
@@ -33,10 +34,11 @@
Class representing a temporary variable definition in an implementation file.
"""
- def __init__(self, ref, type, value):
+ def __init__(self, ref, type, value, lineno=None):
self.ref = ref
self.type = type
self.value = value
+ self.lineno = lineno
def create_feature(self, config):
"""
@@ -54,7 +56,8 @@
'int' : cone.confml.model.ConfmlIntSetting,
'real' : cone.confml.model.ConfmlRealSetting,
'boolean': cone.confml.model.ConfmlBooleanSetting}
- feature = mapping[self.type](ref)
+ # Create temp variables always name being also the ref
+ feature = mapping[self.type](ref, name=ref)
setattr(feature, TEMP_FEATURE_MARKER_VARNAME, True)
config.add_feature(feature, namespace)
@@ -81,9 +84,10 @@
Class representing a temporary variable sequence definition in an implementation file.
"""
- def __init__(self, ref, sub_items):
+ def __init__(self, ref, sub_items, lineno=None):
self.ref = ref
self.sub_items = sub_items
+ self.lineno = lineno
def create_feature(self, config):
if '.' in self.ref:
@@ -95,7 +99,8 @@
namespace = ''
# Creature the sequence feature
- seq_fea = api.FeatureSequence(ref)
+ # Create temp variables always name being also the ref
+ seq_fea = api.FeatureSequence(ref, name=ref)
setattr(seq_fea, TEMP_FEATURE_MARKER_VARNAME, True)
config.add_feature(seq_fea, namespace)
@@ -106,7 +111,7 @@
'boolean': cone.confml.model.ConfmlBooleanSetting}
sub_features = []
for sub_item in self.sub_items:
- sub_feature = mapping[sub_item[1]](sub_item[0])
+ sub_feature = mapping[sub_item[1]](sub_item[0], name=sub_item[0])
seq_fea.add_feature(sub_feature)
def __eq__(self, other):
@@ -183,11 +188,13 @@
"""
Extend this object with the contents of another CommonImplmlData object.
"""
+ if other is None:
+ return
+
if other.phase:
self.phase = other.phase
if other.tags:
self.tags = other.tags
- self.tempvar_defs.extend(other.tempvar_defs)
if other.setting_refs_override:
self.setting_refs_override = other.setting_refs_override
if other.output_root_dir:
@@ -198,7 +205,7 @@
def copy(self):
result = CommonImplmlData()
result.phase = self.phase
- if result.tags is not None:
+ if self.tags is not None:
result.tags = self.tags.copy()
result.tempvar_defs = list(self.tempvar_defs)
result.setting_refs_override = copy.deepcopy(self.setting_refs_override)
@@ -453,8 +460,7 @@
def read_data(cls, etree):
"""
Read common ImplML data from the given XML element.
- @return: A CommonImplmlData instance or None if no common namespace
- elements were found.
+ @return: A CommonImplmlData instance.
"""
result = CommonImplmlData()
@@ -466,17 +472,14 @@
'outputRootDir' : cls._read_output_root_dir,
'outputSubDir' : cls._read_output_sub_dir}
- found = False
for elem in etree:
ns, tag = utils.xml.split_tag_namespace(elem.tag)
if ns != COMMON_IMPLML_NAMESPACE: continue
if tag not in reader_methods: continue
reader_methods[tag](elem, result)
- found = True
- if found: return result
- else: return None
+ return result
@classmethod
def _read_phase(cls, elem, result):
@@ -502,13 +505,14 @@
ref = elem.get('ref')
type = elem.get('type', 'string')
value = elem.get('value', '')
+ lineno = utils.etree.get_lineno(elem)
if ref is None:
cls._raise_missing_attr(elem, 'ref')
if type not in cls.VALID_TYPES:
cls._raise_invalid_type(ref, type)
- result.tempvar_defs.append(TempVariableDefinition(ref, type, value))
+ result.tempvar_defs.append(TempVariableDefinition(ref, type, value, lineno))
@classmethod
def _read_tempvarseq(cls, elem, result):
@@ -531,7 +535,9 @@
if not sub_items:
raise exceptions.ParseError("Temporary variable sequence '%s' does not have any sub-items" % ref)
- result.tempvar_defs.append(TempVariableSequenceDefinition(ref, sub_items))
+ lineno = utils.etree.get_lineno(elem)
+
+ result.tempvar_defs.append(TempVariableSequenceDefinition(ref, sub_items, lineno))
@classmethod
def _read_setting_refs_override(cls, elem, result):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/api.py
--- a/configurationengine/source/cone/public/api.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/api.py Tue Aug 10 14:29:28 2010 +0300
@@ -1,3 +1,4 @@
+from __future__ import with_statement
#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
@@ -18,14 +19,15 @@
The core interface to the ConE functionality.
"""
-import os
import re
import sys
import logging
-import copy
-import sets
-
-import exceptions, utils, container, mapping
+import mimetypes
+
+from cone.public import exceptions, utils, container, mapping
+
+def get_file_logger():
+ return logger
class Base(container.ObjectContainer):
"""
@@ -38,14 +40,34 @@
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))
-
+ try:
+ for arg in kwargs.keys():
+ if kwargs.get(arg) != None:
+ setattr(self, arg, kwargs.get(arg))
+ except AttributeError,e:
+ raise e
+
def __repr__(self):
dict = self._dict()
return "%s(%s)" % (self.__class__.__name__, dict)
+# def __reduce_ex__(self, protocol_version):
+# tpl = super(Base, self).__reduce_ex__(protocol_version)
+# return tpl
+
+# def __getstate__(self):
+# state = self._dict(internals=True, ignore_empty=True)
+# # pop out the _name so that it wont appear as redundant data (ref is the same)
+# state.pop('_name', None)
+# state.pop('_parent', None)
+# return state
+#
+# def __setstate__(self, state):
+# super(Base, self).__setstate__(state)
+# self.ref = state.get('ref','')
+# for arg in state.keys():
+# self.__dict__.setdefault(arg, state.get(arg))
+
def _get_mapper(self,modelname):
"""
Return a instance of appropriate mapper for given model.
@@ -108,16 +130,23 @@
obj._add(child._clone(**kwargs), container.APPEND)
return obj
- def _dict(self):
+ def _dict(self, **kwargs):
"""
Return the public variables in a dictionary
"""
dict = {}
- for key in self.__dict__.keys():
- if key.startswith('_'):
+ # loop through the items in this object internal __dict__
+ # and add all except internal variables and function overrides
+ for (key,value) in self.__dict__.items():
+ if not kwargs.get('internals', False) and key.startswith('_'):
continue
+ elif not kwargs.get('callables', False) and callable(value):
+ continue
+ elif kwargs.get('ignore_empty') and not value:
+ # ignore empty values
+ pass
else:
- dict[key] = self.__dict__[key]
+ dict[key] = value
return dict
def _default_object(self, name):
@@ -152,6 +181,27 @@
paths.reverse()
return utils.dottedref.join_refs(paths)
+ def path(self, toparent=None):
+ """
+ Get the path to this Base object..
+ @param toparent: the _parent object up to which the path is relative. Default value is None.,
+ which gives the fully qualified path in the topology.
+ @return: The path to this Base object from toparent
+ """
+ return self._path(toparent)
+
+ def parent_path(self, toparent=None):
+ """
+ Get the path to the parent of this Base object..
+ @param toparent: the _parent object up to which the path is relative. Default value is None.,
+ which gives the fully qualified path in the topology.
+ @return: The path to this Base object from toparent
+ """
+ if self._parent != None:
+ return self._parent.path(toparent)
+ else:
+ return ''
+
def get_fullref(self):
"""
Return a full reference, reference including a
@@ -240,6 +290,23 @@
else:
return None
+ def get_configuration(self):
+ """
+ Return the containing configuration of this object.
+ """
+ parent = self._find_parent_or_default(type=Configuration)
+ return parent
+
+ def get_configuration_path(self):
+ """
+ Return the path of containing configuration of this object.
+ """
+ parent = self._find_parent_or_default(type=Configuration)
+ try:
+ return parent.get_full_path()
+ except AttributeError:
+ return None
+
def get_index(self):
"""
@return : the index of the data element for sequential data defined inside the same configuration.
@@ -293,6 +360,27 @@
"""
return None
+ def get_store_interface(self):
+ # if the project cannot be retrieved return None
+ try:
+ return self.get_project()
+ except exceptions.NotFound:
+ return None
+
+ def get_id(self):
+ try:
+ return self._id
+ except AttributeError:
+ return None
+
+ def set_id(self,value):
+ self._id = value
+
+ def del_id(self):
+ delattr(self,'_id')
+
+ """ The id as a property """
+ id = property(get_id,set_id, del_id)
class Project(Base):
"""
@@ -309,10 +397,17 @@
self._model = storage.persistentmodule.MODEL
except AttributeError:
self._model = None
-
+ self.loaded = {}
self.set_storage(storage)
self.update()
- self.loaded = {}
+
+ def __getstate__(self):
+ state = {}
+ state['storage'] = self.storage
+ return state
+
+ def __setstate__(self, state):
+ self.__init__(state['storage'])
def __add_loaded__(self, ref, obj):
"""
@@ -353,8 +448,10 @@
return True
else:
return False
- else:
- return True
+ else:
+ # Return False in case the object is loaded at all in this project
+ # increases performance as unloading is not done on unchanged objects
+ return False
def _supported_type(self, obj):
if isinstance(obj, Configuration) \
@@ -383,10 +480,9 @@
"""
Set the Storage instance of this Project.
"""
- if isinstance(storage, Storage):
- self.storage = storage
- else:
+ if storage != None and not isinstance(storage, Storage):
raise exceptions.StorageException("The given storage is not a instance of Storage!")
+ self.storage = storage
def list_configurations(self, filter_or_filters=None):
"""
@@ -418,7 +514,9 @@
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))]
+ # TODO
+ # huge performance problem
+ return [obj.get_full_path() for obj in self._traverse(type=(Configuration, ConfigurationProxy))]
def get_configuration(self, path):
"""
@@ -445,27 +543,44 @@
"""
# 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):
+ #
+ try:
+ return self.storage.is_resource(path)
+ except exceptions.NotSupportedException:
+ return path in self.list_configurations()
+
+ def add_configuration(self, config, overwrite_existing=False):
"""
Add a Configuration object to this project
- """
+ @param config: The configuration object to add
+ @param overwrite_existing: When this is set true any existing configuration is
+ overwritten.
+ """
if isinstance(config, Configuration):
- if self.is_configuration(config.get_path()):
+ if not overwrite_existing and self.is_configuration(config.get_path()):
raise exceptions.AlreadyExists("%s" % config.get_path())
- self._add(config)
+
+ proxy = ConfigurationProxy(config.path)
+ proxy._set_obj(config)
+ self._add(proxy)
+ #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=""):
+ def create_configuration(self, path, overwrite_existing=False, **kwargs):
"""
Create a Configuration object to this project
- """
- config = self.get_configuration_class()(utils.resourceref.norm(path), namespace=namespace)
- self.add_configuration(config)
+ @param path: The path of the new configuration file
+ @param overwrite_existing: When this is set true any existing configuration is
+ overwritten.
+ @param **kwargs: normal keyword arguments that are passed on to the newly
+ created Configuration object. See Configuration object constructor description on what
+ you can pass on here.
+ """
+ config = self.get_configuration_class()(utils.resourceref.norm(path), **kwargs)
+ self.add_configuration(config, overwrite_existing)
return config
def remove_configuration(self, path):
@@ -487,7 +602,7 @@
self.storage.import_resources(configuration.list_resources(), configuration.get_storage())
return
- def export_configuration(self, configuration, export_storage, empty_folders=False):
+ def export_configuration(self, configuration, export_storage, **kwargs):
"""
Export a configuration object to another storage
"""
@@ -504,8 +619,9 @@
#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)
+ for related in configuration.get_layer().list_all_related(**kwargs)]
+
+ self.storage.export_resources(resr ,export_storage, kwargs.get("empty_folders", False))
return
def get_configuration_class(self):
@@ -545,7 +661,7 @@
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))
+ configuration.set_ref(utils.resourceref.to_dref(path))
self.__add_loaded__(path, configuration)
""" increase the ref counter """
self.__loaded__(path)
@@ -560,6 +676,15 @@
"""
if self.__unloaded__(path):
self.get_storage().unload(path, object)
+ # remove the configuration from this this project,
+ # with proxy set the _obj reference to None
+ try:
+ conf = self.get_configuration(path)
+ if isinstance(conf, ConfigurationProxy):
+ conf._set_obj(None)
+ except exceptions.NotFound:
+ # if the configuration is not found at all then ignore the resetting
+ pass
def get_path(self):
"""
@@ -578,6 +703,9 @@
super(CompositeConfiguration, self).__init__(ref, **kwargs)
self.container = True
+ def _configuration_class(self):
+ return Configuration
+
def add_configuration(self, config):
"""
Add an existing Configuration to this configuration
@@ -587,9 +715,23 @@
"""
Merge the default view features from added config to this configs _default_view.
"""
- self._add(config)
-
- def include_configuration(self, configref):
+ # if the Configuration has a separate resource path, add it automatically behind proxy
+ if utils.resourceref.is_path(config.path) and isinstance(config, Configuration):
+ proxy = ConfigurationProxy(config.path)
+ proxy._set_obj(config)
+ self._add(proxy)
+ # Add the new configuration to the list of "modified/loaded" configurations
+ try:
+ prj = self.get_project()
+ prj.__add_loaded__(config.get_full_path(), config)
+ prj.__loaded__(config.get_full_path())
+ except exceptions.NotFound:
+ # if the parent is not found this configuration is not (yet) a part of project and cant be stored
+ pass
+ else:
+ self._add(config)
+
+ def include_configuration(self, configref, policy=0):
"""
Add an existing Configuration to this configuration by its resource reference
@param config: A Configuration instance:
@@ -597,7 +739,7 @@
"""
# add the configuration load proxy to this configuration instead
# adding the configuration directly
- self._add(ConfigurationProxy(configref))
+ self._add(ConfigurationProxy(configref), policy)
def create_configuration(self, path):
"""
@@ -611,11 +753,9 @@
"""
# normalise the path
normpath = utils.resourceref.norm(path)
- cklass = self.get_configuration_class()
+ cklass = self._configuration_class()
conf = cklass(normpath, namespace=self.namespace)
- proxy = ConfigurationProxy(normpath)
- self.add_configuration(proxy)
- proxy._set_obj(conf)
+ self.add_configuration(conf)
return conf
def remove_configuration(self, path):
@@ -636,9 +776,7 @@
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))]
+ return [config.get_path_for_parent(self) for config in self._traverse(type=(Configuration, ConfigurationProxy))]
def get_configuration(self, path):
"""
@@ -667,17 +805,6 @@
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
@@ -690,18 +817,41 @@
if isinstance(child, Configuration):
self.add_configuration(child)
elif isinstance(child, ConfigurationProxy):
- self.add_configuration(child)
+ self._add(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.
- """
+ def layered_resources(self, layers=None, empty_folders=False, folder=None, resource_type=None):
+ """
+ Fetch resource paths by layers so that if a resource with the same name
+ exists on multiple layers, the one on the latest layer is the active one.
+ @param layers: List of layer indices to specify the layer to use, None
+ for all layers.
+ @param empty_folders: If True, empty folders are returned also.
+ @param folder: Name of a specific folder from which to get resources, or None.
+ If None, resource_type must be specified.
+ @param resource_type: Type of the resources to find. Must be one of
+ ('confml', 'implml', 'content', 'doc') or None.
+ If None, folder must be specified.
+ @return: A container.DataContainer instance containing the resource paths.
+ For example: {'foo.txt': ['layer1/content/foo.txt',
+ 'layer2/content/foo.txt'],
+ 'bar.txt': ['layer1/content/bar.txt']}
+ """
+ MAPPING = {'confml': lambda layer: layer.confml_folder(),
+ 'implml': lambda layer: layer.implml_folder(),
+ 'content': lambda layer: layer.content_folder(),
+ 'doc': lambda layer: layer.doc_folder()}
+ if resource_type is not None and resource_type not in MAPPING:
+ raise ValueError("Invalid resource type %r, should be one of %r" % (resource_type, MAPPING.keys()))
+
+ if folder and resource_type:
+ raise ValueError('Only one of folder and resource_type must be specified!')
+ if not folder and not resource_type:
+ raise ValueError('Either folder or resource_type must be specified!')
+
configuration_array = []
if layers == None:
configuration_array = self.list_configurations()
@@ -709,18 +859,43 @@
all = self.list_configurations()
for i in layers:
configuration_array.append(all[i])
-
- content = container.DataContainer()
+
+ # Add the current configuration as the last one in the list, in case
+ # the current configuration happens to be a layer root itself
+ configuration_array.append('')
+
+ # Set up the get_folder function based on the parameters
+ if resource_type:
+ get_folder = MAPPING[resource_type]
+ else:
+ def get_folder(layer):
+ cpath = layer.get_current_path()
+ return Folder(layer.storage, utils.resourceref.join_refs([cpath, folder]))
+
+ result = 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
-
-
+ folder_obj = get_folder(self.get_configuration(configuration_path).get_layer())
+ folder_path = folder_obj.get_current_path()
+ for res_path in folder_obj.list_resources("", recurse=True, empty_folders=empty_folders):
+ if res_path == '': continue # ZipStorage sometimes returns empty paths
+ res_fullpath = utils.resourceref.join_refs([folder_path, res_path])
+ result.add_value(res_path, res_fullpath)
+ return result
+
+ def layered_confml(self, layers=None, empty_folders=False):
+ return self.layered_resources(layers, empty_folders, resource_type='confml')
+
+ def layered_implml(self, layers=None, empty_folders=False):
+ return self.layered_resources(layers, empty_folders, resource_type='implml')
+
+ def layered_content(self, layers=None, empty_folders=False):
+ return self.layered_resources(layers, empty_folders, resource_type='content')
+
+ def layered_doc(self, layers=None, empty_folders=False):
+ return self.layered_resources(layers, empty_folders, resource_type='doc')
+
+
+
class Configuration(CompositeConfiguration):
"""
A Configuration is a container that can hold several Layer objects.
@@ -729,12 +904,33 @@
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.name = kwargs.get('name',utils.resourceref.to_objref(self.path))
+ self.version = kwargs.get('version')
+ super(Configuration, self).__init__(utils.resourceref.to_objref(self.path), **kwargs)
self.container = True
+ def __reduce_ex__(self, protocol_version):
+ """
+ Make the Configuration pickle a ConfigurationProxy object that would load this configuration
+ """
+ proxy = ConfigurationProxy(self.path, store_interface = self.get_project())
+ tpl = proxy.__reduce_ex__(protocol_version)
+ return tpl
+
+ def __getstate__(self):
+ return None
+
def _default_object(self, name):
- return Feature(name)
+ return self._default_class()(name)
+
+ def _default_class(self):
+ return self._feature_class()
+
+ def _feature_class(self):
+ return Feature
+
+ def _view_class(self):
+ return View
def _supported_type(self, obj):
if isinstance(obj, Configuration) \
@@ -747,16 +943,11 @@
else:
return False
- def _dict(self):
+ def _dict(self, **kwargs):
"""
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 = super(Configuration, self)._dict(**kwargs)
dict['namespace'] = self.namespace
return dict
@@ -783,10 +974,8 @@
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
@@ -796,7 +985,19 @@
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_path_for_parent(self, parent):
+ """
+ Return the path to this configuration for a defined parent Configuration object.
+ """
+ parent_path = ""
+ try:
+ parentconfig = self._find_parent(type=Configuration)
+ if parent != parentconfig:
+ parent_path = utils.resourceref.get_path(parentconfig.get_path_for_parent(parent))
+ except exceptions.NotFound:
+ pass
return utils.resourceref.join_refs([parent_path, self.path])
def get_layer(self):
@@ -821,7 +1022,6 @@
@param namespace: The new namespace of the object
"""
self._namespace = namespace
- #self.root.set_namespace(namespace)
def get_namespace(self):
"""
@@ -836,7 +1036,7 @@
self._namespace = None
namespace = property(get_namespace, set_namespace, del_namespace)
- def list_resources(self, empty_folders=False):
+ def list_resources(self, **kwargs):
"""
List all resources used in this configuration
"""
@@ -848,10 +1048,10 @@
resources = [self.get_full_path()]
- for config in self._traverse(type=Configuration):
+ for config in self._traverse(type=(Configuration,ConfigurationProxy)):
resources.append(config.get_full_path())
layer = self.get_layer()
- for resref in layer.list_all_resources(empty_folders):
+ for resref in layer.list_all_resources():
resources.append(utils.resourceref.join_refs([layer.get_current_path(), resref]))
return utils.distinct_array(resources)
@@ -891,6 +1091,18 @@
"""
return self._get(ref)
+ def create_feature(self, ref, **kwargs):
+ """
+ Create a feature object to the configuration.
+ @param ref: The ref for the Feature object.
+ @param **kwargs: keyword arguments
+ e.g. to add fea2 under fea1 add_feature(fea2, 'fea1')
+ @return: the new feature object.
+ """
+ fea = self._feature_class()(ref, **kwargs)
+ self._add(fea)
+ return fea
+
def add_feature(self, feature, namespace=""):
"""
Add a feature object to the configuration.
@@ -899,7 +1111,11 @@
e.g. to add fea2 under fea1 add_feature(fea2, 'fea1')
@return: None
"""
- self._add_to_path(namespace, feature)
+ if namespace and self._has(namespace):
+ # Add the feature directly with an existing feature's add_feature functionality
+ self.get_feature(namespace).add_feature(feature)
+ else:
+ self._add_to_path(namespace, feature)
def remove_feature(self, ref):
"""
@@ -927,13 +1143,27 @@
def add_data(self, data, policy=container.REPLACE):
"""
Add a data object to this configuration object.
- @param data: The Data object to add.
+ @param data: The Data object or list of Data objects 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)
+ """
+ data_objs = utils.get_list(data)
+
+ if policy == container.PREPEND:
+ data_objs = reversed(data_objs)
+ policy_first = container.PREPEND
+ policy_rest = container.PREPEND
+ else:
+ policy_first = policy
+ policy_rest = container.APPEND
+
+ for i, data_obj in enumerate(data_objs):
+ if not self._has(data_obj.attr):
+ self._add(DataContainer(data_obj.attr, container=True))
+ (namespace, name) = utils.dottedref.psplit_ref(data_obj.get_fearef())
+
+ if i == 0: p = policy_first
+ else: p = policy_rest
+ self._get(data_obj.attr)._add_to_path(namespace, data_obj, p)
def get_data(self, ref):
"""
@@ -1009,13 +1239,24 @@
view.populate()
return view
- def add_view(self, viewname):
+ def create_view(self, viewname):
+ """
+ Create a view object to the configuration.
+ @param viewname: The name of the view to add.
+ @return: view object
+ """
+ viewobj = self._view_class()(viewname)
+ self.add_view(viewobj)
+ return viewobj
+
+ def add_view(self, viewobj):
"""
Add a view object to the configuration.
- @param viewname: The name of the view to add.
+ @param viewobj: The existing view object to add.
@return: None
"""
- return self._add(View(viewname))
+ assert(isinstance(viewobj, View))
+ return self._add(viewobj)
def remove_view(self, ref):
"""
@@ -1038,10 +1279,13 @@
Save the object to the permanent Storage object. Calls the save operation of
all the children.
"""
+ # Change the recursion order so that the current object
+ # is saved first and then its childen.
+ # This increases performance in cases where this object requires information about its childen (no unload -> load cases)
+ self.get_project().unload(self.get_full_path(), self)
for child in self._objects():
if isinstance(child, (Configuration,ConfigurationProxy)):
child.save()
- self.get_project().unload(self.get_full_path(), self)
def close(self):
"""
@@ -1077,13 +1321,13 @@
This returns always the view from the Root configuration point of view.
"""
try:
- parent = self._find_parent_or_default()
+ parent = self._find_parent_or_default()
if parent and isinstance(parent, Configuration):
return parent.get_default_view()
else:
- if not hasattr(self, '_default_view'):
+ if not self._has('?default_view'):
self._create_default_view()
- return self._default_view
+ return self._get('?default_view')
except exceptions.NotFound, e:
raise e
# raise exceptions.NotFound("Default View is not found! No root configuration?")
@@ -1101,17 +1345,19 @@
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
+ default_view = View("?default_view", data=True)
+ #self._default_view._parent= self
+ self._add(default_view)
# 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)
+ # TODO print "Adding : %s -> %s" % (child.namespace, child)
+ 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 = default_view.get_feature(child.fqr)
fea.add_data(child)
except exceptions.NotFound, e:
data_parent_config = child._find_parent_or_default(type=Configuration)
@@ -1128,9 +1374,15 @@
The ConfigurationProxy trust to get the store_interface from the parent object with get_storage() function.
"""
- container.LoadProxy.__init__(self, path)
+ super(ConfigurationProxy,self).__init__(path, **kwargs)
self.set('_name', utils.resourceref.to_objref(path))
+ def __reduce_ex__(self, protocol_version):
+ """
+ Make the Configuration pickle a ConfigurationProxy object that would load this configuration
+ """
+ return super(ConfigurationProxy, self).__reduce_ex__(protocol_version)
+
def _clone(self, **kwargs):
"""
A ConfigurationProxy specific implementation for cloning.
@@ -1152,7 +1404,7 @@
newobj = self._get_obj()._clone(**kwargs)
obj._set_obj(newobj)
return obj
-
+
def _dict(self):
"""
Return the public variables in a dictionary
@@ -1164,7 +1416,7 @@
else:
dict[key] = self.__dict__[key]
return dict
-
+
def _get_mapper(self,modelname):
"""
Return a instance of appropriate mapper for given model.
@@ -1177,32 +1429,27 @@
"""
def __init__(self, ref="", **kwargs):
super(Group, self).__init__(ref, **kwargs)
- self.name = ref
+ self.name = kwargs.get('name', ref)
self.support_data = kwargs.get("data", False)
def _supported_type(self, obj):
if isinstance(obj, (Group, \
Base, \
_FeatureProxy, \
- FeatureLink)):
+ FeatureLink, \
+ ConfigurationProxy)):
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
+ return self._group_class()(name)
+
+ def _group_class(self):
+ return Group
+
+ def _featurelink_class(self):
+ return FeatureLink
def add(self, child, policy=container.REPLACE):
"""
@@ -1213,10 +1460,7 @@
@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)):
+ if self._supported_type(child):
self._add(child)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
@@ -1233,6 +1477,21 @@
"""
self.name = name
+ def create_featurelink(self, feature_ref, **kwargs):
+ """
+ create a feature link object to this element, with the given ref
+ @param feature_ref: the reference for the featurelink which should
+ point to a exising feature in the configuration.
+ @param **kwargs: keyword arguments are passed to the featurelink object
+ directly.
+ """
+ fealink = self._featurelink_class()(feature_ref, **kwargs)
+ self.add(fealink)
+ return fealink
+
+ def get_featurelink(self, ref):
+ return self._get(FeatureLink.get_featurelink_ref(ref))
+
def add_feature(self, feature, path=""):
"""
Add feature to this Group.
@@ -1260,26 +1519,65 @@
except exceptions.NotFound:
raise exceptions.NotFound("Feature '%s' not found." % ref)
- def get_features(self, ref, **kwargs):
+ def get_features(self, refs, **kwargs):
"""
Get a list of features that match the ref.
+
+ @param refs: The paths (refs) to the given feature or xpath like expression. The refs
+ argument can be a single reference or a list of references to features.
+ @return: A list of features.
+
+ NOTE! the invalid references will not raise an exception.
+
Example1: get_features('foo.bar') would be the same as get_feature('foo.bar'), but this returns
always a list [].
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
+ Example4: get_features(['foo','bar.set1']) would try to retrieve a foo and then bar.set1.
+
+ """
+
+ if utils.is_list(refs):
+ features = []
+ for ref in refs:
+ features += self.get_matching_features(ref, **kwargs)
+ return features
+ else:
+ return self.get_matching_features(refs, **kwargs)
+
+ def get_matching_features(self, ref, **kwargs):
+ """
+ Get a list of features that match the ref.
+
+ @param refs: The paths (refs) to the given feature or xpath like expression. The refs
+ argument can be a single reference or a list of references to features.
@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)]
-
+
+ NOTE! the invalid references will not raise an exception but return an empty list.
+
+ Example1: get_features('foo.bar') would be the same as get_feature('foo.bar'), but this returns
+ always a list [].
+ 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.
+
+ """
+ try:
+ (startref, last) = utils.dottedref.psplit_ref(ref)
+ startelem = self._get(startref)
+ kwargs['type'] = _FeatureProxy
+ if last == '**':
+ return [fea for fea in startelem._traverse(**kwargs)]
+ elif last == '*':
+ return [fea for fea in startelem._objects(**kwargs)]
+ elif ref != "":
+ return [self._get(ref)]
+ else:
+ return []
+ except exceptions.NotFound:
+ return []
+
def list_features(self):
"""
Return a array of all Feature children references under this object.
@@ -1292,10 +1590,20 @@
"""
return [fea.fqr for fea in self._traverse(type=(_FeatureProxy))]
- def add_group(self, groupname):
- """
- """
- self._add(Group(groupname))
+ def create_group(self, groupname, **kwargs):
+ """
+ create a group object to this element with given group name.
+ @param groupname: the name for the new group
+ @param **kwargs: keyword arguments are passed on to the new group object.
+ """
+ grp = self._group_class()(groupname, **kwargs)
+ self.add_group(grp)
+ return grp
+
+ def add_group(self, grp):
+ """
+ """
+ self._add(grp)
def remove_group(self, ref):
"""
@@ -1313,7 +1621,7 @@
def list_groups(self):
"""
"""
- return [group.get_name() for group in self._objects(type=Group)]
+ return [group.ref for group in self._objects(type=Group)]
def populate(self):
"""
@@ -1332,7 +1640,6 @@
"""
def __init__(self, ref="", **kwargs):
super(View, self).__init__(self.to_ref(ref), **kwargs)
- self.name = ref
self.container = True
@classmethod
@@ -1350,8 +1657,10 @@
PROPERTIES = ['value']
def __init__(self, ref="", **kwargs):
super(Feature, self).__init__(ref, **kwargs)
- self.name = kwargs.get('name', ref)
+ self.name = kwargs.get('name', None)
self.type = kwargs.get('type', None)
+ self.relevant = kwargs.get('relevant', None)
+ self.constraint = kwargs.get('constraint', None)
self._dataproxy = None
def __copy__(self):
@@ -1364,7 +1673,17 @@
fea = self.__class__(self.ref, **dict)
return fea
-
+ def __getstate__(self):
+ state = super(Feature, self).__getstate__()
+ # remove the dataproxy value so that it is not stored in serializings
+ state.pop('_dataproxy', None)
+ return state
+
+ def __setstate__(self, state):
+ super(Feature, self).__setstate__(state)
+ self._dataproxy = None
+
+
def _supported_type(self, obj):
# For now support added for desc element via support for Base
if isinstance(obj, (Feature, Option, Base)):
@@ -1372,6 +1691,9 @@
else:
return False
+ def _feature_class(self):
+ return Feature
+
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
@@ -1387,6 +1709,8 @@
self._add(child, policy)
elif isinstance(child, Base):
self._add(child, policy)
+ elif isinstance(child, Property):
+ self._add(child, policy)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
@@ -1402,22 +1726,53 @@
"""
self.name = name
+ def get_relevant(self):
+ """
+ Return the relevant attribute of the feature
+ """
+ return self.relevant
+
+ def set_relevant(self, relevant):
+ """
+ Set the relevant attribute
+ """
+ self.relevant = relevant
+
+ def get_constraint(self):
+ """
+ Return the constraint attribute of the feature
+ """
+ return self.constraint
+
+ def set_constraint(self, constraint):
+ """
+ Set the constraint attribute
+ """
+ self.constraint = constraint
+
def get_type(self):
return self.type
def set_type(self, type):
self.type = type
+ def create_feature(self, ref, **kwargs):
+ """
+ Create a feature object to the configuration.
+ @param ref: The ref for the Feature object.
+ @param **kwargs: keyword arguments
+ e.g. to add fea2 under fea1 add_feature(fea2, 'fea1')
+ @return: the new feature object.
+ """
+ fea = self._feature_class()(ref, **kwargs)
+ self.add_feature(fea)
+ return fea
+
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)
+ self._add_to_path(path, feature)
def get_feature(self, path):
"""
@@ -1430,12 +1785,7 @@
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)
+ self._remove(ref)
def list_features(self):
"""
@@ -1491,40 +1841,107 @@
# Return option refs without the leading 'opt_'
return [opt.ref[4:] for opt in self._objects(type=Option)]
+ def add_property(self, property):
+ """
+ @param property: property object to add
+ """
+ if not isinstance(property, Property):
+ raise TypeError("%r is not an instance of Property!" % property)
+ self._add(property)
+
+ def create_property(self, **kwargs):
+ """
+ @param name=str: property name
+ @param value=str: property value
+ @param unit=str: property unit, e.g. kB
+ """
+ self._add(Property(**kwargs))
+
+
+ def get_property(self, ref):
+ """
+ @param ref: The ref of the property
+ """
+ obj = self._get(Property.to_propertyref(ref))
+
+ if not isinstance(obj, Property):
+ raise TypeError('Object %r is not an instance of Property (%r instead)' % (Property.to_propertyref(ref), type(obj)))
+ return obj
+
+ def remove_property(self, ref):
+ """
+ remove a given property from this feature by ref.
+ @param ref:
+ """
+ obj = self._get(Property.to_propertyref(ref))
+ if not isinstance(obj, Property):
+ raise TypeError('Trying to remove property with ref %r, but object with ref %r is not an instance of Property (%s instead)' % (ref, Property.to_propertyref(ref), type(obj)))
+ self._remove(Property.to_propertyref(ref))
+
+ def list_properties(self):
+ """
+ Return a array of all Feature properties under this object.
+ """
+
+ return [Property.to_normref(property.ref) for property in self._objects(type=Property)]
+
def get_value(self, attr=None):
"""
- Get the current value of the feature
+ 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
+ return self.convert_data_to_value(self.dataproxy._get_datas(attr=attr), cast=True, attr=attr)
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)
-
+ data_objs = self.convert_value_to_data(value, attr)
+
+ # Set the created data objects to the dataproxy and the
+ # last configuration, overriding any existing elements
+ self.dataproxy._set_datas(data_objs, attr)
+ last_config = self.get_root_configuration().get_last_configuration()
+ last_config.add_data(data_objs, container.REPLACE)
+
+ def convert_data_to_value(self, data_objects, cast=True, attr=None):
+ """
+ Convert the given list of Data objects into a suitable value
+ for this setting.
+ @param data_objects: The Data object list.
+ @param cast: If True, the value should be cast to its correct Python type
+ (e.g. int), if False, the value should remain in the string form
+ it was in the data objects.
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ @return: The converted value.
+ """
+ if not data_objects: return None
+
+ data_obj = data_objects[-1]
+ if data_obj.map:
+ value = self._resolve_name_id_mapped_value(data_obj.map, cast_value=cast)
+ else:
+ value = data_obj.value
+ if cast: value = self.get_value_cast(value, attr)
+ return value
+
+ def convert_value_to_data(self, value, attr=None):
+ """
+ Convert the given value to a list of Data objects that can be placed
+ in the configuration's last layer's data section (DataContainer object).
+ @param value: The value to convert.
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ @return: The converted Data objects.
+ """
+ value = self.set_value_cast(value, attr)
+ return [Data(fqr=self.fqr, value=value, attr=attr)]
+
def del_value(self, attr=None):
"""
Delete the topmost value for this feature.
"""
- if not self.is_sequence():
- self.dataproxy._del_value(attr)
+ self.dataproxy._del_value(attr)
def get_value_cast(self, value, attr=None):
"""
@@ -1547,18 +1964,7 @@
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
+ return self.convert_data_to_value(self.dataproxy._get_datas(attr=attr), cast=False, attr=attr)
def add_data(self, data):
"""
@@ -1616,6 +2022,10 @@
except AttributeError:
return False
+ def is_sequence_root(self):
+ """ Return true if this feature is a sequence object it self """
+ return False
+
def get_sequence_parent(self):
""" Try to get a FeatureSequence object for this Feature if it is found """
try:
@@ -1630,7 +2040,163 @@
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)
+ """ Use custom OProperty to enable overriding value methods in subclasses """
+ value = utils.OProperty(get_value, set_value, del_value)
+
+ def get_column_value(self, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param ref: the reference to the column
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ """ get the feature specific data from sequence => a column of data table """
+ seq_parent = self.get_sequence_parent()
+ if seq_parent._has_empty_sequence_marker():
+ return []
+
+ coldata = []
+ colref = self.path(seq_parent)
+ for row in seq_parent.data:
+ feadata = row.get_feature(colref)
+ coldata.append(feadata.get_value(attr))
+ return coldata
+
+ def get_column_original_value(self, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param feasequence: the feature sequence object
+ @param ref: the reference to the column
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ """ get the feature specific data from sequence => a column of data table """
+ seq_parent = self.get_sequence_parent()
+ if seq_parent._has_empty_sequence_marker():
+ return []
+
+ coldata = []
+ colref = self.path(seq_parent)
+ for row in seq_parent.data:
+ feadata = row.get_feature(colref)
+ coldata.append(feadata.get_original_value(attr))
+ return coldata
+
+ def set_column_value(self, value, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param feasequence: the feature sequence object
+ @param ref: the reference to the column
+ @param value: the value to set. This must be a list instance.
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ seq_parent = self.get_sequence_parent()
+ colref = self.path(seq_parent)
+
+ if not isinstance(value,list):
+ raise exceptions.ConeException("The value for feature sequence '%s' column '%s' must be a list instance. Got %r" % (self.get_sequence_parent().fqr, colref, value))
+
+ # Handle the special case where the sequence is marked as empty
+ # with the empty sequence marker (single empty data element)
+ if seq_parent._has_empty_sequence_marker():
+ seqrows = []
+ else:
+ seqrows = seq_parent.data
+
+ if len(seqrows) < len(value):
+ raise exceptions.ConeException("Too many values for feature sequence '%s' column '%s'. Sequence holds only %d rows. Got %d data values in %r" % (self.get_sequence_parent().fqr, colref, len(seqrows), len(value), value))
+ for i in range(0, len(value)):
+ feadata = seqrows[i].get_feature(colref)
+ feadata.set_value(value[i])
+
+ def add_sequence_feature(self, feature, path=""):
+ """
+ Override of the add_feature function in sequence to set the sequence childs to act
+ as columns of the feature sequence
+ @param feature: The Feature object to add
+ @param path: path to feature if it not added directly under parent_fea
+ """
+ # modify all possible children of feature
+ for fea in feature._traverse(type=Feature):
+ to_sequence_feature(fea)
+
+ # Finally modify and add this feature to parent_feat
+ to_sequence_feature(feature)
+ self._add_to_path(path, feature)
+
+ def _resolve_name_id_mapped_value(self, mapping_string, cast_value=True):
+ """
+ Resolve the name-ID mapped value based on the given mapping string.
+ @param mapping_string: The name-ID mapping string in the data element, e.g.
+ "FooFeature/FooSequence[@key='123']"
+ @param cast_value: If True, the resolved value will be cast to the corresponding
+ Python type, otherwise the raw string representation of the value in the
+ data element will be returned.
+ @return: The resolved value.
+ """
+ def fail(msg): raise exceptions.NameIdMappingError(msg)
+
+ pattern = r"^([\w/]+)\[@key='(.*)'\]$"
+ m = re.match(pattern, mapping_string)
+ if m is None: fail("Malformed mapping expression: %s" % mapping_string)
+
+ source_seq_ref = m.group(1).replace('/', '.')
+ mapping_key = m.group(2)
+
+ dview = self.get_root_configuration().get_default_view()
+
+ try:
+ source_seq = dview.get_feature(source_seq_ref)
+ except exceptions.NotFound:
+ fail("Mapping source sequence '%s' does not exist" % source_seq_ref)
+
+ if source_seq.type != 'sequence':
+ fail("Mapping source setting '%s' is not a sequence setting" % source_seq_ref)
+ if not source_seq.mapKey or not source_seq.mapValue:
+ fail("Source sequence '%s' must have both mapKey and mapValue specified" % source_seq_ref)
+
+ def get_subsetting(ref):
+ """
+ Return the sub-setting by the given mapKey or mapValue ref from the
+ source sequence.
+ @param ref: The reference in the format it is in the ConfML file.
+ E.g. 'SubSetting', 'FileSubSetting/localPath', 'FileSubSetting/targetPath'
+ """
+ subsetting = source_seq.get_feature(ref.replace('/', '.'))
+ # Use localPath for file and folder settings by default
+ if subsetting.type in ('file', 'folder'):
+ subsetting = subsetting.get_feature('localPath')
+ return subsetting
+
+ try:
+ key_subsetting = get_subsetting(source_seq.mapKey)
+ except exceptions.NotFound:
+ fail("Invalid mapKey in source sequence '%s': no sub-setting with ref '%s'" % (source_seq_ref, source_seq.mapKey))
+
+
+ # Get possible override for mapValue from options
+ value_subsetting_ref = source_seq.mapValue
+ value_subsetting_ref_overridden = False
+ for opt in self._objects(type=Option):
+ if not opt.map or not opt.map_value: continue
+ if opt.map.replace('/', '.') == source_seq_ref:
+ value_subsetting_ref = opt.map_value
+ value_subsetting_ref_overridden = True
+
+ try:
+ value_subsetting = get_subsetting(value_subsetting_ref)
+ except exceptions.NotFound:
+ if value_subsetting_ref_overridden:
+ fail("Invalid mapValue override in option: sub-setting '%s' does not exist under source sequence '%s'" % (value_subsetting_ref, source_seq_ref))
+ else:
+ fail("Invalid mapValue in source sequence '%s': no sub-setting with ref '%s'" % (source_seq_ref, value_subsetting_ref))
+
+ key_list = key_subsetting.get_original_value()
+ if mapping_key not in key_list:
+ fail("No item-setting in source sequence '%s' matches key '%s'" % (source_seq_ref, mapping_key))
+
+ if cast_value: value_list = value_subsetting.get_value()
+ else: value_list = value_subsetting.get_original_value()
+ return value_list[key_list.index(mapping_key)]
+
class FeatureSequence(Feature):
POLICY_REPLACE = 0
@@ -1642,11 +2208,9 @@
dataelem_name = '?datarows'
template_name = '?template'
def __init__(self, ref="", **kwargs):
- super(FeatureSequence, self).__init__(ref)
+ super(FeatureSequence, self).__init__(ref, **kwargs)
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):
@@ -1665,8 +2229,8 @@
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 == ''):
+ # otherwise the policy is either replace or undefined
+ # (firstdata.policy == 'replace' or firstdata.policy == ''):
return self.POLICY_REPLACE
else:
return self.POLICY_APPEND
@@ -1675,7 +2239,6 @@
"""
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():
@@ -1690,11 +2253,19 @@
"""
Add a feature data row for a new data in this sequence
"""
+ create_sub_data_objs = True
if dataobj == None:
dataobj = Data(fqr=self.fqr)
elif dataobj.attr != 'data':
# Add data rows only for data objects (not e.g. RFS)
return
+ else:
+ # If the data object is given, but it doesn't contain any child
+ # elements, don't add them automatically. This is to account for the
+ # case where there is only one empty data element that specifies
+ # that the sequence is set to be empty
+ if len(dataobj._order) == 0:
+ create_sub_data_objs = False
fea = FeatureSequenceSub(self.dataelem_name)
rowproxy = _FeatureDataProxy(fea._name, fea)
""" the imaginary features share the parent relation of the proxy objects """
@@ -1707,13 +2278,32 @@
# 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)
+ subfea = self.get_feature(feaname)
+ cellfea = FeatureSequenceSub(fearef)
+ cellfea.set_value_cast = subfea.set_value_cast
+ cellfea.get_value_cast = subfea.get_value_cast
+ cellfea.convert_data_to_value = subfea.convert_data_to_value
+ cellfea.convert_value_to_data = subfea.convert_value_to_data
+ rowproxy.add_feature(cellfea, pathto_fea)
subproxy = rowproxy.get_feature(feaname)
- subproxy._obj._parent = subproxy._parent
- if not dataobj._has(feaname):
+ subproxy._obj._parent = subproxy._parent
+ if create_sub_data_objs and not dataobj._has(feaname):
dataobj._add_to_path(pathto_fea, Data(ref=fearef))
subproxy._add_data(dataobj._get(feaname))
-
+ return dataobj
+
+ def _has_empty_sequence_marker(self):
+ """
+ Return True if the sequence setting has the empty sequence marker (a single
+ empty data element), which denotes that the sequence is set to empty.
+ """
+ datatable = self.get_data()
+ if len(datatable) == 1:
+ data_elem = datatable[0].get_datas()[0]
+ if len(data_elem._order) == 0:
+ return True
+ return False
+
def add(self, child, policy=container.REPLACE):
"""
A generic add function to add child objects. The function is intended to act as
@@ -1731,38 +2321,83 @@
self._add(child)
else:
raise exceptions.IncorrectClassError("Cannot add %s to %s" % (child, self))
+
+ def add_feature(self, feature, path=""):
+ """
+ Override of the add_feature function in sequence to set the sequence childs to act
+ as columns of the feature sequence
+ @param feature: The Feature object to add
+ """
+ add_sequence_feature(self, feature, path)
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)
+ if self._has_empty_sequence_marker():
+ # We currently have the empty sequence marker (single empty data
+ # element), so this one that we are adding should replace it
+ policy = self.POLICY_REPLACE
+
+ datarow = self._add_datarow(None, policy)
+ # add the new data sequence/row to the last configuration layer
+ last_config = self.get_root_configuration().get_last_configuration()
+
+ container_policy = {self.POLICY_REPLACE: container.REPLACE,
+ self.POLICY_APPEND: container.APPEND,
+ self.POLICY_PREPEND: container.PREPEND}[policy]
+ last_config.add_data(datarow, container_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
+ if data[index] != None:
+ rowproxy[index].set_value(data[index])
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])
+ if data is None:
+ self._templatedata = None
+ return
+
+ if not isinstance(data, list):
+ raise TypeError('data must be a list (got %r)' % data)
+
+ # Create the new template data object
+ templatedata = Data(fqr=self.fqr, template=True)
+
+ # Add all sub-objects to the data object
+ def add_data_objects(feature, data_obj, value_list):
+ refs = feature.list_features()
+ if len(refs) != len(value_list):
+ raise ValueError("Data value list is invalid")
+ for i, ref in enumerate(refs):
+ value = value_list[i]
+ subfea = feature.get_feature(ref)
+ if isinstance(value, list):
+ subdata = Data(ref=ref)
+ data_obj.add(subdata)
+ add_data_objects(feature.get_feature(ref), subdata, value)
+ else:
+ if value is not None:
+ subdata = Data(ref=ref, value=subfea.set_value_cast(value))
+ data_obj.add(subdata)
+ add_data_objects(self, templatedata, data)
+
+ self._set_template_data(templatedata)
+
+ # Remove any existing template data
+ pconfig = self.find_parent(type=Configuration)
+ dataobjs = pconfig._traverse(type=Data, filters=[lambda x: x.template and x.fqr == self.fqr])
+ if dataobjs:
+ for dataobj in dataobjs:
+ dataobj._parent._remove(dataobj.get_fullref())
+
+ # Add the template data to the parent config (beginning of the data section)
+ pconfig.add_data(self._templatedata, policy=container.PREPEND)
def get_template(self):
"""
@@ -1771,7 +2406,19 @@
#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()]
+ def get_data_items(feature, data_obj):
+ refs = feature.list_features()
+ if refs:
+ result = []
+ for ref in refs:
+ if data_obj._has(ref):
+ result.append(get_data_items(feature.get_feature(ref), data_obj._get(ref)))
+ else:
+ result.append(None)
+ return result
+ else:
+ return data_obj.value
+ return get_data_items(self, self._templatedata)
else:
return None
@@ -1796,69 +2443,73 @@
# 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.
"""
+ if self._has_empty_sequence_marker():
+ return []
+
datatable = self.get_data()
- rettable = []
+ rettable = []
for row in datatable:
rowvalues = row.value
rettable.append(rowvalues)
return rettable
+ 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'
+ """
+ if self._has_empty_sequence_marker():
+ return []
+
+ datatable = self.get_data()
+ rettable = []
+ for row in datatable:
+ rowvalues = row.get_original_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)
+ if value:
+ # Add the first item with replace policy
+ self.add_sequence(value[0], self.POLICY_REPLACE)
+ for row in value[1:]:
+ self.add_sequence(row)
+ else:
+ # Setting the sequence to empty, so add one empty item-setting
+ # to signify that
+ self.add_sequence(None, self.POLICY_REPLACE)
+
+ # Strip all sub-elements from the data element just created,
+ # since the ConfML spec says that an empty sequence is denoted
+ # by a single empty data element
+ data_elem = self.get_data()[0].get_datas()[0]
+ for r in list(data_elem._order):
+ data_elem._remove(r)
def is_sequence(self):
""" Return always true from a sequence object """
return True
+ def is_sequence_root(self):
+ """ Return true if this feature is a sequence object it self """
+ return True
+
+ def get_column_features(self):
+ """ Return a list of sequence subfeature, which are the columns of the sequence """
+ columns = []
+ for subref in self.list_features():
+ columns.append(self.get_feature(subref))
+ return columns
+
def get_sequence_parent(self):
""" Return this object as a sequence parent """
return self
@@ -1866,12 +2517,84 @@
value = property(get_value, set_value)
data = property(get_data)
+
+def add_sequence_feature(parent_feature, feature, path=""):
+ """
+ Override of the add_feature function in sequence to set the sequence childs to act
+ as columns of the feature sequence
+ @param parent_feature: The parent feature where the feature object is added
+ @param feature: The Feature object to add
+ @param path: path to feature if it not added directly under parent_fea
+ """
+ # modify all possible children of feature
+ for fea in feature._traverse(type=Feature):
+ to_sequence_feature(fea)
+
+ # Finally modify and add this feature to parent_feat
+ to_sequence_feature(feature)
+ parent_feature._add_to_path(path, feature)
+
+def to_sequence_feature(feature):
+ """
+ modify a Feature object to sequence feature that will return column like data from a sequence.
+ @param feature: The Feature object for which is modified.
+ """
+ feature.get_value = feature.get_column_value
+ feature.get_original_value = feature.get_column_original_value
+ feature.set_value = feature.set_column_value
+ feature.add_feature = feature.add_sequence_feature
+
+def get_column_value(feasequence, ref, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param feasequence: the feature sequence object
+ @param ref: the reference to the column
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ """ get the feature specific data from sequence => a column of data table """
+ coldata = []
+ for row in feasequence.data:
+ feadata = row.get_feature(ref)
+ coldata.append(feadata.get_value(attr))
+ return coldata
+
+def get_column_original_value(feasequence, ref, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param feasequence: the feature sequence object
+ @param ref: the reference to the column
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ """ get the feature specific data from sequence => a column of data table """
+ coldata = []
+ for row in feasequence.data:
+ feadata = row.get_feature(ref)
+ coldata.append(feadata.get_original_value(attr))
+ return coldata
+
+def set_column_value(feasequence, ref, value, attr=None):
+ """
+ Get the value of the featuresequence column
+ @param feasequence: the feature sequence object
+ @param ref: the reference to the column
+ @param value: the value to set. This must be a list instance.
+ @param attr: The attribute name of the data. E.g. attr='data', attr='rfs'
+ """
+ if not isinstance(value,list):
+ raise exceptions.ConeException("The value for feature sequence '%s' column '%s' must be a list instance. Got %r" % (feasequence.fqr, ref, value))
+ seqrows = feasequence.data
+ if len(seqrows) < len(value):
+ raise exceptions.ConeException("Too many values for feature sequence '%s' column '%s'. Sequence holds only %d rows. Got %d data values in %r" % (feasequence.fqr, ref, len(seqrows), len(value), value))
+ for i in range(0, len(value)):
+ feadata = seqrows[i].get_feature(ref)
+ feadata.set_value(value[i])
+
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)
+ super(FeatureSequenceCell, self).__init__(ref)
self.name = kwargs.get('name', ref)
self.type = 'seqcell'
@@ -1897,11 +2620,16 @@
A Feature class. Feature is the base for all Configurable items in a Configuration.
"""
def __init__(self, ref="", **kwargs):
- super(Feature, self).__init__(ref)
+ super(FeatureSequenceSub, self).__init__(ref)
self.name = kwargs.get('name', ref)
self.type = 'subseq'
self._index = 0
+ def __getstate__(self):
+ state = super(FeatureSequenceSub,self).__getstate__()
+ state['_children'].pop('?datarows', None)
+ return state
+
def get_index(self):
"""
@return : the index of the data element for sequential data defined inside the same configuration.
@@ -1915,24 +2643,46 @@
@param value: the value row to set
"""
if utils.is_list(value):
- for subindex in range(0, len(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)
+ else:
+ data_objs = self.convert_value_to_data(value)
+ data_object_where_to_add = self._parent._get_data()
+
+ self.dataproxy._set_datas(data_objs, attr)
+ data_object_where_to_add._add(data_objs, container.REPLACE)
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())
+ # Handle empty sequences
+ if self.get_sequence_parent()._has_empty_sequence_marker():
+ return []
+
# 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)
-
+ return super(FeatureSequenceSub,self).get_value(attr)
+
+ 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'
+ """
+ # Handle empty sequences
+ if self.get_sequence_parent()._has_empty_sequence_marker():
+ return []
+
+ childdatas = self.dataproxy._objects()
+ if len(childdatas) > 0:
+ return [subdata.get_original_value() for subdata in childdatas]
+ else:
+ return self.dataproxy._get_value(attr)
+
value = property(get_value, set_value)
@@ -1941,14 +2691,49 @@
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):
+ """ class variable for defining the override attributes"""
+ override_attributes = ['name']
+ ref_prefix = 'link_'
+ PROXYREF_PREFIX = 'proxy_'
+
+ def __init__(self, ref="", **kwargs):
# Store the fully qualified reference to this object
- self.link = link
- ref = link.replace('.', '_')
- super(FeatureLink, self).__init__(ref)
+ self.link = kwargs.get('link', ref)
+ self.name = kwargs.get('name', None)
+ ref = self.get_featurelink_ref(self.link)
+ # the reference of this particular object
+ super(FeatureLink, self).__init__(ref, **kwargs)
self._obj = None
self._populated = False
+ def add(self, child, policy=container.REPLACE):
+ """
+ Add an override to enable adding any override attribute to a featurelink object.
+
+ 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, 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 featurelink
+ """
+ return self.name
+
+ def set_name(self, name):
+ """
+ Set the name
+ """
+ self.name = name
+
@property
def fqr(self):
return self.link
@@ -1962,14 +2747,58 @@
try:
if not self._populated:
feas = self.get_default_view().get_features(self.link)
+ # get the non wildcard part of ref
+ static_ref = utils.dottedref.get_static_ref(self.link)
# add the found features to the parent
for fea in feas:
- self._get_parent().add_feature(fea._obj)
+ override_attrs = {}
+ # override the FeatureProxy object with exactly same reference
+ # (in feat/* case dont override the children features)
+ if fea.fqr == static_ref:
+ override_attrs = self.get_attributes()
+ feature = fea._obj
+ proxy_ref = self.get_featureproxy_ref(feature.fqr)
+ proxy = _FeatureProxy(proxy_ref, feature, **override_attrs)
+ self._get_parent()._add(proxy)
+
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))
+ def get_attributes(self):
+ """
+ Returns a list of FeatureLink attributes that override settings of the original feature.
+ @return: a dictionary of attribute key : value pairs.
+ """
+ attrs = {}
+ for attr in self.override_attributes:
+ # try to get the attribute from this object
+ # and set it to the attribute list if it not None
+ try:
+ value = getattr(self, attr)
+ if value != None: attrs[attr] = value
+ except AttributeError:
+ pass
+ return attrs
+
+ @classmethod
+ def get_featurelink_ref(cls, ref):
+ """
+ return a featurelink ref from a feature ref.
+ This is needed to make the featurelink object refs unique in a container
+ that has Features.
+ """
+ return cls.ref_prefix + ref.replace('.', '_').replace('/','_')
+
+ @classmethod
+ def get_featureproxy_ref(cls, ref):
+ """
+ Return a ref for a given setting fqr to be used under a group.
+ This is needed to make the featureproxy object refs unique in a container
+ that has Features.
+ """
+ return cls.PROXYREF_PREFIX + ref.replace('.', '_').replace('/','_')
class _FeatureProxy(container.ObjectProxyContainer, Base):
"""
@@ -1977,10 +2806,10 @@
link to the actual Feature object.
"""
def __init__(self, ref="", obj=None, **kwargs):
- super(_FeatureProxy, self).__init__(obj, ref)
- Base.__init__(self, ref)
+ container.ObjectProxyContainer.__init__(self, obj, ref)
+ Base.__init__(self, ref, **kwargs)
self.support_data = False
-
+
def __getattr__(self, name):
"""
First check if the requested attr is a children then
@@ -1995,7 +2824,7 @@
return self._objects()[index]
def __setitem__(self, index, value):
- raise exceptions.NotSupported()
+ raise exceptions.NotSupportedException()
def __delitem__(self, index):
item = self.__getitem__(index)
@@ -2020,6 +2849,12 @@
"""
self._parent = newparent
+ def get_proxied_obj(self):
+ """
+ @return: Returns proxied object.
+ """
+ return self._obj
+
def add_feature(self, feature, path=""):
"""
"""
@@ -2061,7 +2896,65 @@
"""
pass
-
+ def has_attribute(self, name):
+ """
+ Perform a check whether an attribute with given name is stored inside the
+ _FeatureProxy. The check does not extend to the proxied (_obj) insanses or
+ children of this proxy.
+
+ @return: True when an attribute is a real attribute in this _FeatureProxy object.
+ """
+ return self.__dict__.has_key(name)
+
+ def get_option(self, ref):
+ """
+ @param name: The option reference of the option (as returned by list_options())
+ """
+ real_ref = 'opt_' + ref
+ for op in self.options.values():
+ if op.ref == real_ref:
+ return op
+ else:
+
+ obj = self.get_proxied_obj()._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 list_options(self):
+ """
+ Return a array of all Option children references under this object.
+ """
+ opts = self.get_proxied_obj().list_options()
+
+ for opt in self.options:
+ opts.append(self.options[opt].ref[4:])
+
+ return opts
+
+ def get_property(self, ref):
+ """
+ @param name: The property reference of the property (as returned by list_properties())
+ """
+ for prop in self.properties.values():
+ if prop.ref == Property.to_propertyref(ref):
+ return prop
+ else:
+ obj = self.get_proxied_obj()._get(Property.to_propertyref(ref))
+ return obj
+
+ def list_properties(self):
+ """
+ Return a array of all Property children references under this object.
+ """
+ props = self.get_proxied_obj().list_properties()
+
+ for pr in self.properties:
+ props.append(Property.to_normref(self.properties[pr].ref))
+
+ return props
+
+
class _FeatureDataProxy(_FeatureProxy):
"""
A Feature class. Feature is the base for all Configurable items in a Configuration.
@@ -2085,10 +2978,10 @@
"""
"""
if object.__getattribute__(self, '_obj') is not None:
- self._obj.dataproxy = self
+ self.get_proxied_obj().dataproxy = self
if name in Feature.PROPERTIES:
- return getattr(self._obj, name)
+ return getattr(self.get_proxied_obj(), name)
else:
return super(_FeatureDataProxy, self).__getattr__(name)
@@ -2096,10 +2989,10 @@
"""
"""
if object.__getattribute__(self, '_obj') is not None:
- self._obj.dataproxy = self
+ self.get_proxied_obj().dataproxy = self
if name in Feature.PROPERTIES:
- return setattr(self._obj, name, value)
+ return setattr(self.get_proxied_obj(), name, value)
else:
super(_FeatureDataProxy, self).__setattr__(name, value)
@@ -2107,15 +3000,19 @@
"""
"""
if name in Feature.PROPERTIES:
- return delattr(self._obj, name)
+ return delattr(self.get_proxied_obj(), name)
else:
return super(_FeatureDataProxy, self).__delattr__(name)
def _add_data(self, data):
"""
- Add a data value.
+ Add a data value or a list of data values.
@param data: A Data object
"""
+ if isinstance(data, list):
+ for d in data: self._add_data(d)
+ return
+
try:
self.datas[data.attr].append(data)
except KeyError:
@@ -2142,7 +3039,14 @@
Get the entire data array.
"""
dataattr = attr or self.defaultkey
- return self.datas[dataattr]
+ return self.datas.get(dataattr, [])
+
+ def _set_datas(self, datas, attr=None):
+ """
+ Set the entire data array.
+ """
+ dataattr = attr or self.defaultkey
+ self.datas[dataattr] = list(datas)
def _get_value(self, attr=None):
"""
@@ -2152,7 +3056,7 @@
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
@@ -2253,6 +3157,18 @@
self.policy = kwargs.get('policy', '')
self.template = kwargs.get('template', False)
self.map = kwargs.get('map')
+ self.empty = kwargs.get('empty', False)
+ self.lineno = None
+
+ def __setstate__(self, state):
+ super(Data, self).__setstate__(state)
+ self.value = state.get('value', None)
+ self.attr = state.get('attr', None)
+ self.policy = state.get('policy', '')
+ self.map = state.get('map', None)
+ self.template = state.get('template', False)
+ self.lineno = state.get('lineno', None)
+ self.fearef = state.get('fearef', None)
def get_fearef(self):
if self.fearef:
@@ -2261,14 +3177,7 @@
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
+ return self.value
def get_map(self):
return self.map
@@ -2279,18 +3188,6 @@
#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:
@@ -2303,7 +3200,7 @@
policy = property(get_policy, set_policy, del_policy)
-class ValueSet(sets.Set):
+class ValueSet(set):
"""
A value set object to indicate a set of possible values for a feature.
e.g. A boolean feature ValueSet([True, False])
@@ -2337,6 +3234,51 @@
return False
+class Property(Base):
+ """
+ Confml property class
+ """
+ def __init__(self, **kwargs):
+ """
+ @param name=str: name string (mandatory)
+ @param value=str: value for the property, string
+ @param unit=str: unit of the property
+ """
+ if kwargs.get('name',None) == None:
+ raise ValueError("Property name cannot be None!")
+ super(Property,self).__init__(Property.to_propertyref(kwargs.get('name',None)))
+ self.name = kwargs.get('name',None)
+ self.value = kwargs.get('value',None)
+ self.unit = kwargs.get('unit',None)
+
+ @classmethod
+ def to_propertyref(cls, name):
+ """
+ @param name: name of the property
+ @return: A property reference.
+ """
+ if name is not None:
+ return "property_%s" % name
+ else:
+ raise ValueError("Property name cannot be None!")
+
+ @classmethod
+ def to_normref(cls, ref):
+ """
+ @param ref: a property reference
+ @return: normalized property reference
+ """
+ return ref[9:]
+
+ def get_name(self):
+ return self.name
+
+ def get_value(self):
+ return self.value
+
+ def get_unit(self):
+ return self.unit
+
class Option(Base):
"""
Confml option class.
@@ -2347,6 +3289,8 @@
self.value = value
self.map = kwargs.get('map', None)
self.relevant = kwargs.get('relevant', None)
+ self.map_value = kwargs.get('map_value', None)
+ self.display_name = kwargs.get('display_name', None)
@classmethod
def to_optref(cls, value, map):
@@ -2391,7 +3335,7 @@
MODE_APPEND = 3
MODE_DELETE = 4
- def __init__(self, path):
+ def __init__(self, path, mode=''):
"""
@param path: the reference to the root of the storage.
"""
@@ -2399,7 +3343,16 @@
self.curpath = ""
self.container = True
self.__opened_res__ = {}
-
+ self.mode = mode
+ self.cpath_stack = []
+
+ def __reduce_ex__(self, protocol_version):
+ return (open_storage,
+ (self.path, self.mode),
+ None,
+ None,
+ None)
+
def __opened__(self, res):
"""
Internal function to add a newly opened Resource object to the list of open resources.
@@ -2496,6 +3449,34 @@
"""
return self.rootpath
+ def push(self, path):
+ """
+ Set the current path under the Storage to the given path and push the possible existing path to a stack.
+ The current path can be reverted with pop method.
+
+ @return: None
+ @param path: The path which is set as current path.
+ """
+ self.cpath_stack.append(self.curpath)
+ self.curpath = path
+
+ def pop(self):
+ """
+ Pop a path from path stack and set the current path to the popped element. The path can be pushed to the
+ current path stack with push.
+
+ NOTE! if the pop is called when the current path stack is empty, the path will just remain is empty path
+ keeping the active path in the storages root path.
+
+ @return: The new path.
+ """
+ try:
+ path = self.cpath_stack.pop()
+ self.curpath = path
+ except IndexError:
+ pass
+ return self.curpath
+
def set_current_path(self, path):
"""
@param path: the current path under the Storage.
@@ -2556,7 +3537,7 @@
"""
raise exceptions.NotSupportedException()
- def list_resources(self, path, recurse=False):
+ def list_resources(self, path, **kwargs):
"""
find the resources under certain ref/path
@param ref : reference to path where resources are searched
@@ -2581,14 +3562,6 @@
"""
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
@@ -2691,13 +3664,13 @@
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()
+ raise exceptions.NotSupportedException()
def save(self, size=0):
"""
Save all changes to data to storage.
"""
- raise NotSupportedException()
+ raise exceptions.NotSupportedException()
def get_mode(self):
return self.storage.get_mode(self.mode)
@@ -2768,27 +3741,208 @@
except Exception, e:
self.logger.warning("Invalid BMP-file: %s" % resource.get_path())
+
+class currentdir(object):
+ def __init__(self, storage, curdir):
+ self.storage = storage
+ # make sure that the curdir does not contain path prefix
+ self.curdir = curdir.lstrip('/')
+
+ def __enter__(self):
+ self.storage.push(self.curdir)
+
+ def __exit__(self, type, value, tb):
+ self.storage.pop()
+
+
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):
+ def __init__(self, storage, path, **kwargs):
"""
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):
+ self.curpath = path
+ self.storage = storage
+
+ def set_path(self, path):
+ """
+ """
+ self.curpath = path
+
+ def get_path(self):
+ """
+ """
+ return self.curpath
+
+ 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.
+ """
+ self.storage.close()
+
+ def save(self):
+ """
+ Flush changes from all resources to the repository.
+ """
+ return self.storage.save()
+
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.open_resource(path, mode)
+ return res
+
+ 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
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.delete_resource(path)
+ return res
+
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.close_resource(path)
+ return res
+
+ def is_resource(self, path):
+ """
+ Return true if the ref is a resource
+ @param ref : reference to path where resources are searched
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.is_resource(path)
+ return res
+
+ def list_resources(self, path, **kwargs):
+ """
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.list_resources(path, **kwargs)
+ return res
+
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.import_resources(paths, storage)
+ return res
+
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.export_resources(paths, storage)
+ return res
+
+ 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.
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.save_resource(path)
+ return res
+
+ def create_folder(self, path):
+ """
+ Create a folder entry to a path
+ @param path : path to the folder
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.create_folder(path)
+ return res
+
+ def delete_folder(self, path):
+ """
+ Delete a folder entry from a path. The path must be empty.
+ @param path : path to the folder
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.delete_folder(path)
+ return res
+
+ def is_folder(self, path):
+ """
+ Check if the given path is an existing folder in the storage
+ @param path : path to the folder
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.is_folder(path)
+ return res
+
+ def get_mode(self, mode_str):
+ return self.storage.get_mode()
+
+ 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
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.unload(path, object)
+ return res
+
+ 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
+ """
+ with currentdir(self.storage, self.curpath):
+ res = self.storage.load(path)
+ return res
+
+ path = property(get_path, set_path)
+
+
+class CompositeLayer(Folder):
"""
A base class for composite Configuration objects.
"""
- def __init__(self, path="", **kwargs):
+ def __init__(self, storage, path="", **kwargs):
+ super(CompositeLayer, self).__init__(storage, path, **kwargs)
self.layers = kwargs.get('layers', [])
self.path = path
@@ -2850,18 +4004,29 @@
lres.append(utils.resourceref.join_refs([layerpath, respath]))
return lres
- def list_all_resources(self, empty_folders=False):
+ def list_all_resources(self, **kwargs):
"""
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):
+ for respath in sublayer.list_all_resources(**kwargs):
lres.append(utils.resourceref.join_refs([layerpath, respath]))
-
return lres
-
+
+ def list_all_related(self, **kwargs):
+ """
+ Returns a list of all (non confml) 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_related(**kwargs):
+ 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.
@@ -2876,11 +4041,9 @@
@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)
+ super(Layer, self).__init__(storage, 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',
@@ -2894,11 +4057,26 @@
def __getattr__(self, name):
return getattr(self.storage, name)
+ def __getstate__(self):
+ state = {}
+ state['predefined'] = self.predefined
+ state['path'] = self.path
+ state['layers'] = self.layers
+ return state
+
+ def __setstate__(self, state):
+ state = {}
+ self.predefined = state.get('predefined',{})
+ self.path = state.get('path','')
+ self.layers = state.get('layers',[])
+
+ return state
+
def list_confml(self):
"""
@return: array of confml file references.
"""
- res = self.storage.list_resources(self.predefined['confml_path'], True)
+ res = self.list_resources(self.predefined['confml_path'], recurse=True)
res += super(Layer, self).list_confml()
return res
@@ -2906,7 +4084,7 @@
"""
@return: array of implml file references.
"""
- res = self.storage.list_resources(self.predefined['implml_path'], True)
+ res = self.list_resources(self.predefined['implml_path'], recurse=True)
res += super(Layer, self).list_implml()
return res
@@ -2914,7 +4092,7 @@
"""
@return: array of content file references.
"""
- res = self.storage.list_resources(self.predefined['content_path'], True)
+ res = self.list_resources(self.predefined['content_path'], recurse=True)
res += super(Layer, self).list_content()
return res
@@ -2922,59 +4100,85 @@
"""
@return: array of document file references.
"""
- res = self.storage.list_resources(self.predefined['doc_path'], True)
+ res = self.list_resources(self.predefined['doc_path'], recurse=True)
res += super(Layer, self).list_doc()
return res
def confml_folder(self):
- cpath = self.storage.get_current_path()
+ cpath = self.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()
+ cpath = self.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()
+ cpath = self.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()
+ cpath = self.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):
+ def list_all_resources(self, **kwargs):
"""
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 += self.list_resources(folderpath, recurse=True)
- lres += super(Layer, self).list_all_resources(empty_folders)
-
+ lres += super(Layer, self).list_all_resources()
return lres
- def list_all_related(self, empty_folders=False):
+ def list_all_related(self, **kwargs):
"""
Returns a list of all (non confml) layer related resource paths with full path in the storage.
"""
+
lres = []
+ exclude_filters = kwargs.get('exclude_filters', {})
+ kwargs['recurse'] = True
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)
+ filter = exclude_filters.get(folderpath, None)
+ resources = self.list_resources(folderpath, **kwargs)
+ if filter:
+ lres += [res for res in resources if not re.search(filter, res, re.IGNORECASE)]
+ else:
+ lres += resources
+ lres += super(Layer, self).list_all_related(**kwargs)
return lres
+class Include(Base, container.LoadLink):
+ """
+ A common include element that automatically loads a resource
+ and its object under this include element.
+ """
+ def __init__(self, ref="", **kwargs):
+ path = kwargs.get('path') or ref
+ store_interface = kwargs.get('store_interface',None)
+ ref = utils.resourceref.to_objref(path)
+ container.LoadLink.__init__(self, path, store_interface)
+ Base.__init__(self, ref)
+
+ def get_store_interface(self):
+ if not self._storeint and self._parent:
+ try:
+ self._storeint = self._parent.get_store_interface()
+ except exceptions.NotFound:
+ # If project is not found, let the store interface be None
+ pass
+ return self._storeint
+
+
class Rule(object):
"""
Base class for Rules in the system.
@@ -3007,7 +4211,104 @@
return mapmodule.public.mapping.BaseMapper()
-##################################################################
+class Problem(object):
+ SEVERITY_ERROR = "error"
+ SEVERITY_WARNING = "warning"
+ SEVERITY_INFO = "info"
+
+ def __init__(self, msg, **kwargs):
+ self.msg = msg
+ self.type = kwargs.get('type', '')
+ self.line = kwargs.get('line', None)
+ self.file = kwargs.get('file', None)
+ self.severity = kwargs.get('severity', self.SEVERITY_ERROR)
+ self.traceback = kwargs.get('traceback', None)
+ # A slot for any problem specific data
+ self.problem_data = kwargs.get('problem_data', None)
+
+ def log(self, logger, current_file=None):
+ """
+ Log this problem with the given logger.
+ """
+ file = self.file or current_file
+ if self.line is None:
+ msg = "(%s) %s" % (file, self.msg)
+ else:
+ msg = "(%s:%d) %s" % (file, self.line, self.msg)
+
+ mapping = {self.SEVERITY_ERROR: logging.ERROR,
+ self.SEVERITY_WARNING: logging.WARNING,
+ self.SEVERITY_INFO: logging.INFO}
+ level = mapping.get(self.severity, logging.ERROR)
+ logger.log(level, msg)
+
+ if self.traceback:
+ logger.debug(self.traceback)
+
+ @classmethod
+ def from_exception(cls, ex):
+ """
+ Create a Problem object from an exception instance.
+
+ If the exception is a sub-class of ConeException, then it may contain
+ extra information (like a line number) for the problem.
+ """
+ if isinstance(ex, exceptions.ConeException):
+ return Problem(msg = ex.problem_msg or unicode(ex),
+ type = ex.problem_type or '',
+ line = ex.problem_lineno,
+ severity = cls.SEVERITY_ERROR)
+ else:
+ return Problem(msg = unicode(ex),
+ severity = cls.SEVERITY_ERROR)
+
+ def __repr__(self):
+ var_data = []
+ for varname in ('msg', 'type', 'line', 'file', 'severity'):
+ var_data.append("%s=%r" % (varname, getattr(self, varname)))
+ return "%s(%s)" % (self.__class__.__name__, ', '.join(var_data))
+
+ def __eq__(self, other):
+ if not isinstance(other, Problem):
+ return False
+ for varname in ('msg', 'type', 'line', 'file', 'severity'):
+ self_val = getattr(self, varname)
+ other_val = getattr(other, varname)
+ if self_val != other_val:
+ return False
+ return True
+
+ def __ne__(self, other):
+ return self == other
+
+ def __lt__(self, other):
+ if not isinstance(other, Problem):
+ return False
+ return (self.file, self.line) < (other.file, other.line)
+
+def make_content_info(resource, data):
+ """
+ Factory for ContentInfo
+ """
+ cnt_inf = None
+
+ if resource != None:
+ guessed_type = mimetypes.guess_type(resource.get_path())
+ mimetype = None
+ mimesubtype = None
+
+ if guessed_type != None:
+ mimetype, mimesubtype = guessed_type[0].split('/')
+
+ if mimetype == 'image' and mimesubtype == 'x-ms-bmp':
+ cnt_inf = BmpImageContentInfo(resource, data)
+ else:
+ cnt_inf = ContentInfo(mimetype, mimesubtype)
+ return cnt_inf
+
+def open_storage(path, mode="r", **kwargs):
+ return Storage.open(path, mode="r", **kwargs)
+
class NullHandler(logging.Handler):
"""
Default handler that does not do anything.
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/container.py
--- a/configurationengine/source/cone/public/container.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/container.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,7 +22,8 @@
import re
import pickle
import logging
-import utils, exceptions
+import utils
+from cone.public import exceptions
def object_container_filter(obj,**kwargs):
""" Create a list of filter functions for each argument """
@@ -137,7 +138,35 @@
return self.data.clear()
class ContainerBase(object):
+ def __init__(self, name="",**kwargs):
+ if len(name.split(".")) > 1 or len(name.split("/")) > 1:
+ raise exceptions.InvalidRef("Illegal name for ObjectContainer %s" % name)
+ self._name = name
+ self._parent = None
+ self._order = []
+ self._children = {}
+ self._respath = ""
+ for arg in kwargs.keys():
+ setattr(self, arg, kwargs.get(arg))
+
+ def __getstate__(self):
+ state = {}
+ if self._parent: state['_parent'] = self._parent
+ if self._order: state['_order'] = self._order
+ if self._children: state['_children'] = self._children
+ if self._respath: state['_respath'] = self._respath
+ return state
+ def __setstate__(self, state):
+ self._name = state.get('ref','')
+ self._parent = state.get('_parent',None)
+ self._order = state.get('_order',[])
+ self._children = state.get('_children',{})
+ self._respath = state.get('_respath',"")
+ # update the parent link for all the children of this object
+ for child in self._objects():
+ child._parent = self
+
def _set_parent(self, newparent):
"""
@param newparent: The new parent object
@@ -157,6 +186,18 @@
"""
self._parent = None
+ def get_store_interface(self):
+ """
+ Get a possible store interface for this ContainerBase object
+ """
+ return None
+
+ def get_path(self):
+ """
+ Return the path of the object
+ """
+ return self._respath
+
parent = property(_get_parent, _set_parent,_del_parent)
@@ -189,7 +230,7 @@
class LoadInterface(ContainerBase):
def load(self,ref):
- file = open(ref,"r")
+ file = open(ref,"rb")
self._parent = None
return pickle.load(file)
@@ -197,7 +238,7 @@
"""
unload or release
"""
- file = open(ref,"w")
+ file = open(ref,"wb")
pickle.dump(obj,file)
file.close()
@@ -207,138 +248,6 @@
"""
return ""
-class LoadProxy(ContainerBase):
- """
- This class is meant for loading & unloading an object, when it need.
- """
- def __init__(self, path, store_interface=None):
- """
- @param path: the path which is used in loadin
- @param store_interface: the loading interface object, which is used.
- Expects load(path) and dump(obj) functions
- """
- self.set('_obj', None)
- self.set('_parent', None)
- self.set('path', path)
- self.set('_storeint', store_interface)
-
- def __getattr__(self,name):
- """
- direct all not found attribute calls to the sub object getattr
- """
- if not self._obj:
- self._load()
- return getattr(self._obj,name)
-
- def __setattr__(self, name, value):
- """
- direct attribute setting calls to the sub object setattr
- """
- if not self._obj:
- self._load()
- setattr(self._obj,name,value)
-
- def __delattr__(self, name):
- """
- direct attribute setting calls to the sub object setattr
- """
- if not self._obj:
- self._load()
- delattr(self._obj,name)
-
- def _set_parent(self, newparent):
- """
- @param newparent: The new parent object
- @return: None
- """
- self.set('_parent',newparent)
- if self._obj:
- self._obj._parent = self._parent
-
- def _set_obj(self, obj):
- self.set('_obj',obj)
- # set the same _parent for the actual object as is stored for the proxy
- self._obj._parent = self._parent
- self._obj.set_path(self.path)
-
- def _get_obj(self):
- if not self._obj:
- self._load()
- return self._obj
-
- def _load(self):
- # Should the loading of layer external resources be supported?
- # E.g. resources with absolute path relative to the storage (starts with slash)
- """ If the loading of the object fails => Raise an InvalidObject exception """
- try:
- obj = self._store_interface().load(self.fullpath)
- self._set_obj(obj)
- obj.set_ref(utils.resourceref.to_objref(self.path))
- except exceptions.NotResource,e:
- logging.getLogger('cone').warning("Loading %s from parent %s failed! %s" % (self.path,self.get_parent_path(), e))
- raise exceptions.InvalidObject("Invalid configuration object %s" % self.path)
-
- def _unload(self):
- if self._obj:
- self._store_interface().unload(self.fullpath, self._obj)
- self.set('_obj',None)
-
- def _store_interface(self):
- if not self._storeint:
- self.set('_storeint',self._parent.get_project())
- return self._storeint
-
- def set(self,name,value):
- """
- Proxy has a specific attribute setting function, because by default all attributes are
- stored to the actual proxy object
- """
- self.__dict__[name] = value
-
- def get(self,name):
- """
- Proxy has also a specific attribute getting function, because by default all attributes are
- stored to the actual proxy object
- """
- return self.__dict__[name]
-
- def save(self):
- if hasattr(self._obj,'save'):
- self._obj.save()
- self._unload()
-
- def close(self):
- if hasattr(self._obj,'close'):
- self._obj.close()
-
- def get_parent_path(self):
- """
- Return the path of the configuration resource
- """
- if self._parent:
- return utils.resourceref.get_path(self._parent.get_path())
- else:
- return ""
-
- def get_path(self):
- """
- Return the path of the configuration resource
- """
- if self._obj:
- return self._obj.get_path()
- else:
- return self.path
-
- @property
- def fullpath(self):
- """
- Return the path of the configuration resource
- """
- try:
- return self._obj.get_full_path()
- except AttributeError:
- parent_path = self.get_parent_path()
- return utils.resourceref.join_refs([parent_path,self.path])
class ObjectContainer(ContainerBase):
"""
@@ -348,14 +257,7 @@
def __init__(self,name="",**kwargs):
"""
"""
- if len(name.split(".")) > 1 or len(name.split("/")) > 1:
- raise exceptions.InvalidRef("Illegal name for ObjectContainer %s" % name)
- self._name = name
- self._parent = None
- self._order = []
- self._children = {}
- for arg in kwargs.keys():
- setattr(self, arg, kwargs.get(arg))
+ super(ObjectContainer,self).__init__(name, **kwargs)
def __getattr__(self,name):
"""
@@ -364,7 +266,10 @@
try:
return self.__dict__['_children'][name]
except KeyError:
- return getattr(super(ObjectContainer),name)
+ try:
+ return getattr(super(ObjectContainer),name)
+ except AttributeError,e:
+ raise AttributeError("%s object has not attribute '%s'" % (self.__class__, name))
def _path(self, toparent=None):
"""
@@ -384,13 +289,32 @@
else:
return self._name
- def _add(self, child, policy=REPLACE):
+ def _add(self, child_or_children, policy=REPLACE):
"""
- Add a child object.
- @param child: The child object to add. The child needs to be an instance of ObjectContainer.
+ Add a child object or multiple child objects.
+ @param child_or_children: The child object or list of child objects to add.
+ The children need to be instances of ObjectContainer.
@param policy: The policy which is used when an object with same name exists already
"""
+ if isinstance(child_or_children, list):
+ objs = child_or_children
+ if policy == PREPEND:
+ objs = reversed(objs)
+ policy_first = PREPEND
+ policy_rest = PREPEND
+ else:
+ policy_first = policy
+ policy_rest = APPEND
+
+ for i, obj in enumerate(objs):
+ if i == 0: p = policy_first
+ else: p = policy_rest
+ self._add(obj, p)
+ return
+
+
# check that the child is a supported type
+ child = child_or_children
if not self._supported_type(child):
raise exceptions.IncorrectClassError("Cannot add instance of %s to %s." % (child.__class__,self.__class__))
if policy == REPLACE:
@@ -443,12 +367,17 @@
if not child._name.startswith('?'):
self._order.append(child._name)
else:
- """ if the existing child is a instance of ObjectContainer,
- add all children of the existing contianer to this new object """
+ """
+ if the existing child is a instance of ObjectContainer,
+ add all children of the existing container to this new object, except if the
+ child already exists in the new child.
+ """
existingchild = self._children[child._name]
if isinstance(existingchild, ObjectContainer):
for subchild in existingchild._objects():
- child._add(subchild)
+ if not child._children.has_key(subchild._name):
+ child._add(subchild)
+
self._children[child._name] = child
return
@@ -508,8 +437,8 @@
curelem = utils.get_list(curelem._children[name])[index]
return curelem
# Catch the KeyError exception from dict and IndexError from list
- except (KeyError,IndexError):
- raise exceptions.NotFound("Child %s not found!" % path)
+ except (KeyError,IndexError), e:
+ raise exceptions.NotFound("Child %s not found from %s! %s" % (path, self, e))
def _has(self, path):
"""
@@ -545,7 +474,9 @@
del self._order[self._order.index(name)]
elif self._get(path) != None: # delete if the child is found
del self._children[path]
- del self._order[self._order.index(path)]
+ # hidded children are not added to the order list
+ if not path.startswith('?'):
+ del self._order[self._order.index(path)]
else:
raise exceptions.NotFound("Child %s not found!" % path)
@@ -565,6 +496,8 @@
given as dict, so they must be given with name. E.g. _traverse(name='test')
@param name: The node name or part of name which is used as a filter. This is a regular expression (uses internally re.match())
@param path: The path name or part of name which is used as a filter. This is a regular expression (uses internally re.match())
+ @param type: The type (class) of the objects that should be returned (this can be a tuple of types)
+ @param depth: The max recursion depth that traverse goes through.
@param filters: A list of predefined filters can be given as lambda functions. E.g. filters=[lambda x: isinstance(x._obj, FooClass)]
@return: a list of ObjectContainer objects.
"""
@@ -582,7 +515,7 @@
ret = []
for child in self._objects():
- subchildren = child._tail_recurse(_apply_filter,filters=filterlist)
+ subchildren = child._tail_recurse(_apply_filter,filters=filterlist,depth=kwargs.get('depth',-1))
ret += subchildren
return ret
@@ -611,20 +544,25 @@
@param kwargs: a list of arguments as dict
@return: an list of objects, which can be anything that the funtion returns
"""
-
+ depth = kwargs.get('depth',-1)
ret = []
- ret += function(self,**kwargs)
- for child in self._objects():
- try:
- # We wont add the object to the ret until we know that it is a valid object
- subchildren = child._tail_recurse(function,**kwargs)
- #ret += function(child,**kwargs)
- ret += subchildren
- except exceptions.InvalidObject,e:
- # remove the invalid object from this container
- logging.getLogger('cone').warning('Removing invalid child because of exception %s' % e)
- self._remove(child._name)
- continue
+ # check the if the recursion maximum depth has been reached
+ # if not reached but set, decrease it by one and set that to subrecursion
+ if depth != 0:
+ ret += function(self,kwargs.get('filters',[]))
+ kwargs['depth'] = depth - 1
+ for child in self._objects():
+ try:
+ # We wont add the object to the ret until we know that it is a valid object
+ subchildren = child._tail_recurse(function,**kwargs)
+ #ret += function(child,**kwargs)
+ ret += subchildren
+ except exceptions.InvalidObject,e:
+ # remove the invalid object from this container
+ logging.getLogger('cone').warning('Removing invalid child because of exception %s' % e)
+ self._remove(child._name)
+ continue
+
return ret
def _head_recurse(self, function,**kwargs):
@@ -695,7 +633,7 @@
This function should be overloaded by a subclass if the supported types need to be changed.
@return: True if object is supported, otherwise false.
"""
- return isinstance(obj, ObjectContainer)
+ return isinstance(obj, (ObjectContainer,ContainerBase))
def _default_object(self,name):
"""
@@ -773,6 +711,13 @@
"""
return self.ref
+ def has_ref(self, ref):
+ """
+ Check if object container contains the given reference.
+ @param ref: reference
+ """
+ return self._has(ref)
+
class ObjectProxyContainer(ObjectProxy,ObjectContainer):
"""
Combines the Container and Proxy classes to one.
@@ -792,3 +737,317 @@
return self.__dict__['_children'][name]
except KeyError:
return getattr(self._obj,name)
+
+class LoadContainer(ContainerBase):
+ """
+ This class is meant for loading & unloading an object(s), to a ObjectContainer.
+ The loading is done if the object container methods are accessed.
+ """
+ def __init__(self, path, store_interface=None):
+ """
+ @param path: the path which is used in loading
+ @param store_interface: the loading interface object, which is used.
+ Expects load(path) and dump(obj) functions
+ """
+ super(LoadContainer, self).__init__()
+ self._parent = None
+ self._container = None
+ self._storeint = store_interface
+ self._respath = path
+
+ def __getattr__(self,name):
+ """
+ Load the container objects if they are not allready loaded
+ """
+ if not self._container:
+ self._load()
+ return getattr(self._container,name)
+
+ def _load(self):
+ """ If the loading of the object fails => Raise an InvalidObject exception """
+ try:
+ self._container = ObjectContainer()
+ # this should be modified to support loading multiple elements
+ intf = self.get_store_interface()
+ # Do not try to load the objects if interface cannot be found
+ if intf:
+ obj = intf.load(self.get_full_path())
+ self._container._add(obj)
+ except exceptions.NotResource,e:
+ logging.getLogger('cone').warning("Loading %s from parent %s failed! %s" % (self.path,self.get_parent_path(), e))
+ raise exceptions.InvalidObject("Invalid configuration object %s" % self.path)
+
+ def _unload(self):
+ # go through objects in the container
+ intf = self.get_store_interface()
+ for obj in self._container._objects():
+ # remove the parent link
+ obj._parent = None
+ if intf:
+ intf.unload(self.get_full_path(), obj)
+ self._container._remove(obj._name)
+ # set the container back to None
+ self._container = None
+
+ def get_store_interface(self):
+ if not self._storeint and self._parent:
+ try:
+ self._storeint = self._parent.get_store_interface()
+ except exceptions.NotFound:
+ # If project is not found, let the store interface be None
+ pass
+ return self._storeint
+
+ def get_parent_path(self):
+ """
+ Return the path of the configuration resource
+ """
+ if self._parent:
+ return utils.resourceref.get_path(self._parent.get_path())
+ else:
+ return ""
+
+ def get_full_path(self, obj=None):
+ """
+ Return the path of the configuration resource
+ """
+ if obj != None:
+ try:
+ return obj.get_full_path()
+ except AttributeError:
+ pass
+ # default path processing returns the fullpath of this elem
+ parent_path = self.get_parent_path()
+ return utils.resourceref.join_refs([parent_path,self.get_path()])
+
+
+class LoadLink(ContainerBase):
+ """
+ This class is meant for loading & unloading an object(s), to a ObjectContainer.
+ The loading is done if the object container methods are accessed.
+ """
+ def __init__(self, path, store_interface=None):
+ """
+ @param path: the path which is used in loading
+ @param store_interface: the loading interface object, which is used.
+ Expects load(path) and dump(obj) functions
+ """
+ super(LoadLink, self).__init__()
+ self._parent = None
+ self._loaded = False
+ self._storeint = store_interface
+ self._respath = path
+
+ def populate(self):
+ """
+ Populate the object to the parent
+ """
+ if self._parent == None:
+ raise exceptions.NoParent("Cannot populate a LoadLink object without existing parent object")
+ if not self._loaded:
+ for obj in self._load():
+ self._parent._add(obj)
+
+ def _load(self):
+ """ If the loading of the object fails => Raise an InvalidObject exception """
+ objs = []
+ try:
+ # this should be modified to support loading multiple elements
+ intf = self.get_store_interface()
+ # Do not try to load the objects if interface cannot be found
+ if intf:
+ obj = intf.load(self.get_full_path())
+ objs.append(obj)
+ except exceptions.NotResource,e:
+ logging.getLogger('cone').warning("Loading %s from parent %s failed! %s" % (self.path,self.get_parent_path(), e))
+ raise exceptions.InvalidObject("Invalid configuration object %s" % self.path)
+ return objs
+
+ def _unload(self):
+ pass
+
+ def get_store_interface(self):
+ if not self._storeint and self._parent:
+ try:
+ self._storeint = self._parent.get_store_interface()
+ except exceptions.NotFound:
+ # If project is not found, let the store interface be None
+ pass
+ return self._storeint
+
+ def get_parent_path(self):
+ """
+ Return the path of the configuration resource
+ """
+ if self._parent:
+ return utils.resourceref.get_path(self._parent.get_path())
+ else:
+ return ""
+
+ def get_full_path(self, obj=None):
+ """
+ Return the path of the configuration resource
+ """
+ if obj != None:
+ try:
+ return obj.get_full_path()
+ except AttributeError:
+ pass
+ # default path processing returns the fullpath of this elem
+ parent_path = self.get_parent_path()
+ return utils.resourceref.join_refs([parent_path,self.get_path()])
+
+
+class LoadProxy(ContainerBase):
+ """
+ This class is meant for representing any object loading & unloading an object,
+ when it is actually needed.
+ object
+ """
+ def __init__(self, path, store_interface=None):
+ """
+ @param path: the path which is used in loadin
+ @param store_interface: the loading interface object, which is used.
+ Expects load(path) and dump(obj) functions
+ """
+ self.set('_obj', None)
+ self.set('_parent', None)
+ self.set('path', path)
+ self.set('_storeint', store_interface)
+
+ def __getattr__(self,name):
+ """
+ direct all not found attribute calls to the sub object getattr
+ """
+ if not self._obj:
+ self._load()
+ return getattr(self._obj,name)
+
+ def __getstate__(self):
+ """
+ Return a state which should have sufficient info to load the proxy object but
+ dont serialize the object itself.
+ """
+ state = {}
+ state['path'] = self.path
+ state['_obj'] = None
+ # state['_parent'] = self._parent
+ state['_storeint'] = self._storeint
+ return state
+
+ def __setstate__(self, state):
+ self.set('_obj', state.get('_obj',None))
+ self.set('_storeint', state.get('_storeint',None))
+ self.set('_parent', state.get('_parent',self._storeint))
+ self.set('path', state.get('path',''))
+
+ def __setattr__(self, name, value):
+ """
+ direct attribute setting calls to the sub object setattr
+ """
+ if not self._obj:
+ self._load()
+ setattr(self._obj,name,value)
+
+ def __delattr__(self, name):
+ """
+ direct attribute setting calls to the sub object setattr
+ """
+ if not self._obj:
+ self._load()
+ delattr(self._obj,name)
+
+ def _set_parent(self, newparent):
+ """
+ @param newparent: The new parent object
+ @return: None
+ """
+ self.set('_parent',newparent)
+ if self._obj:
+ self._obj._parent = self._parent
+
+ def _set_obj(self, obj):
+ self.set('_obj',obj)
+ # set the same _parent for the actual object as is stored for the proxy
+ if self._obj:
+ self._obj._parent = self._parent
+ self._obj.set_path(self.path)
+
+ def _get_obj(self):
+ if not self._obj:
+ self._load()
+ return self._obj
+
+ def _load(self):
+ # Should the loading of layer external resources be supported?
+ # E.g. resources with absolute path relative to the storage (starts with slash)
+ """ If the loading of the object fails => Raise an InvalidObject exception """
+ try:
+ obj = self.get_store_interface().load(self.fullpath)
+ self._set_obj(obj)
+ obj.set_ref(utils.resourceref.to_objref(self.path))
+ except exceptions.NotResource,e:
+ logging.getLogger('cone').warning("Loading %s from parent %s failed! %s" % (self.path,self.get_parent_path(), e))
+ raise exceptions.InvalidObject("Invalid configuration object %s" % self.path)
+
+ def _unload(self):
+ if self._obj:
+ self.get_store_interface().unload(self.fullpath, self._obj)
+ self.set('_obj',None)
+
+ def get_store_interface(self):
+ if not self._storeint:
+ self.set('_storeint',self._parent.get_store_interface())
+ return self._storeint
+
+ def set(self,name,value):
+ """
+ Proxy has a specific attribute setting function, because by default all attributes are
+ stored to the actual proxy object
+ """
+ self.__dict__[name] = value
+
+ def get(self,name):
+ """
+ Proxy has also a specific attribute getting function, because by default all attributes are
+ stored to the actual proxy object
+ """
+ return self.__dict__[name]
+
+ def save(self):
+ if hasattr(self._obj,'save'):
+ self._obj.save()
+ self._unload()
+
+ def close(self):
+ if hasattr(self._obj,'close'):
+ self._obj.close()
+
+ def get_parent_path(self):
+ """
+ Return the path of the configuration resource
+ """
+ if self._parent:
+ return utils.resourceref.get_path(self._parent.get_path())
+ else:
+ return ""
+
+ def get_path(self):
+ """
+ Return the path of the configuration resource
+ """
+ if self._obj:
+ return self._obj.get_path()
+ else:
+ return self.path
+
+ @property
+ def fullpath(self):
+ """
+ Return the path of the configuration resource
+ """
+ try:
+ return self._obj.get_full_path()
+ except AttributeError:
+ parent_path = self.get_parent_path()
+ return utils.resourceref.join_refs([parent_path,self.path])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/exceptions.py
--- a/configurationengine/source/cone/public/exceptions.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/exceptions.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,7 +17,34 @@
# @author Teemu Rytkonen
class ConeException(Exception):
- pass
+ """
+ Base class for ConE exceptions.
+
+ The attributes ``problem_desc`` and ``problem_lineno`` contain a description of
+ the error and the line on which the error occurred, if available.
+ The exception message itself may be composed of these two to make it more
+ readable, but it may also just be the same as the description.
+
+ @message: Exception message.
+ @param problem_lineno: The line number for api.Problem conversion. Can be None to
+ signify that the line number is not available.
+ @param problem_desc: Error description for api.Problem conversion. If None,
+ the exception message will be used here also.
+ @param problem_type: Problem type for api.Problem conversion. If None, the
+ class-level default will be used.
+ """
+
+ #: Problem type for conversion to api.Problem.
+ #: A default can be set on the exception class level, but it may
+ #: also be set for individual exception instances.
+ problem_type = None
+
+ def __init__(self, message='', problem_lineno=None, problem_msg=None, problem_type=None):
+ Exception.__init__(self, message)
+ self.problem_lineno = problem_lineno
+ self.problem_msg = problem_msg or message
+ if problem_type is not None:
+ self.problem_type = problem_type
class NotSupportedException(ConeException):
def __init__(self, message=""):
@@ -46,27 +73,19 @@
pass
class ParseError(ConeException):
- """
- Exception raised when invalid data is attempted to be parsed.
-
- The attributes ``desc`` and ``lineno`` contain a description of
- the error and the line on which the error occurred, if available.
- The exception message itself may be composed of these two to make it more
- readable, but it may also just be the same as the description.
-
- @message: Exception message.
- @param lineno: The line number where the error occurred. Can be None to
- signify that the line number is not available.
- @param desc: Error description. If None, the exception message will be
- used here also.
- """
- def __init__(self, message, lineno=None, desc=None):
- ConeException.__init__(self, message)
- self.lineno = lineno
- self.desc = desc or message
+ pass
class XmlParseError(ParseError):
- pass
+ problem_type = 'xml'
+
+class XmlSchemaValidationError(ParseError):
+ problem_type = 'schema'
+
+class ConfmlParseError(ParseError):
+ problem_type = 'model.confml'
+
+class ImplmlParseError(ParseError):
+ problem_type = 'model.implml'
class IncorrectClassError(ConeException):
pass
@@ -79,3 +98,10 @@
operation an invalid object is encountered.
"""
pass
+
+class NameIdMappingError(ConeException):
+ """
+ Exception raised when resolving a name-ID mapped value fails.
+ """
+ pass
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/parsecontext.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/parsecontext.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,137 @@
+#
+# 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:
+#
+
+import threading
+import logging
+
+import cone.public.utils
+
+class ParseContext(object):
+ """
+ Parse context class for handling exceptions and problems encountered
+ when parsing a file (ConfML, ImplML or anything included from those).
+
+ The context contains the path to the file that is currently being parsed,
+ but the file path can also be overridden when calling a handler method
+ (e.g. an ImplML file includes some other file, which in contains a problem).
+
+ Sub-classes should override _handle_exception() and _handle_problem(),
+ NOT handle_exception() and handle_problem().
+ """
+ def __init__(self):
+ #: The file that is currently being parsed.
+ self.current_file = None
+
+ def handle_exception(self, exception, file_path=None):
+ """
+ Handle an exception that occurred while parsing a file.
+
+ @param exception: The exception that occurred.
+ @param file_path: Override for the name of the file that was being parsed.
+ If this is None, self.current_file is used.
+ """
+ if file_path is None:
+ file_path = self.current_file
+
+ self._handle_exception(exception, file_path)
+
+ def handle_problem(self, problem, file_path=None):
+ """
+ Handle a Problem that occurred while parsing a file.
+
+ @param problem: The problem object.
+ @param file_path: Override for the name of the file that was being parsed.
+ If this is None, self.current_file is used.
+ """
+ if file_path is None:
+ file_path = self.current_file
+
+ self._handle_problem(problem, file_path)
+
+ def _handle_exception(self, exception, file_path):
+ """
+ Called to handle an exception that occurred while parsing a file.
+
+ Note that this should always be called in an exception handler,
+ so you can safely use e.g. traceback.format_exc().
+
+ @param exception: The exception that occurred.
+ @param file_path: The file that was being parsed.
+ """
+ cone.public.utils.log_exception(
+ logging.getLogger('cone'),
+ "Error parsing '%s': %s" % (file_path, str(exception)))
+
+ def _handle_problem(self, problem, file_path):
+ """
+ Called when parsing a file yields a problem.
+ @param problem: The problem object.
+ @param file_path: Override for the name of the file that was being parsed.
+ If this is None, self.current_file is used.
+ """
+ problem.file = file_path
+ problem.log(logging.getLogger('cone'))
+
+# Thread-local storage for the contexts
+_contexts = threading.local()
+
+def _init_contexts():
+ """
+ Initialize thread-local contexts if they are not initialized yet.
+ """
+ if not hasattr(_contexts, 'implml'):
+ _contexts.implml = None
+ _contexts.confml = None
+ _contexts.implml_default = ParseContext()
+ _contexts.confml_default = ParseContext()
+
+def get_implml_context():
+ """
+ Get the current ImplML parse context.
+ """
+ _init_contexts()
+ if _contexts.implml is not None:
+ return _contexts.implml
+ else:
+ return _contexts.implml_default
+
+def set_implml_context(context):
+ """
+ Set the current ImplML parse context.
+ @param context: The context to set. If None, the default context
+ will be used.
+ """
+ _init_contexts()
+ _contexts.implml = context
+
+def get_confml_context():
+ """
+ Get the current ConfML parse context.
+ """
+ _init_contexts()
+ if _contexts.confml is not None:
+ return _contexts.confml
+ else:
+ return _contexts.confml_default
+
+def set_confml_context(context):
+ """
+ Set the current ConfML parse context.
+ @param context: The context to set. If None, the default context
+ will be used.
+ """
+ _init_contexts()
+ _contexts.confml = context
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/plugin.py
--- a/configurationengine/source/cone/public/plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,13 +18,12 @@
import sys
import os
-import re
import logging
-import sets
import inspect
-import xml.parsers.expat
+import re
+import codecs
-from cone.public import exceptions, utils, api, container, settings, rules
+from cone.public import exceptions, utils, api, settings, rules, parsecontext
import _plugin_reader
debug = 0
@@ -69,34 +68,95 @@
"""
return hasattr(feature, _plugin_reader.TEMP_FEATURE_MARKER_VARNAME)
-class GenerationContext(object):
+def uses_ref(refs, impl_refs):
+ """
+ Compare two lists of setting references and return whether any of the
+ references in ``refs`` is used in ``impl_refs``.
+ """
+ for ref in refs:
+ for impl_ref in impl_refs:
+ if ref.startswith(impl_ref):
+ if len(ref) == len(impl_ref):
+ return True
+ elif ref[len(impl_ref)] == '.':
+ return True
+ return False
+
+class GenerationContext(rules.DefaultContext):
"""
Context object that can be used for passing generation-scope
data to implementation instances.
"""
- def __init__(self, tags={}):
+ def __init__(self, **kwargs):
#: The tags used in this generation context
#: (i.e. the tags passed from command line)
- self.tags = tags
+ self.tags = kwargs.get('tags', {})
#: The tags policy used in this generation context
- self.tags_policy = "OR"
+ self.tags_policy = kwargs.get('tags_policy', "OR")
#: A dictionary that implementation instances can use to
#: pass any data between each other
self.impl_data_dict = {}
- #: A string for the phase of the generation
- self.phase = ""
+ #: A string for the phase of the generation.
+ #: If None, no filtering based on phase is done when
+ #: running the implementations
+ self.phase = kwargs.get('phase', None)
#: a list of rule results
self.results = []
#: a pointer to the configuration
- self.configuration = None
+ self.configuration = kwargs.get('configuration', None)
+
+ #: If True, then all implementation filtering done by
+ #: should_run() is disabled, and it always returns True.
+ self.filtering_disabled = False
+
+ #: if True, then the execution flow should normal except
+ #: no output files are actually generated
+ self.dry_run= kwargs.get('dry_run', None)
+
+ #: the output folder for generation
+ #: ensure already here that the output exists
+ self.output= kwargs.get('output', 'output')
+
+ #: List of references of the settings that have been modified in
+ #: listed layers and should trigger an implementation to be executed.
+ #: None if ref filtering is not used
+ self.changed_refs = kwargs.get('changed_refs', None)
+
+
+ #: A boolean flag to determine whether to use ref filtering or not
+ self.filter_by_refs = kwargs.get('filter_by_refs', False)
+
+ #: Temp features
+ self.temp_features = kwargs.get('temp_features', [])
+
+ #: Executed implementation objects. This is a set so that a
+ #: implementation would exist only once in it. Even if it executed
+ #: more than once. The generation_output will show the actual
+ #: output several times if a implementation is executed several times.
+ self.executed = set()
+
+ #: Set of all implementation objects in the configuration context
+ self.impl_set = kwargs.get('impl_set', ImplSet())
+
+ #: Generation output elements as a list
+ self.generation_output = []
- def eval(self, ast, expression, value):
+ #: possible log elemement
+ self.log = []
+ self.log_file = ""
+
+ def __getstate__(self):
+ state = self.__dict__
+ state['impl_data_dict'] = {}
+ return state
+
+ def eval(self, ast, expression, value, **kwargs):
"""
eval for rule evaluation against the context
"""
@@ -107,31 +167,396 @@
Handle a terminal object
"""
try:
- if isinstance(expression, str):
- m = re.match("\${(.*)}", expression)
- if m:
- try:
- dview = self.configuration.get_default_view()
- return dview.get_feature(m.group(1)).value
- except Exception, e:
- logging.getLogger('cone').error("Could not dereference feature %s. Exception %s" % (expression, e))
- raise e
- elif expression in ['true','1','True']:
- return True
- elif expression in ['false','0','False']:
- return False
- else:
- try:
- return eval(expression)
- except NameError:
- # If the expression is a string in it self it can be returned
- return expression
- else:
- return expression
+ if isinstance(expression, basestring):
+ try:
+ dview = self.configuration.get_default_view()
+ return dview.get_feature(expression).value
+ except Exception, e:
+ logging.getLogger('cone').error("Could not dereference feature %s. Exception %s" % (expression, e))
+ raise e
except Exception,e:
logging.getLogger('cone').error("Exception with expression %s: %s" % (expression, e))
raise e
+
+ def convert_value(self, value):
+ try:
+ # Handle some special literals
+ if value == 'true': return True
+ if value == 'false': return False
+ if value == 'none': return None
+
+ # Values can be any Python literals, so eval() the string to
+ # get the value
+ return eval(value)
+ except Exception:
+ ref_regex = re.compile('^[\w\.\*]*$', re.UNICODE)
+ if ref_regex.match(value) is None:
+ raise RuntimeError("Could not evaluate '%s'" % value)
+ else:
+ raise RuntimeError("Could not evaluate '%s'. Did you mean a setting reference and forgot to use ${}?" % value)
+
+ def set(self, expression, value, **kwargs):
+ log = logging.getLogger('cone.ruleml')
+ try:
+ feature = self.configuration.get_default_view().get_feature(expression)
+ feature.set_value(value)
+
+ relation = kwargs.get('relation')
+ if relation:
+ log.info("Set %s = %r from %r" % (expression, value, relation))
+ else:
+ log.info("Set %s = %r" % (expression, value))
+
+ refs = [feature.fqr]
+ if feature.is_sequence():
+ refs = ["%s.%s" % (feature.fqr,subref) for subref in feature.list_features()]
+
+ self.add_changed_refs(refs, relation)
+ if relation:
+ self.generation_output.append(GenerationOutput(expression,
+ relation,
+ type='ref'))
+ return True
+ except exceptions.NotFound,e:
+ log.error('Set operation for %s failed, because feature with that reference was not found! Exception %s', expression, e)
+ raise e
+
+ def should_run(self, impl, log_debug_message=True):
+ """
+ Return True if the given implementation should be run (generated).
+
+ Also optionally log a message that the implementation is
+ filtered out based on phase, tags or setting references.
+
+ Calling this method also affects the output of executed_impls. Every
+ implementation for which a call to this method has returned True
+ will also be in that list.
+
+ @param impl: The implementation to check.
+ @param log_debug_message: If True, a debug message will be logged
+ if the implementation is filtered out based on phase, tags
+ or setting references.
+ """
+ if self.filtering_disabled:
+ return True
+
+ if isinstance(impl, ImplContainer):
+ # Don't perform any filtering on containers
+ return True
+
+ impl_phases = impl.invocation_phase()
+ if isinstance(impl_phases, basestring):
+ impl_phases = [impl_phases]
+
+ if self.phase is not None and self.phase not in impl_phases:
+ # Don't log a debug message for phase-based filtering to
+ # avoid unnecessary spamming (uncomment if necessary
+ # during development)
+ #logging.getLogger('cone').debug('Filtered out based on phase: %r (%r not in %r)' % (impl, self.phase, impl_phases))
+ return False
+ if self.tags and not impl.has_tag(self.tags, self.tags_policy):
+ if log_debug_message:
+ logging.getLogger('cone').debug('Filtered out based on tags: %r' % impl)
+ return False
+ if self.filter_by_refs and self.changed_refs and impl.has_ref(self.changed_refs) == False:
+ if log_debug_message:
+ logging.getLogger('cone').debug('Filtered out based on refs: %r' % impl)
+ return False
+
+ # Assumption is that when a implementation should be run it is added to the executed pile
+ self.executed.add(impl)
+ return True
+
+ def have_run(self, impl):
+ """
+ This function will add the given implementation
+ outputs to the list of generation_outputs.
+ """
+ # Add outputs only from actual leaf implementations
+ # not from ImplContainers
+ if not isinstance(impl, ImplContainer):
+ self.generation_output += impl.get_outputs()
+
+ def create_file(self, filename, **kwargs):
+ """
+ Create a file handle under the output folder. Also adds the output file to the generation outputs list.
+ @param filename: the filename with path, that is created under the output folder of the generation context.
+ @param **kwargs: the keyword arguments that can provide essential information for the GenerationOutput
+ object creation. They should at least contain the implementation argument for the GenerationObject.
+ @param **kwargs implementation: the implementation object that created this output
+ @param **kwargs mode: the mode of the output file created
+ @param **kwargs encoding: the possible encoding of the output file. When this parameter is given the create_file will
+ use codecs.open method to create the file.
+ @return: the filehandle of the new file.
+ """
+
+ implml = kwargs.get('implementation', None)
+ mode = kwargs.get('mode', 'wb')
+ encoding = kwargs.get('encoding', None)
+ targetfile = os.path.normpath(os.path.join(self.output, filename))
+
+ if not os.path.exists(os.path.dirname(targetfile)):
+ os.makedirs(os.path.dirname(targetfile))
+
+ if not encoding:
+ outfile = open(targetfile, mode)
+ else:
+ outfile = codecs.open(targetfile, mode, encoding)
+ # Add the generation output
+ self.generation_output.append(GenerationOutput(utils.resourceref.norm(targetfile),
+ implml,
+ phase=self.phase,
+ type='file',
+ output=self.output))
+ return outfile
+
+ def add_file(self, filename, **kwargs):
+ """
+ Add a file to the generation outputs list.
+ @param filename: the filename with path, that is added. If the path is a relative path
+ the path is added under the output folder of the generation context. Absolute path is added as such and not manipulated.
+ @param **kwargs: the keyword arguments that can provide essential information for the GenerationOutput
+ object creation. They should at least contain the implementation argument for the GenerationObject.
+ @return: None
+ """
+ if not os.path.isabs(filename):
+ targetfile = os.path.join(self.output, filename)
+ else:
+ targetfile = filename
+ # Add the generation output
+ self.generation_output.append(GenerationOutput(utils.resourceref.norm(targetfile),
+ kwargs.get('implementation'),
+ phase=self.phase,
+ type='file',
+ output=self.output))
+
+ def get_output(self, **kwargs):
+ """
+ Get a output object from the generation_output list.
+ @param **kwargs: the keyword arguments.
+ @param implml_type: a filter for generation outputs to filter generation outputs only with given implementation type.
+ @return: list of generation output objects
+ """
+ filters = []
+ if kwargs.get('implml_type'):
+ filters.append(lambda x: x.implementation and x.implementation.IMPL_TYPE_ID == kwargs.get('implml_type'))
+
+ outputs = []
+ # go through all the generation_output items with all provided filters
+ # if the item passes all filters add it to the outputs list
+ for item in self.generation_output:
+ passed = True
+ for filter in filters:
+ if not filter(item):
+ passed = False
+ continue
+ if passed:
+ outputs.append(item)
+ return outputs
+
+ def add_changed_refs(self, refs, implml=None):
+ """
+ Add changed refs to the current set of changed refs if necessary.
+
+ If there are new refs and they are added, log also a debug message.
+ """
+ if self.changed_refs is None:
+ return
+ for ref in refs:
+ self.add_changed_ref(ref, implml)
+
+ def add_changed_ref(self, ref, implml=None):
+ """
+ Add changed ref to the current set of changed refs if necessary.
+
+ If there are new refs and they are added, log also a debug message.
+ """
+ if self.changed_refs is None:
+ return
+
+ if ref not in self.changed_refs:
+ self.changed_refs.append(ref)
+ logging.getLogger('cone').debug('Added ref %s from implml %s' % (ref, implml))
+
+ def get_refs_with_no_output(self, refs=None):
+ if not refs:
+ refs = self.changed_refs
+ if refs:
+ # create a set from the changed refs
+ # then remove the refs that have a generation output
+ # and return the remaining refs as a list
+ refsset = set(refs)
+ implrefs = set()
+ for output in self.generation_output:
+ if output.implementation:
+ implrefs |= set(output.implementation.get_refs() or [])
+ if output.type == 'ref':
+ implrefs.add(output.name)
+ # Add all sequence subfeatures to the list of implementation references
+ dview = self.configuration.get_default_view()
+ for fea in dview.get_features(list(implrefs)):
+ if fea.is_sequence():
+ seqfeas = ["%s.%s" % (fea.fqr,fearef) for fearef in fea.get_sequence_parent().list_features()]
+ implrefs |= set(seqfeas)
+
+ refsset = refsset - implrefs
+ return sorted(list(refsset))
+ else:
+ return []
+
+ def get_refs_with_no_implementation(self, refs=None):
+ if not refs:
+ refs = self.changed_refs
+ if refs:
+ # create a set from the changed refs
+ # then remove the refs that have a generation output
+ # and return the remaining refs as a list
+ refsset = set(refs)
+ implrefs = set(self.impl_set.get_implemented_refs())
+ logging.getLogger('cone').debug("changed_refs: %s" % refsset)
+ logging.getLogger('cone').debug("implrefs: %s" % implrefs)
+ # Add all sequence subfeatures to the list of implementation references
+ dview = self.configuration.get_default_view()
+ for fea in dview.get_features(list(implrefs)):
+ if fea.is_sequence():
+ seqfeas = ["%s.%s" % (fea.fqr,fearef) for fearef in fea.get_sequence_parent().list_features()]
+ implrefs |= set(seqfeas)
+
+ refsset = refsset - implrefs
+ return sorted(list(refsset))
+ else:
+ return []
+
+ @property
+ def executed_impls(self):
+ """
+ List of all executed implementations (implementations for which
+ a call to should_run() has returned True).
+ """
+ return list(self.executed)
+
+ @property
+ def features(self):
+ """
+ return the default view of the context configuration to access all features of the configuration.
+ """
+ return self.configuration.get_default_view()
+
+ def grep_log(self, entry):
+ """
+ Grep the self.log entries for given entry and return a list of tuples with line (index, entry)
+ """
+ return utils.grep_tuple(entry, self.log)
+
+class MergedContext(GenerationContext):
+ def __init__(self, contexts):
+ self.contexts = contexts
+ self.configuration = None
+ self.changed_refs = []
+ self.temp_features = []
+ self.executed = set()
+ self.impl_set = ImplSet()
+ self.impl_dict = {}
+ self.generation_output = []
+ self.log = []
+ self.log_files = []
+ self.outputs = {}
+ for context in contexts:
+ self.changed_refs += context.changed_refs
+ self.temp_features += context.temp_features
+ self.configuration = context.configuration
+ self.executed |= context.executed
+ self.generation_output += context.generation_output
+ self.log += context.log
+ self.log_files.append(context.log_file)
+ for output in context.generation_output:
+ self.outputs[output.name] = output
+ for impl in context.impl_set:
+ self.impl_dict[impl.ref] = impl
+ self.impl_set = ImplSet(self.impl_dict.values())
+
+ def get_changed_refs(self, **kwargs):
+ changed_refs = set()
+ operation = kwargs.get('operation', 'union')
+ for context in self.contexts:
+ if not changed_refs:
+ # set the base set from the first context
+ changed_refs = set(context.changed_refs)
+ else:
+ if operation == 'union':
+ changed_refs |= set(context.changed_refs)
+ elif operation == 'intersection':
+ changed_refs &= set(context.changed_refs)
+ elif operation == 'difference':
+ changed_refs -= set(context.changed_refs)
+ elif operation == 'symmetric_difference':
+ changed_refs ^= set(context.changed_refs)
+ else:
+ raise exceptions.NotSupportedException('Illegal opration %s for get_changed_refs!' % operation)
+ #remove temp features
+ if kwargs.get('ignore_temps'):
+ changed_refs = changed_refs - set(self.temp_features)
+ return list(changed_refs)
+
+class GenerationOutput(object):
+ """
+ A GenerationOutput object that is intended to be part of GenerationContext.generation_outputs.
+ The data should hold information about
+ """
+ TYPES = ['file', 'ref']
+
+ def __init__(self, name, implementation, **kwargs):
+ """
+ @param name: the name of the output as string
+ @param implementation: the implementation object that generated this output
+ @param type: the type of the output that could be file|ref
+ """
+
+ """ The name of the output """
+ self.name = name
+
+ """ The implementation object that generated the output """
+ self.implementation = implementation
+
+ """ The type of the output """
+ self.type = kwargs.get('type', None)
+
+ """ phase of the generation """
+ self.phase = kwargs.get('phase', None)
+
+ """ the context output path of the generation """
+ self.output = kwargs.get('output', None)
+
+ """ the possible exception """
+ self.exception = kwargs.get('exception', None)
+
+ def __str__(self):
+ return "%s(%s, %s)" % (self.__class__.__name__, self.name, self.implementation)
+
+ @property
+ def filename(self):
+ """
+ return the filename part of the the output name. Valid only if the output name is a path.
+ """
+ return os.path.basename(self.name)
+
+ @property
+ def relpath(self):
+ """
+ return the relative name part of the the output name, with relation to the context output path.
+ """
+ return utils.relpath(self.name, self.output)
+
+ @property
+ def abspath(self):
+ """
+ return the relative name part of the the output name, with relation to the context output path.
+ """
+ if os.path.isabs(self.name):
+ return os.path.normpath(self.name)
+ else:
+ return os.path.abspath(os.path.normpath(self.name))
class FlatComparisonResultEntry(object):
"""
@@ -316,8 +741,9 @@
self._settings = None
self.ref = ref
self.index = None
+ self.lineno = None
self.configuration = configuration
- self._output_root = self.settings.get('output_root','output')
+ self._output_root = self.settings.get('output_root','')
self.output_subdir = self.settings.get('output_subdir','')
self.plugin_output = self.settings.get('plugin_output','')
@@ -328,32 +754,32 @@
self.condition = None
self._output_root_override = None
- def _eval_context(self, context):
- """
- This is a internal function that returns True when the context matches to the
- context of this implementation. For example phase, tags, etc are evaluated.
- """
- if context.tags and not self.has_tag(context.tags, context.tags_policy):
- return False
- if context.phase and not context.phase in self.invocation_phase():
- return False
- if self.condition and not self.condition.eval(context):
- return False
-
- return True
+ def __reduce_ex__(self, protocol_version):
+ config = self.configuration
+ if protocol_version == 2:
+ tpl = (read_impl_from_location,
+ (self.ref, config, self.lineno),
+ None,
+ None,
+ None)
+ return tpl
+ else:
+ return (read_impl_from_location,
+ (self.ref, config, self.lineno))
+
def _dereference(self, ref):
"""
Function for dereferencing a configuration ref to a value in the Implementation configuration context.
"""
- return configuration.get_default_view().get_feature(ref).value
+ return self.configuration.get_default_view().get_feature(ref).value
def _compare(self, other, dict_keys=None):
"""
The plugin instance against another plugin instance
"""
raise exceptions.NotSupportedException()
-
+
def generate(self, context=None):
"""
Generate the given implementation.
@@ -383,6 +809,18 @@
"""
return []
+ def get_outputs(self):
+ """
+ Return a list of GenerationOutput objets as a list.
+ """
+ outputs = []
+ phase = None
+ if self.generation_context: phase = self.generation_context.phase
+ for outfile in self.list_output_files():
+ outputs.append(GenerationOutput(outfile,self,type='file', phase=phase) )
+ return outputs
+
+
def get_refs(self):
"""
Return a list of all ConfML setting references that affect this
@@ -404,14 +842,7 @@
if isinstance(refs, basestring):
refs = [refs]
- for ref in refs:
- for impl_ref in impl_refs:
- if ref.startswith(impl_ref):
- if len(ref) == len(impl_ref):
- return True
- elif ref[len(impl_ref)] == '.':
- return True
- return False
+ return uses_ref(refs, impl_refs)
def flat_compare(self, other):
"""
@@ -457,6 +888,9 @@
@property
def settings(self):
+ """
+ return the plugin specific settings object.
+ """
if not self._settings:
parser = settings.SettingsFactory.cone_parser()
if self.IMPL_TYPE_ID is not None:
@@ -468,9 +902,15 @@
@property
def output(self):
+ """
+ return the output folder for this plugin instance.
+ """
vars = {'output_root': self.output_root,'output_subdir': self.output_subdir,'plugin_output': self.plugin_output}
default_format = '%(output_root)s/%(output_subdir)s/%(plugin_output)s'
- return utils.resourceref.norm(self.settings.get('output',default_format,vars))
+ output = utils.resourceref.remove_begin_slash(utils.resourceref.norm(self.settings.get('output',default_format,vars)))
+ if os.path.isabs(self.output_root):
+ output = utils.resourceref.insert_begin_slash(output)
+ return output
def _get_output_root(self):
if self._output_root_override is not None:
@@ -616,8 +1056,32 @@
return [self]
def __repr__(self):
- return "%s(ref=%r, type=%r, index=%r)" % (self.__class__.__name__, self.ref, self.IMPL_TYPE_ID, self.index)
+ return "%s(ref=%r, type=%r, lineno=%r)" % (self.__class__.__name__, self.ref, self.IMPL_TYPE_ID, self.lineno)
+
+ @property
+ def path(self):
+ """
+ return path relative to the Configuration projec root
+ """
+ return self.ref
+ @property
+ def abspath(self):
+ """
+ return absolute system path to the implementation
+ """
+ return os.path.abspath(os.path.join(self.configuration.storage.path,self.ref))
+
+ def uses_layers(self, layers, context):
+ """
+ Return whether this implementation uses any of the given layers
+ in the given context, i.e., whether the layers contain anything that would
+ affect generation output.
+ """
+ # The default implementation checks against refs changed in the layers
+ refs = []
+ for l in layers: refs.extend(l.list_leaf_datas())
+ return self.has_ref(refs)
class ImplContainer(ImplBase):
"""
@@ -655,43 +1119,66 @@
@return:
"""
- if context:
- if not self._eval_context(context):
- # should we report something if we exit here?
- return
-
+ log = logging.getLogger('cone')
+
+ if self.condition and not self.condition.eval(context):
+ log.debug('Filtered out based on condition %s: %r' % (self.condition, self))
+ return
+
# run generate on sub impls
for impl in self.impls:
- impl.generate(context)
+ if context:
+ # 1. Check should the implementation be run from context
+ # 2. Run ImplContainer if should
+ # 3. run other ImplBase objects if this is not a dry_run
+ if context.should_run(impl):
+ if isinstance(impl, ImplContainer) or \
+ not context.dry_run:
+ impl.generate(context)
+ # context.have_run(impl)
+ else:
+ impl.generate(context)
def get_refs(self):
+ # Containers always return None, because the ref-based filtering
+ # happens only on the actual implementations
+ return None
+
+ def get_child_refs(self):
"""
- Return a list of all ConfML setting references that affect this
- implementation. May also return None if references are not relevant
- for the implementation.
+ ImplContainer always None with get_refs so it one wants to get the references from all
+ leaf child objects, one can use this get_child_refs function
+ @return: a list of references.
"""
refs = []
for impl in self.impls:
- subrefs = impl.get_refs()
- if subrefs:
- refs += subrefs
- if refs:
- return utils.distinct_array(refs)
- else:
- return None
+ if isinstance(impl, ImplContainer):
+ refs += impl.get_child_refs()
+ else:
+ refs += impl.get_refs() or []
+ return utils.distinct_array(refs)
+ def has_tag(self, tags, policy=None):
+ # Container always returns True
+ return True
+
def get_tags(self):
+ # Containers always return None, because the tag-based filtering
+ # happens only on the actual implementations
+ return None
+
+ def get_child_tags(self):
"""
- overloading the get_tags function in ImplContainer to create sum of
- tags of all subelements of the Container
- @return: dictionary of tags
+ ImplContainer always None with get_tags so it one wants to get the teags from all
+ leaf child objects, one can use this get_child_tags function
+ @return: a list of references.
"""
- tags = ImplBase.get_tags(self)
+ tags = {}
for impl in self.impls:
- # Update the dict by appending new elements to the values instead
- # of overriding
- for key,value in impl.get_tags().iteritems():
- tags[key] = tags.get(key,[]) + value
+ if isinstance(impl, ImplContainer):
+ utils.update_dict(tags, impl.get_child_tags())
+ else:
+ utils.update_dict(tags, impl.get_tags())
return tags
def list_output_files(self):
@@ -703,6 +1190,15 @@
files += impl.list_output_files()
return utils.distinct_array(files)
+ def get_outputs(self):
+ """
+ Return a list of GenerationOutput objets as a list.
+ """
+ outputs = []
+ for impl in self.impls:
+ outputs += impl.get_outputs()
+ return outputs
+
def set_output_root(self,output):
"""
Set the root directory for the output files. The output
@@ -712,25 +1208,6 @@
for impl in self.impls:
impl.set_output_root(output)
- def invocation_phase(self):
- """
- @return: the list of phase names in which phases this container wants to be executed.
- """
- # use a dictionary to store phases only once
- phases = {}
- phases[ImplBase.invocation_phase(self)] = 1
- for impl in self.impls:
- # for now only get the phases from sub ImplContainer objects
- # this is needed until the plugin phase can be overridden with the common elems
- if isinstance(impl, ImplContainer):
- subphases = impl.invocation_phase()
- if isinstance(subphases, list):
- # join the two lists as one
- phases = phases.fromkeys(phases.keys() + subphases, 1)
- else:
- phases[subphases] = 1
- return phases.keys()
-
def get_temp_variable_definitions(self):
tempvars = self._tempvar_defs[:]
for impl in self.impls:
@@ -757,8 +1234,59 @@
for subimpl in self.impls:
actual_impls += subimpl.get_all_implementations()
return actual_impls
-
-
+
+ def uses_layers(self, layers, context):
+ #log = logging.getLogger('uses_layers(%r)' % self)
+
+ # If no sub-implementation has matching tags, the implementations would
+ # never be run in this context, so there's no need to go further in that case
+ if not self._have_impls_matching_tags(context.tags, context.tags_policy):
+ #log.debug("No impls have matching tags, returning False")
+ return False
+
+ # If the container has a condition depending on any of the changed refs,
+ # it means that the refs can affect generation output
+ if self.condition:
+ refs = []
+ for l in layers: refs.extend(l.list_leaf_datas())
+ if uses_ref(refs, self.condition.get_refs()):
+ #log.debug("Refs affect condition, returning True")
+ return True
+
+ # If the condition evaluates to False (and doesn't depend on the
+ # changed refs), the implementations won't be run, and thus they
+ # don't use the layers in this context
+ if self.condition and not self.condition.eval(context):
+ #log.debug("Condition evaluates to False, returning False")
+ return False
+
+ for impl in self.impls:
+ # Filter out based on tags if the implementation is not
+ # a container (using ImplBase.has_tag() here since RuleML v2
+ # overrides has_tag() to always return True)
+ if not isinstance(impl, ImplContainer):
+ if not ImplBase.has_tag(impl, context.tags, context.tags_policy):
+ continue
+
+ if impl.uses_layers(layers, context):
+ #log.debug("%r uses layer, returning True" % impl)
+ return True
+
+ #log.debug("Returning False")
+ return False
+
+ def _have_impls_matching_tags(self, tags, tags_policy):
+ """
+ Return if any of the container's leaf implementations use the given tags.
+ """
+ for impl in self.impls:
+ if isinstance(impl, ImplContainer):
+ if impl._have_impls_matching_tags(tags, tags_policy):
+ return True
+ elif ImplBase.has_tag(impl, tags, tags_policy):
+ return True
+ return False
+
class ReaderBase(object):
"""
Base class for implementation readers.
@@ -779,6 +1307,25 @@
#: for different versions of an implementation).
NAMESPACE = None
+ #: ID for the namespace used in the generated XML schema files.
+ #: Must be unique, and something simple like 'someml'.
+ NAMESPACE_ID = None
+
+ #: Sub-ID for schema problems for this ImplML namespace.
+ #: This is used as part of the problem type for schema validation
+ #: problems. E.g. if the sub-ID is 'someml', then a schema validation
+ #: problem would have the problem type 'schema.implml.someml'.
+ #: If this is not given, then the problem type will simply be
+ #: 'schema.implml'.
+ SCHEMA_PROBLEM_SUB_ID = None
+
+ #: The root element name of the implementation langauge supported by
+ #: the reader. This is also used in the generate XML schema files, and
+ #: must correspond to the root element name specified in the schema data.
+ #: If get_schema_data() returns None, then this determines the name of
+ #: the root element in the automatically generated default schema.
+ ROOT_ELEMENT_NAME = None
+
#: Any extra XML namespaces that should be ignored by the
#: implementation parsing machinery. This is useful for specifying
#: namespaces that are not actual ImplML namespaces, but are used
@@ -806,6 +1353,37 @@
raise exceptions.NotSupportedException()
@classmethod
+ def read_impl_from_location(cls, resource_ref, configuration, lineno):
+ """
+ Read an implementation instance from the given resource at the given line number.
+
+ @param resource_ref: Reference to the resource in the configuration in
+ which the given document root resides.
+ @param configuration: The configuration used.
+ @param lineno: the line number where the root node for this particular element is searched from.
+ @return: The read implementation instance, or None.
+ """
+ root = cls._read_xml_doc_from_resource(resource_ref, configuration)
+ elemroot = utils.etree.get_elem_from_lineno(root, lineno)
+ ns, tag = utils.xml.split_tag_namespace(elemroot.tag)
+ reader = cls.get_reader_for_namespace(ns)
+ implml = reader.read_impl(resource_ref, configuration, elemroot)
+ implml.lineno = lineno
+ return implml
+
+ @classmethod
+ def get_reader_for_namespace(cls, namespace):
+ return ImplFactory.get_reader_dict().get(namespace, None)
+
+ @classmethod
+ def get_schema_data(cls):
+ """
+ Return the XML schema data used for validating the ImplML supported by this reader.
+ @return: The schema data as a string, or None if not available.
+ """
+ return None
+
+ @classmethod
def _read_xml_doc_from_resource(cls, resource_ref, configuration):
"""
Parse an ElementTree instance from the given resource.
@@ -847,6 +1425,7 @@
@classmethod
def read_impl(cls, resource_ref, configuration, doc_root, read_impl_count=None):
+ on_top_level = read_impl_count == None
# The variable read_impl_count is used to keep track of the number of
# currently read actual implementations. It is a list so that it can be used
# like a pointer, i.e. functions called from here can modify the number
@@ -857,9 +1436,8 @@
ns, tag = utils.xml.split_tag_namespace(doc_root.tag)
if tag != "container":
- logging.getLogger('cone').error("Error: The root element must be a container in %s" % (ns, resource_ref))
+ logging.getLogger('cone').error("Error: The root element must be a container in %s, %s" % (ns, resource_ref))
- impls = []
reader_classes = cls.get_reader_classes()
namespaces = reader_classes.keys()
# Read first the root container object with attributes
@@ -867,7 +1445,7 @@
containerobj = ImplContainer(resource_ref, configuration)
containerobj.condition = cls.get_condition(doc_root)
- common_data = _plugin_reader.CommonImplmlDataReader.read_data(doc_root)
+ containerobj._common_data = _plugin_reader.CommonImplmlDataReader.read_data(doc_root)
# traverse through the subelements
for elem in doc_root:
@@ -877,6 +1455,7 @@
# common namespace elements were handled earlier)
if tag == "container":
subcontainer = cls.read_impl(resource_ref, configuration, elem, read_impl_count=read_impl_count)
+ subcontainer.lineno = utils.etree.get_lineno(elem)
containerobj.append(subcontainer)
subcontainer.index = None # For now all sub-containers have index = None
else:
@@ -886,14 +1465,30 @@
else:
reader = reader_classes[ns]
subelem = reader.read_impl(resource_ref, configuration, elem)
- if common_data: common_data.apply(subelem)
+ subelem.lineno = utils.etree.get_lineno(elem)
containerobj.append(subelem)
subelem.index = read_impl_count[0]
read_impl_count[0] = read_impl_count[0] + 1
-
- if common_data:
- common_data.apply(containerobj)
- containerobj._tempvar_defs = common_data.tempvar_defs + containerobj._tempvar_defs
+
+ containerobj._tempvar_defs = containerobj._common_data.tempvar_defs
+
+ if on_top_level:
+ def inherit_common_data(container):
+ for impl in container.impls:
+ if isinstance(impl, ImplContainer):
+ new_common_data = container._common_data.copy()
+ new_common_data.extend(impl._common_data)
+ impl._common_data = new_common_data
+ inherit_common_data(impl)
+ def apply_common_data(container):
+ for impl in container.impls:
+ if isinstance(impl, ImplContainer):
+ apply_common_data(impl)
+ else:
+ container._common_data.apply(impl)
+ inherit_common_data(containerobj)
+ apply_common_data(containerobj)
+
return containerobj
@classmethod
@@ -913,7 +1508,7 @@
else:
return None
-class ImplSet(sets.Set):
+class ImplSet(set):
"""
Implementation set class that can hold a set of ImplBase instances.
"""
@@ -925,13 +1520,16 @@
INVOCATION_PHASES = ['pre','normal','post']
def __init__(self,implementations=None, generation_context=None):
- super(ImplSet,self).__init__(implementations)
+ super(ImplSet,self).__init__(implementations or [])
self.output = 'output'
- if generation_context:
- self.generation_context = generation_context
- else:
- self.generation_context = GenerationContext()
-
+ self.generation_context = generation_context
+ self.ref_to_impl = {}
+
+ def _create_ref_dict(self):
+ for impl in self:
+ for ref in impl.get_refs() or []:
+ self.ref_to_impl.setdefault(ref, []).append(impl)
+
def invocation_phases(self):
"""
@return: A list of possible invocation phases
@@ -957,7 +1555,21 @@
# impl.generation_context = self.generation_context
if not context:
context = self.generation_context
- self.execute(self, 'generate', context)
+ else:
+ self.generation_context = context
+ # Sort by file name so that execution order is always the same
+ # (easier to compare logs)
+ sorted_impls = sorted(self, key=lambda impl: impl.ref)
+
+ for impl in sorted_impls:
+ # 1. Check should the implementation be run from context
+ # 2. Run ImplContainer if should
+ # 3. run other ImplBase objects if this is not a dry_run
+ if context.should_run(impl):
+ if isinstance(impl, ImplContainer) or \
+ not context.dry_run:
+ self.execute([impl], 'generate', context)
+ # context.have_run(impl)
def post_generate(self, context=None):
"""
@@ -965,7 +1577,16 @@
"""
if not context:
context = self.generation_context
- self.execute(self, 'post_generate', context)
+
+ impls = []
+ # Sort by file name so that execution order is always the same
+ # (easier to compare logs)
+ sorted_impls = sorted(self, key=lambda impl: impl.ref)
+ for impl in sorted_impls:
+ if context.should_run(impl, log_debug_message=False):
+ impls.append(impl)
+
+ self.execute(impls, 'post_generate', context)
def execute(self, implementations, methodname, *args):
"""
@@ -978,17 +1599,21 @@
@param implementations:
@param methodname: the name of the function to execute
"""
- # Sort by (file_name, index_in_file) to ensure the correct execution order
- impls = sorted(implementations, key=lambda impl: (impl.ref, impl.index))
- for impl in impls:
+ for impl in implementations:
try:
- impl.set_output_root(self.output)
if hasattr(impl, methodname):
_member = getattr(impl, methodname)
_member(*args)
else:
logging.getLogger('cone').error('Impl %r has no method %s' % (impl, methodname))
except Exception, e:
+ if self.generation_context:
+ self.generation_context.generation_output.append(GenerationOutput('exception from %s' % impl.ref,
+ impl,
+ phase=self.generation_context.phase,
+ type='exception',
+ output=self.generation_context.output,
+ exception=e))
utils.log_exception(logging.getLogger('cone'), 'Impl %r raised an exception: %s' % (impl, repr(e)))
@@ -1059,6 +1684,38 @@
impls.append(impl)
return ImplSet(impls)
+ def find_implementations(self,**kwargs):
+ """
+ Find any implementation with certain parameters.
+ All arguments are given as dict, so they must be given with name. E.g. copy(phase='normal')
+ @param phase: name of the phase
+ @param refs: A list of refs that are filtered with function has_refs
+ @param tags: A dictionary of tags that are filtered with function has_tags
+ @return: a new ImplSet object with the filtered items.
+ """
+ impls = []
+ """ Create a list of filter functions for each argument """
+ filters=[]
+ filters.append(lambda x: x != None)
+ if kwargs.get('phase', None) != None:
+ filters.append(lambda x: kwargs.get('phase') in x.invocation_phase())
+ if kwargs.get('refs',None) != None:
+ # Changed has_ref usage to allow not supporting refs (meaning that non supported wont be filtered with refs)
+ filters.append(lambda x: x.has_ref(kwargs.get('refs')) == True)
+ if kwargs.get('tags', None) != None:
+ filters.append(lambda x: x.has_tag(kwargs.get('tags'),kwargs.get('policy')))
+
+ """ Go through the implementations and add all to resultset that pass all filters """
+ for impl in self:
+ pass_filters = True
+ for filter in filters:
+ if not filter(impl):
+ pass_filters = False
+ break
+ if pass_filters:
+ impls.append(impl)
+ return ImplSet(impls)
+
def flat_compare(self, other):
"""
Perform a flat comparison between this implementation container and another one.
@@ -1201,8 +1858,8 @@
to be created.
@return: A list containing the references of all created temporary features.
- @raise exceptions.AlreadyExists: Any of the temporary features already exists
- in the configuration, or there are duplicate temporary features defined.
+ @raise exceptions.AlreadyExists: There are duplicate temporary features defined
+ in the configuration. Redefinitions of the temporaty features are only ignored.
"""
# ----------------------------------------------------
# Collect a list of all temporary variable definitions
@@ -1218,9 +1875,11 @@
# Check if already exists
try:
dview.get_feature(fea_def.ref)
- raise exceptions.AlreadyExists(
- "Temporary variable '%s' defined in file '%s' already exists in the configuration!" \
- % (fea_def.ref, impl.ref))
+ #raise exceptions.AlreadyExists(
+ # "Temporary variable '%s' defined in file '%s' already exists in the configuration!" \
+ # % (fea_def.ref, impl.ref))
+ logging.getLogger('cone').warning("Temporary variable '%s' re-definition ignored." % fea_def.ref)
+ continue
except exceptions.NotFound:
pass
@@ -1246,7 +1905,7 @@
# ------------------------------
refs = []
if tempvar_defs:
- logging.getLogger('cone').debug('Creating %d temporary variable(s)' % len(tempvar_defs))
+ logging.getLogger('cone').debug('Creating %d temporary variable(s) %r' % (len(tempvar_defs), tempvar_defs))
autoconfig = get_autoconfig(configuration)
for fea_def in tempvar_defs:
fea_def.create_feature(autoconfig)
@@ -1285,7 +1944,16 @@
result += impl.get_all_implementations()
return result
-
+ def get_implemented_refs(self):
+ if not self.ref_to_impl:
+ self._create_ref_dict()
+ return sorted(self.ref_to_impl.keys())
+
+ def get_implementations_with_ref(self, ref):
+ if not self.ref_to_impl:
+ self._create_ref_dict()
+ return sorted(self.ref_to_impl.get(ref, []), lambda a,b: cmp(a.ref, b.ref))
+
class RelationExecutionResult(object):
"""
Class representing a result from relation execution.
@@ -1334,7 +2002,7 @@
self.entries = entries
self.source = source
- def execute(self):
+ def execute(self, context=None):
"""
Execute all relations inside the container, logging any exceptions thrown
during the execution.
@@ -1342,17 +2010,18 @@
"""
results = []
for i, entry in enumerate(self.entries):
+
if isinstance(entry, rules.RelationBase):
- result = self._execute_relation_and_log_error(entry, self.source, i + 1)
+ result = self._execute_relation_and_log_error(entry, self.source, i + 1, context)
if isinstance(RelationExecutionResult):
results.append(result)
elif isinstance(entry, RelationContainer):
- results.extend(self._execute_container_and_log_error(entry))
+ results.extend(self._execute_container_and_log_error(entry, context))
else:
logging.getLogger('cone').warning("Invalid RelationContainer entry: type=%s, obj=%r" % (type(entry), entry))
return results
- def _execute_relation_and_log_error(self, relation, source, index):
+ def _execute_relation_and_log_error(self, relation, source, index, context=None):
"""
Execute a relation, logging any exceptions that may be thrown.
@param relation: The relation to execute.
@@ -1360,27 +2029,32 @@
@param index: The index of the rule, can be None if the index is not known.
@return: The return value from the relation execution, or None if an error occurred.
"""
- try:
- return relation.execute()
+ try:
+ return relation.execute(context)
except Exception, e:
- log = logging.getLogger('cone')
- if index is not None:
- utils.log_exception(log, "Error executing rule no. %s in '%s'" % (index, source))
- else:
- utils.log_exception(log, "Error executing a rule in '%s'" % relation_or_container.source)
+ msg = "Error executing rule %r: %s: %s" % (relation, e.__class__.__name__, e)
+ if context:
+ gout = GenerationOutput('exception from %s' % source,
+ relation,
+ phase=context.phase,
+ type='exception',
+ output=context.output,
+ exception=msg)
+ context.generation_output.append(gout)
+ utils.log_exception(logging.getLogger('cone'), msg)
return None
- def _execute_container_and_log_error(self, container):
+ def _execute_container_and_log_error(self, container, context):
"""
Execute a relation container, logging any exceptions that may be thrown.
@param relation: The relation container to execute.
@return: The results from the relation execution, or an empty list if an error occurred.
"""
try:
- return container.execute()
+ return container.execute(context)
except Exception, e:
log = logging.getLogger('cone')
- utils.log_exception(log, "Error executing rules in '%s'" % container.source)
+ utils.log_exception(log, "Exception executing rules in '%s': %s" % container.source, e)
return []
def get_relation_count(self):
@@ -1395,6 +2069,18 @@
count += 1
return count
+ def get_relations(self):
+ """
+ Return a list of all relations in this container.
+ """
+ result = []
+ for entry in self.entries:
+ if isinstance(entry, RelationContainer):
+ result.extend(entry.get_relations())
+ else:
+ result.append(entry)
+ return result
+
class ImplFactory(api.FactoryBase):
@@ -1437,7 +2123,9 @@
file_extensions = []
for reader in cls.get_reader_classes():
for fe in reader.FILE_EXTENSIONS:
- file_extensions.append(fe.lower())
+ fe = fe.lower()
+ if fe not in file_extensions:
+ file_extensions.append(fe)
return file_extensions
@classmethod
@@ -1478,7 +2166,7 @@
log.warn("'%s' entry point '%s' is not a sub-class of cone.plugin.ReaderBase (%r)" % (ENTRY_POINT, entry_point.name, reader_class))
else:
msg = "Reader class for XML namespace '%s' loaded from egg '%s' entry point '%s'" % (reader_class.NAMESPACE, ENTRY_POINT, entry_point.name)
- log.debug(msg)
+ #log.debug(msg)
#print msg
reader_classes.append(reader_class)
@@ -1507,23 +2195,39 @@
@raise NotSupportedException: The file contains an XML namespace that is
not registered as an ImplML namespace.
"""
+ context = parsecontext.get_implml_context()
+ context.current_file = resource_ref
try:
+ resource = configuration.get_resource(resource_ref)
+ try: data = resource.read()
+ finally: resource.close()
+
+ # Schema-validation while parsing disabled for now
+ #cone.validation.schemavalidation.validate_implml_data(data)
+
impls = []
reader_dict = cls.get_reader_dict()
- root = ReaderBase._read_xml_doc_from_resource(resource_ref, configuration)
+
+ root = utils.etree.fromstring(data)
ns = utils.xml.split_tag_namespace(root.tag)[0]
if ns not in reader_dict.keys():
- logging.getLogger('cone').error("Error: no reader for namespace '%s' in %s" % (ns, resource_ref))
+ context.handle_problem(api.Problem("No reader for namespace '%s'" % ns,
+ type="xml.implml",
+ file=resource_ref,
+ line=utils.etree.get_lineno(root)))
+ #logging.getLogger('cone').error("Error: no reader for namespace '%s' in %s" % (ns, resource_ref))
return []
rc = reader_dict[ns]
# return the single implementation as a list to maintain
# backwards compability
impl = rc.read_impl(resource_ref, configuration, root)
impl.index = 0
+ impl.lineno = utils.etree.get_lineno(root)
return [impl]
- except exceptions.ParseError, e:
- # Invalid XML data in the file
- logging.getLogger('cone').error("Implementation %s reading failed with error: %s" % (resource_ref,e))
+ except Exception, e:
+ if isinstance(e, exceptions.XmlParseError):
+ e.problem_type = 'xml.implml'
+ context.handle_exception(e)
return []
def get_impl_set(configuration,filter='.*'):
@@ -1531,12 +2235,12 @@
return a ImplSet object that contains all implementation objects related to the
given configuration
"""
- impls = configuration.get_layer().list_implml()
+ impls = configuration.layered_implml().flatten().values()
impls = pre_filter_impls(impls)
# filter the resources with a given filter
impls = utils.resourceref.filter_resources(impls,filter)
- impl_container = create_impl_set(impls,configuration)
- return impl_container
+ impl_set = create_impl_set(impls,configuration)
+ return impl_set
def filtered_impl_set(configuration,pathfilters=None, reffilters=None):
"""
@@ -1544,7 +2248,7 @@
given configuration
"""
if pathfilters: logging.getLogger('cone').info('Filtering impls with %s' % pathfilters)
- impls = configuration.get_layer().list_implml()
+ impls = configuration.layered_implml().flatten().values()
impls = pre_filter_impls(impls)
# filter the resources with a given filter
if pathfilters:
@@ -1552,13 +2256,15 @@
for filter in pathfilters:
newimpls += utils.resourceref.filter_resources(impls,filter)
impls = utils.distinct_array(newimpls)
- impl_container = create_impl_set(impls,configuration,reffilters)
- return impl_container
+ impl_set = create_impl_set(impls,configuration,reffilters)
+ return impl_set
def create_impl_set(impl_filename_list, configuration,reffilters=None):
impl_filename_list = pre_filter_impls(impl_filename_list)
if reffilters: logging.getLogger('cone').info('Filtering with refs %s' % reffilters)
impl_container = ImplSet()
+ impl_container.generation_context = GenerationContext()
+ impl_container.generation_context.configuration = configuration
for impl in impl_filename_list:
try:
if configuration != None and ImplFactory.is_supported_impl_file(impl):
@@ -1578,3 +2284,6 @@
"""
filter = r'(/|^|\\)\..*(/|$|\\)'
return utils.resourceref.neg_filter_resources(impls, filter)
+
+def read_impl_from_location(resource_ref, configuration, lineno):
+ return ReaderBase.read_impl_from_location(resource_ref, configuration, lineno)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/rules.py
--- a/configurationengine/source/cone/public/rules.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/rules.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,10 +17,12 @@
import operator as ops
import logging
import tokenize
-from token import ENDMARKER, NAME, ERRORTOKEN
+import re
+from token import ENDMARKER, NAME, ERRORTOKEN, OP
import StringIO
-from cone.public import container
+from cone.public import container, exceptions, utils
+import types
RELATIONS = {}
@@ -29,14 +31,20 @@
caller = inspect.getouterframes(inspect.currentframe())[1][3]
raise NotImplementedError(caller + ' needs to be implemented')
+REF_DOLLAR = '$'
+REF_START_BRACE = '{'
+REF_END_BRACE = '}'
+REF_REGEX = re.compile('(?P\${[\w\.\*]*})', re.UNICODE)
+
def get_tokens(tokenstr):
result = []
tokens = []
tokenstr = tokenstr.replace('\r', '')
name_buffer = [] # Temp buffer for reading name tokens
last_epos = None
+
+ ref_start = False
for toknum, tokval, spos, epos, _ in tokenize.generate_tokens(StringIO.StringIO(unicode(tokenstr)).readline):
- #print "toknum: %r, tokval: %r, spos: %r, epos: %r" % (toknum, tokval, spos, epos)
val = tokval.strip('\r\n\t ')
if toknum == ENDMARKER and name_buffer:
@@ -46,15 +54,28 @@
# since its value is empty)
if val == '': continue
+ # Handle the references here, ${ref} is the format
+ if toknum in (OP, ERRORTOKEN) and\
+ tokval in (REF_DOLLAR, REF_START_BRACE, REF_END_BRACE) or\
+ ref_start:
+ if tokval == REF_DOLLAR:
+ ref_start = True
+ elif tokval == REF_END_BRACE:
+ ref_start = False
+ if name_buffer and spos[1] != last_epos[1]:
+ tokens.append(''.join(name_buffer))
+ name_buffer = []
+ name_buffer.append(tokval)
+ last_epos = epos
# Put NAME, and ERRORTOKEN tokens through the temp
# buffer
- if toknum in (NAME, ERRORTOKEN):
+ elif toknum in (NAME, ERRORTOKEN):
# If this and the previous token in the temp buffer are not adjacent,
# they belong to separate tokens
if name_buffer and spos[1] != last_epos[1]:
tokens.append(''.join(name_buffer))
name_buffer = []
-
+
name_buffer.append(val)
last_epos = epos
# Other tokens can just go directly to the token list
@@ -89,6 +110,8 @@
relation_name = "RelationBase"
def __init__(self, data, left, right):
self.description = ""
+ self.ref = None
+ self.lineno = None
self.data = data or container.DataContainer()
self.left = left
self.right = right
@@ -98,6 +121,9 @@
@return: A string presentation of the relation object
"""
return "%s %s %s" % (self.left,self.relation_name,self.right)
+
+ def __repr__(self):
+ return "%s(ref=%r, lineno=%r)" % (self.__class__.__name__, self.ref, self.lineno)
def get_name(self):
"""
@@ -111,7 +137,7 @@
"""
return self.description
- def execute(self):
+ def execute(self, context=None):
"""
Execute the relation object.
"""
@@ -161,12 +187,12 @@
class RelationContainerImpl(RelationContainer):
""" Base implementation for RelationContainer to use in ConE rules
"""
- def execute(self):
+ def execute(self, context=None):
ret = True
i = 0
for relation in self:
i += 1
- r = relation.execute()
+ r = relation.execute(context)
ret = ret and r
return ret
@@ -225,8 +251,9 @@
super(BaseRelation, self).__init__(data, left, right)
self.interpreter = ASTInterpreter(context=self.context)
- def execute(self):
+ def execute(self, context=None):
"""
+ @param context: The context for execution can be given as a parameter.
@return Returns error dictionary
In the client code proper way to check if the rule applies:
@@ -236,7 +263,7 @@
"""
# logger.debug("Interpreter context %s" % self.interpreter.context)
self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
- ret = self.interpreter.eval()
+ ret = self.interpreter.eval(context, relation=self)
return ret
def get_keys(self):
@@ -255,8 +282,44 @@
return bool(self.interpreter.errors)
def get_refs(self):
- return (ASTInterpreter.extract_refs(self.left), ASTInterpreter.extract_refs(self.right))
+ """
+ Get a list of left side references and right side references.
+ @return: left refs
+ """
+ try:
+ refs = []
+ tempast = ASTInterpreter()
+ tempast.create_ast("%s" % self.left)
+ for exp in tempast.expression_list:
+ refs += exp.get_refs()
+ except Exception, e:
+ utils.log_exception(logging.getLogger('cone.rules'), "Exception in get_refs() of relation %r: %s" % (self, e))
+ return []
+ return refs
+ def get_set_refs(self):
+ """
+ Get a list of references that could get altered by set expression in this rule.
+ This list is empty if the relation does not have any set expressions.
+ @return: a list of references.
+ """
+
+ return [exp.left.get_ref() for exp in self.get_set_expressions()]
+
+ def get_expressions(self):
+ if not self.interpreter.expression_list:
+ self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
+ return self.interpreter.expression_list
+
+ def get_set_expressions(self):
+ setelems = []
+ if not self.interpreter.expression_list:
+ self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
+ for elem in self.interpreter.expression_list:
+ if isinstance(elem, SetExpression):
+ setelems.append(elem)
+ return setelems
+
def _eval_rside_value(self, value): abstract()
def _compare_value(self, value): abstract()
@@ -279,7 +342,7 @@
return self.interpreter.errors
def expand_rule_elements(self, rule):
- """ Expans rule elements base on the reference.
+ """ Expands rule elements base on the reference.
Context is used for fetching the child elements for parent references
which uses asterisk identifier for selecting all child features:
'parent_feature.*' -> 'child_fea_1 and child_fea_2'.
@@ -298,7 +361,11 @@
else:
expanded_rule = expanded_element.rstrip()
elif token.lower() in OPERATORS:
- expanded_rule += ' %s ' % token
+ operator_class = OPERATORS[token]
+ if operator_class.PARAM_COUNT == 2:
+ expanded_rule += ' %s ' % token
+ else:
+ expanded_rule += '%s ' % token
else:
if expanded_rule:
expanded_rule += '%s'% token
@@ -337,13 +404,32 @@
def eval(self, ast, expression, value):
pass
- def get_keys(self, refs):
- return ASTInterpreter.extract_refs(refs)
+ def set(self, expression, value):
+ """
+ set a element described with expression to value
+ @param expression: the expression refering to a element
+ @param value: the value to set
+ @raise exception: when the setting value to expression fails.
+ """
+ pass
def get_children_for_reference(self, reference):
# implement ConE specific children expansion
pass
+ def convert_value(self, value):
+ if value in ('True', 'true', '1'):
+ return True
+ elif value in ('False', 'false', '0'):
+ return False
+ elif value in ('None',):
+ return None
+ else:
+ try:
+ return int(value)
+ except:
+ return value
+
def handle_terminal(self, expression):
try:
return int(expression)
@@ -374,10 +460,18 @@
def get_title(self):
return self.KEY
- def eval(self, context): pass
+ def is_terminal(self):
+ return False
+
+ def eval(self, context, **kwargs): pass
+
+ def get_refs(self): return []
class OneParamExpression(Expression):
PARAM_COUNT = 1
+ # OP that return itself
+ OP = lambda _, x : x
+
def __init__(self, ast, expression):
super(OneParamExpression, self).__init__(ast)
self.expression = expression
@@ -385,8 +479,11 @@
def __unicode__(self):
return u'%s %s' % (self.KEY, self.expression)
- def eval(self, context):
- self.value = self.OP(self.expression.eval(context))
+ def __str__(self):
+ return '%s %s' % (self.KEY, self.expression)
+
+ def eval(self, context, **kwargs):
+ self.value = self.OP(self.expression.eval(context))
context.eval(self.ast, self, self.value)
return self.value
@@ -403,38 +500,128 @@
def __unicode__(self):
return u'%s %s %s' % (self.left, self.KEY, self.right)
- def eval(self, context):
+ def __str__(self):
+ return '%s %s %s' % (self.left, self.KEY, self.right)
+
+ def eval(self, context, **kwargs):
self.value = self.OP(self.left.eval(context), self.right.eval(context))
context.eval(self.ast, self, self.value)
return self.value
class TwoOperatorBooleanExpression(TwoOperatorExpression):
- def eval(self, context):
- self.value = self.OP(bool(self.left.eval(context)), bool(self.right.eval(context)))
+ def eval(self, context, **kwargs):
+ self.value = self.OP(bool(self.left.eval(context, **kwargs)), bool(self.right.eval(context, **kwargs)))
context.eval(self.ast, self, self.value)
return self.value
-class TerminalExpression(Expression):
- KEY = 'terminal'
+class ReferenceTerminal(Expression):
+ PARAM_COUNT = 0
+ KEY = 'reference'
def __init__(self, ast, expression):
- super(TerminalExpression, self).__init__(ast)
+ super(ReferenceTerminal, self).__init__(ast)
+ if not ASTInterpreter.is_ref(unicode(expression)):
+ expression = ASTInterpreter.create_ref(expression)
self.expression = expression
- def eval(self, context):
+ def is_terminal(self):
+ return True
+
+ def eval(self, context, **kwargs):
""" Use context to eval the value
- Expression on TerminalExpression is feature reference or value
+ Expression on ReferenceTerminal is feature reference or value
context should handle the reference conversion to correct value
"""
- self.value = context.handle_terminal(self.expression)
+ self.value = context.handle_terminal(ASTInterpreter.clean_ref(self.expression))
+ return self.value
+
+ def get_ref(self):
+ """
+ @return: The setting reference, e.g. 'MyFeature.MySetting'
+ """
+ return ASTInterpreter.clean_ref(self.expression)
+
+ def get_refs(self):
+ """
+ """
+ return [u'%s' % self.get_ref()]
+
+ def __unicode__(self):
+ return self.expression
+
+ def __str__(self):
+ return "(%s => %s)" % (self.expression, self.value)
+
+ def __repr__(self):
+ return self.expression
+
+class ValueTerminal(Expression):
+ PARAM_COUNT = 0
+ KEY = 'value_terminal'
+
+ def __init__(self, ast, expression):
+ super(ValueTerminal, self).__init__(ast)
+ self.expression = expression
+
+ def is_terminal(self):
+ return True
+
+ def eval(self, context, **kwargs):
+ self.value = context.convert_value(self.expression)
return self.value
def __unicode__(self):
return self.expression
- def __repr__(self):
+ def __str__(self):
return self.expression
+class TypeCoercionError(exceptions.ConeException):
+ pass
+
+class AutoValueTerminal(Expression):
+ PARAM_COUNT = 0
+ KEY = 'autovalue_terminal'
+
+ def __init__(self, ast, expression):
+ super(AutoValueTerminal, self).__init__(ast)
+ self.expression = expression
+
+ def is_terminal(self):
+ return True
+
+ def eval(self, context, **kwargs):
+ type = kwargs.get('type', None)
+
+ if self.expression in ("None", None):
+ self.value = None
+ elif type in (types.IntType, types.FloatType):
+ try:
+ self.value = type(self.expression)
+ except ValueError:
+ raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
+ elif type == types.BooleanType:
+ if self.expression in ('True', 'true', True):
+ self.value = True
+ elif self.expression in ('False', 'false', False):
+ self.value = False
+ else:
+ raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
+ elif type in types.StringTypes:
+ self.value = unicode(self.expression)
+ elif type == types.ListType:
+ self.value = list(self.expression)
+ else:
+ raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
+ return self.value
+
+ def __unicode__(self):
+ return self.expression
+
+ def __str__(self):
+ return self.expression
+
+
class NegExpression(OneParamExpression):
PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
KEY= '-'
@@ -470,6 +657,11 @@
KEY = '=='
OP = ops.eq
+ def eval(self, context, **kwargs):
+ self.value = self.OP(self.left.eval(context), self.right.eval(context))
+ context.eval(self.ast, self, self.value)
+ return self.value
+
class NotEqualExpression(TwoOperatorExpression):
PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
KEY = '!='
@@ -496,6 +688,59 @@
OP = ops.ge
+def handle_multiply(self, left, right):
+ return left * right
+
+class MultiplyExpression(TwoOperatorExpression):
+ expression = "multiply_operation"
+ PRECEDENCE = PRECEDENCES['MULDIV_OPERATORS']
+ KEY= '*'
+ OP = handle_multiply
+
+def handle_divide(self, left, right):
+ return left / right
+
+class DivideExpression(TwoOperatorExpression):
+ expression = "divide_operation"
+ PRECEDENCE = PRECEDENCES['MULDIV_OPERATORS']
+ KEY= '/'
+ OP = handle_divide
+
+def handle_plus(self, left, right):
+ return left + right
+
+class PlusExpression(TwoOperatorExpression):
+ expression = "plus_operation"
+ PRECEDENCE = PRECEDENCES['ADDSUB_OPERATORS']
+ KEY= '+'
+ OP = handle_plus
+
+def handle_minus(self, left, right):
+ return left - right
+
+class MinusExpression(TwoOperatorExpression):
+ expression = "minus_operation"
+ PRECEDENCE = PRECEDENCES['ADDSUB_OPERATORS']
+ KEY= '-'
+ OP = handle_minus
+
+def handle_set(self, left, right):
+ left.set_value(right)
+
+class SetExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['SET_OPERATORS']
+ KEY= '='
+ OP = handle_set
+
+ def eval(self, context, **kwargs):
+ if not isinstance(self.left, ReferenceTerminal):
+ raise RuntimeError("Can only set the value of a setting, '%s' is not a setting reference. Did you forget to use ${}?" % self.left.expression)
+
+ value = self.right.eval(context, **kwargs)
+ context.set(self.left.get_ref(), value, **kwargs)
+ return True
+
+
def handle_require(expression, left, right):
if left and right:
return True
@@ -508,13 +753,12 @@
KEY = 'requires'
OP = handle_require
- def eval(self, context):
+ def eval(self, context, **kwargs):
super(RequireExpression, self).eval(context)
if not self.value:
left_keys = []
for ref in self.ast.extract_refs(unicode(self.left)):
- for key in context.get_keys(ref):
- left_keys.append(key)
+ left_keys.append(ref)
for key in left_keys:
self.ast.add_error(key, { 'error_string' : 'REQUIRES right side value is "False"',
@@ -535,13 +779,12 @@
KEY = 'excludes'
OP = handle_exclude
- def eval(self, context):
+ def eval(self, context, **kwargs):
super(ExcludeExpression, self).eval(context)
if not self.value:
left_keys = []
for ref in self.ast.extract_refs(unicode(self.left)):
- for key in context.get_keys(ref):
- left_keys.append(key)
+ left_keys.append(ref)
for key in left_keys:
self.ast.add_error(key, { 'error_string' : 'EXCLUDE right side value is "True"',
@@ -568,11 +811,38 @@
A simple condition object that can refer to a model object and evaluate if the value matches
"""
def __init__(self, left, right):
- lterm = TerminalExpression(None, left)
- rterm = TerminalExpression(None, right)
+ if isinstance(left, basestring) and ASTInterpreter.is_ref(left):
+ lterm = ReferenceTerminal(None, left)
+ else:
+ lterm = ValueTerminal(None, left)
+ if isinstance(right, basestring) and ASTInterpreter.is_ref(right):
+ rterm = ReferenceTerminal(None, right)
+ else:
+ rterm = AutoValueTerminal(None, right)
EqualExpression.__init__(self, None, lterm, rterm)
-
+ def eval(self, context, **kwargs):
+ left_value = self.left.eval(context)
+ try:
+ right_value = self.right.eval(context, type=type(left_value))
+ except TypeCoercionError:
+ # If type coercion fails, the result is always False
+ self.value = False
+ return self.value
+
+ # Type coercion successful, perform value comparison
+ self.value = self.OP(left_value, right_value)
+ context.eval(self.ast, self, self.value)
+ return self.value
+
+ def get_refs(self):
+ result = []
+ if isinstance(self.left, ReferenceTerminal):
+ result.append(self.left.get_ref())
+ if isinstance(self.right, ReferenceTerminal):
+ result.append(self.right.get_ref())
+ return result
+
# in format KEY : OPERATOR CLASS
OPERATORS = {
'and' : AndExpression,
@@ -590,7 +860,11 @@
'>=' : GreaterThanEqualExpression,
'requires' : RequireExpression,
'excludes' : ExcludeExpression,
- '-' : NegExpression
+ '-' : MinusExpression,
+ '+' : PlusExpression,
+ '*' : MultiplyExpression,
+ '/' : DivideExpression,
+ '=' : SetExpression
}
def add_operator(key, operator_class=None, baseclass=RequireExpression):
@@ -613,6 +887,29 @@
class ParseException(Exception): pass
+def is_str_literal(value):
+ """
+ return true if the value is a string literal. A string that begins and ends with single or douple quotes.
+ @param value: the value to investigate
+ @return: Boolean
+ """
+ if isinstance(value, (str, unicode)):
+ if re.match("[\"\'].*[\"\']", value):
+ return True
+ return False
+
+def get_str_literal(value):
+ """
+ return the string literal value
+ @param value: the value to convert
+ @return: string or unicode based on the input value
+ """
+ if isinstance(value, (str, unicode)):
+ m = re.match("[\"\'](.*)[\"\']", value)
+ if m:
+ return m.group(1)
+ return None
+
class ASTInterpreter(object):
def __init__(self, infix_expression=None, context=None):
""" Takes infix expression as string """
@@ -629,6 +926,7 @@
self.errors = {}
self.postfix_array = []
self.parse_tree = []
+ self.expression_list = []
self.expression = infix_expression
def __unicode__(self):
@@ -652,11 +950,11 @@
def _infix_to_postfix(self):
"""
- Shunting yard algorithm used to convert infix presentation to postfix.
+ Shunting yard algorithm used to convert infix presentation to postxfix.
"""
if not self.expression:
raise ParseException('Expression is None')
- tokens = get_tokens(self.expression) # [token for token in self.expression.split()]
+ tokens = get_tokens(self.expression)
stack = []
# logger.debug('TOKENS: %s' % tokens)
for token in tokens:
@@ -721,6 +1019,7 @@
def _create_parse_tree(self):
self.parse_tree = []
for token in self.postfix_array:
+ is_ref = ASTInterpreter.is_ref(token)
if token in OPERATORS:
# logger.debug('OP: %s' % (token))
expression_class = OPERATORS[token]
@@ -735,9 +1034,15 @@
# logger.debug('The operation: %s' % expression)
self.parse_tree.append(expression)
+ self.expression_list.append(expression)
+ elif not is_ref:
+ expression = ValueTerminal(self, token)
+ self.parse_tree.append(expression)
+ self.expression_list.append(expression)
else:
- expression = TerminalExpression(self, token)
+ expression = ReferenceTerminal(self, token)
self.parse_tree.append(expression)
+ self.expression_list.append(expression)
#logger.debug('THE STACK: %s' % self.parse_tree)
#for s in self.parse_tree:
@@ -745,22 +1050,41 @@
return self.parse_tree
- def eval(self):
+ def eval(self, context=None, **kwargs):
""" Evals the AST
If empty expression is given, None is returned
"""
for expression in self.parse_tree:
- self.value = expression.eval(self.context)
+ self.value = expression.eval(context or self.context, **kwargs)
return self.value
@staticmethod
def extract_refs(expression):
tokens = get_tokens(expression)
- refs = []
- for token in tokens:
- if not token.lower() in OPERATORS and token != LEFT_PARENTHESIS and token != RIGHT_PARENTHESIS:
- refs.append(token.strip('%s%s' % (LEFT_PARENTHESIS, RIGHT_PARENTHESIS)))
- return refs
+ return [ASTInterpreter.clean_ref(t) for t in tokens if t.lower() not in OPERATORS and\
+ t not in (LEFT_PARENTHESIS, RIGHT_PARENTHESIS) and\
+ ASTInterpreter.is_ref(t)]
+
+ @staticmethod
+ def extract_non_operators(expression):
+ tokens = get_tokens(expression)
+ return [ASTInterpreter.clean_ref(t) for t in tokens if t.lower() not in OPERATORS and\
+ t not in (LEFT_PARENTHESIS, RIGHT_PARENTHESIS)]
+
+ @staticmethod
+ def clean_ref(ref):
+ return ref.replace('$', '').replace('{', '').replace('}', '')
+
+ @staticmethod
+ def create_ref(ref):
+ return '${%s}' % ref
+
+ @staticmethod
+ def is_ref(val):
+ mo = REF_REGEX.match(val)
+ if mo and len(mo.groups()) > 0 and mo.group() == val:
+ return True
+ return False
##################################################################
# Create and configure the main level logger
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/Import.pk
--- a/configurationengine/source/cone/public/tests/Import.pk Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/Import.pk Tue Aug 10 14:29:28 2010 +0300
@@ -1,110 +1,110 @@
-ccopy_reg
-_reconstructor
-p0
-(ccone.storage.stringstorage
-StringStorage
-p1
-c__builtin__
-object
-p2
-Ntp3
-Rp4
-(dp5
-S'_order'
-p6
-(lp7
-S'test1'
-p8
-aS'test2'
-p9
-aS'test3'
-p10
-asS'container'
-p11
-I01
-sS'_children'
-p12
-(dp13
-g8
-g0
-(ccone.storage.stringstorage
-_StringStorageObject
-p14
-g2
-Ntp15
-Rp16
-(dp17
-S'_parent'
-p18
-g4
-sg6
-(lp19
-sg12
-(dp20
-sS'path'
-p21
-S'test1.txt'
-p22
-sS'data'
-p23
-S'Testing reading.\n'
-p24
-sS'_name'
-p25
-g8
-sbsg10
-g0
-(g14
-g2
-Ntp26
-Rp27
-(dp28
-g18
-g4
-sg6
-(lp29
-sg12
-(dp30
-sg21
-S'test3.txt'
-p31
-sg23
-g24
-sg25
-g10
-sbsg9
-g0
-(g14
-g2
-Ntp32
-Rp33
-(dp34
-g18
-g4
-sg6
-(lp35
-sg12
-(dp36
-sg21
-S'test2.txt'
-p37
-sg23
-g24
-sg25
-g9
-sbssS'curpath'
-p38
-S''
-p39
-sS'rootpath'
-p40
-S'temp/unload.pk'
-p41
-sg25
-S'C:\\DocumentsandSettings\\teerytko\\workspace\\cone_trunk\\source\\cone\\public\\tests\\Import_pk'
-p42
-sg18
-NsS'ref'
-p43
-g42
+ccopy_reg
+_reconstructor
+p0
+(ccone.storage.stringstorage
+StringStorage
+p1
+c__builtin__
+object
+p2
+Ntp3
+Rp4
+(dp5
+S'_order'
+p6
+(lp7
+S'test1'
+p8
+aS'test2'
+p9
+aS'test3'
+p10
+asS'container'
+p11
+I01
+sS'_children'
+p12
+(dp13
+g8
+g0
+(ccone.storage.stringstorage
+_StringStorageObject
+p14
+g2
+Ntp15
+Rp16
+(dp17
+S'_parent'
+p18
+g4
+sg6
+(lp19
+sg12
+(dp20
+sS'path'
+p21
+S'test1.txt'
+p22
+sS'data'
+p23
+S'Testing reading.\n'
+p24
+sS'_name'
+p25
+g8
+sbsg10
+g0
+(g14
+g2
+Ntp26
+Rp27
+(dp28
+g18
+g4
+sg6
+(lp29
+sg12
+(dp30
+sg21
+S'test3.txt'
+p31
+sg23
+g24
+sg25
+g10
+sbsg9
+g0
+(g14
+g2
+Ntp32
+Rp33
+(dp34
+g18
+g4
+sg6
+(lp35
+sg12
+(dp36
+sg21
+S'test2.txt'
+p37
+sg23
+g24
+sg25
+g9
+sbssS'curpath'
+p38
+S''
+p39
+sS'rootpath'
+p40
+S'temp/unload.pk'
+p41
+sg25
+S'Import_pk'
+p42
+sg18
+NsS'ref'
+p43
+g42
sb.
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/__init__.py
--- a/configurationengine/source/cone/public/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,34 +13,3 @@
#
# Description:
#
-
-import unittest, os, sys
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../..'))
-if SOURCE_ROOT not in sys.path:
- sys.path.append(SOURCE_ROOT)
-
-# Find all unittest_*.py files in this folder
-import re
-__all__ = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(ROOT_PATH))
-# Strip .py endings
-__all__ = map(lambda name: name[:-3], __all__)
-
-def collect_suite():
- sys.path.insert(0, ROOT_PATH)
- try:
- suite = unittest.TestSuite()
- for test_module in __all__:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- del sys.path[0]
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/runtests.py
--- a/configurationengine/source/cone/public/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/test_defaults.cfg
--- a/configurationengine/source/cone/public/tests/test_defaults.cfg Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/test_defaults.cfg Tue Aug 10 14:29:28 2010 +0300
@@ -1,6 +1,6 @@
[DEFAULT]
-output_root=output
+output_root=
output_subdir=
plugin_output=
output=%(output_root)s/%(output_subdir)s/%(plugin_output)s
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/layer1/implml/test.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/layer1/implml/test.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/customisation/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/customisation/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/customisation/confml/my_standard_view.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/customisation/confml/my_standard_view.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,77 @@
+
+
+
+ This is my test view.
+
+ Different example settings.
+
+ Different string settings.
+
+ Overrided description for ExampleString1.
+
+
+
+
+
+
+
+
+
+
+ Different int settings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mailbox group - with no id!!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sequence test in view, full, splitted, full with asterisks
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/customisation/root_standard.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/customisation/root_standard.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/mailboxes.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/mailboxes.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,99 @@
+
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+ Mailbox1 description
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/options_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/options_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/unit-test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/confml/unit-test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,368 @@
+
+
+
+
+ Some int constraints testing
+
+
+ Integer 1, must be equal or bigger than #2
+
+
+ Integer 2, must be equal or smaller than #1
+
+
+ Integer 3, relevant only if int1 is 4
+
+
+ Integer 4, relevant only if int2 is 3, must be same as int3
+
+
+
+
+ Some german cars
+
+ Example sequence containing one string and one int
+
+
+ Car string in sequence description
+
+
+ Car int in sequence description
+
+
+
+
+
+
+ Some japan cars
+
+ Example sequence containing one string and one int
+
+
+ Car string in sequence description
+
+
+ Car int in sequence description
+
+
+
+
+
+
+ Some italy cars
+
+ Example sequence containing one string and one int
+
+
+ Car string in sequence description
+
+
+ Car int in sequence description
+
+
+
+
+
+
+ Some bikes
+
+ Example sequence containing one string and one int
+
+
+ Bike string in sequence description
+
+
+ Bike int in sequence description
+
+
+
+
+
+
+ This is example feature group description
+
+
+ Example string description. Min length 10, max 50.
+
+
+
+
+ Example number description. Value must be between 2000-2100 (inclusive)
+
+
+
+
+
+ Example string description 2. Not required field. Length 5 characters.
+
+
+
+
+
+
+
+
+
+
+ Example number description 2. Value must be between 0-799 (exclusive 800)
+
+
+
+
+
+
+
+
+ Example number description 3. Value must be between 10-20.
+
+
+
+
+
+ Example file. Target read only, pattern .*\.png
+
+
+
+
+
+
+
+
+ Example folder.
+
+
+
+
+
+ Example real description. Not required field.
+
+
+
+ Example selection numbers from 1 to 5
+
+
+
+
+
+
+
+
+
+ Example multi selection characters from A to E
+
+
+
+
+
+
+
+
+ Example boolean
+
+
+
+ Example sequence containing one string and one int
+
+
+ Example string in sequence description
+
+
+ Example int in sequence description
+
+
+
+
+
+ Example date description
+
+
+
+ Example time description
+
+
+
+ Example date/time description
+
+
+
+ Example duration description, 2 days, 5 hours
+
+
+
+
+
+ This is another example feature group for testing different map options
+
+
+ Example selection values (options)
+
+
+
+
+
+
+
+
+
+ Example selection to one map, German cars
+
+
+
+
+ Example selection to one map, Italian cars
+
+
+
+
+ Example selection to one map, Japanese cars
+
+
+
+
+ Example selection to three maps, German, Italian and Japanese cars
+
+
+
+
+
+
+ Example selection to four maps, bikes, all cars and some option values also
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Example multi selection values from x to y and map to bikes
+
+
+
+
+
+
+
+
+
+
+ 4
+ 2
+ 3
+ 3
+
+
+
+
+ Audi
+ 111
+
+
+ Bmw
+ 222
+
+
+
+
+
+ Subaru
+ 555
+
+
+ Mitsubishi
+ 666
+
+
+ Toyota
+ 777
+
+
+
+
+
+ Ferrari
+ 888
+
+
+ Fiat
+ 999
+
+
+
+
+
+ Tunturi
+ 28
+
+
+ Helkama
+ 26
+
+
+
+
+ The Year (Current)
+ 2009
+ Hello
+ 555
+ 13
+ 3.14
+
+ somefile.png
+ BUILD:///data
+
+
+ UI/Application data
+ BUILD:///data/UI
+
+ 3
+ "B B" "C C" "E E"
+ true
+
+ Some century
+ 1900
+
+
+ Some century X
+ 2101
+
+
+
+ Django!
+ 1
+
+
+
+ Fox
+ 3
+
+
+ 2009-01-19Z
+ 09:15:00
+ 2009-01-19T09:15:00Z
+ P2DT2H
+
+
+
+
+ 2
+ 222
+ 888
+ 777
+ 666
+
+ 6
+ "3" "26"
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/unit-test/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/testdata/view_tests/view_tests-cpf.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/testdata/view_tests/view_tests-cpf.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+
+
+
+
+ 234
+ 031.001
+ S60 / 3.2
+ tiger
+ 2009-11-17
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_base.py
--- a/configurationengine/source/cone/public/tests/unittest_base.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_base.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,11 +18,8 @@
Test the configuration
"""
import unittest
-import string
-import sys,os
-import __init__
-from cone.public import api,exceptions,utils, container
+from cone.public import api, container
class TestBase(unittest.TestCase):
# @test
@@ -35,6 +32,11 @@
self.assertTrue(base)
self.assertEquals(base.namespace,"")
+ def test_get_configuration(self):
+ base= api.Base("foo")
+ self.assertEquals(base.get_configuration(),None)
+ self.assertEquals(base.get_configuration_path(),None)
+
def test_properties(self):
base= api.Base("foo")
self.assertTrue(base)
@@ -52,7 +54,7 @@
self.assertEquals(base.bar.fqr, 'foo.bar')
self.assertEquals(base.bar.get_fullfqr(), 'foo.bar')
- def test_create_hiearchy_with_container(self):
+ def test_create_hiearchy_with_container_test_path(self):
cont= api.Base("", container=True)
base= api.Base("foo")
base._add(api.Base("bar1"))
@@ -65,6 +67,20 @@
self.assertEquals(cont.foo.bar1.namespace, 'foo')
self.assertEquals(cont.foo.bar2.bar21.namespace, 'foo.bar2')
self.assertEquals(cont.foo.bar2.bar21.fqr, 'foo.bar2.bar21')
+ self.assertEquals(cont.foo.bar2.bar21.path(cont.foo.bar2), 'bar21')
+ self.assertEquals(cont.foo.bar2.bar21.path(cont.foo), 'bar2.bar21')
+ self.assertEquals(cont.foo.bar2.bar21.path(cont), 'foo.bar2.bar21')
+
+ def test_create_hiearchy_with_container_test_parent_path(self):
+ cont= api.Base("", container=True)
+ base= api.Base("foo")
+ base._add(api.Base("bar1"))
+ base._add(api.Base("bar2"))
+ base.bar2._add(api.Base("bar21"))
+ cont._add(base)
+ self.assertEquals(cont.foo.bar2.bar21.parent_path(cont.foo.bar2), '')
+ self.assertEquals(cont.foo.bar2.bar21.parent_path(cont.foo), 'bar2')
+ self.assertEquals(cont.foo.bar2.bar21.parent_path(cont), 'foo.bar2')
def test_create_hiearchy_with_container_and_hidden_elem(self):
cont= api.Base("", container=True)
@@ -99,5 +115,4 @@
self.assertEquals(cont.foo.bar1[0].bar21.get_fullfqr(), 'foo.bar1[0].bar21')
if __name__ == '__main__':
- unittest.main()
-
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_configuration.py
--- a/configurationengine/source/cone/public/tests/unittest_configuration.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_configuration.py Tue Aug 10 14:29:28 2010 +0300
@@ -12,19 +12,20 @@
# Contributors:
#
# Description:
-#
+#
"""
Test the configuration
"""
import unittest
-import string
-import sys,os
-import __init__
+import os
+import pickle
-from cone.public import api,exceptions,utils
+from cone.public import api,exceptions
from cone.storage import persistentdictionary
-from cone.confml import persistentconfml
+from testautomation.utils import remove_if_exists
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
class TestConfiguration(unittest.TestCase):
def setUp(self):
@@ -35,6 +36,29 @@
conf = api.Configuration("testmee.confml")
self.assertTrue(conf)
+ def test_configuration_reduce_ex(self):
+ prj = api.Project(api.Storage('.'))
+ conf = api.Configuration("testmee.confml")
+ prj.add_configuration(conf)
+ tpl = conf.__reduce_ex__(2)
+ self.assertEquals(tpl[2]['_storeint'],prj)
+ self.assertEquals(tpl[2]['path'],'testmee.confml')
+
+ def test_configuration_pickle(self):
+ remove_if_exists(os.path.join(ROOT_PATH,'temp'))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'temp'), 'w'))
+ conf = api.Configuration("testmee.confml")
+ prj.add_configuration(conf, True)
+ prj.save()
+ dfile = open(os.path.join(ROOT_PATH,'temp/out.dat'), 'w')
+ pickle.dump(conf, dfile)
+ dfile.close()
+ dfile = open(os.path.join(ROOT_PATH,'temp/out.dat'))
+ conf2 = pickle.load(dfile)
+ self.assertEquals(conf2.path,'testmee.confml')
+ self.assertEquals(conf2.name,'testmee_confml')
+
+
def test_get_root_configuration(self):
conf = api.Configuration("testmee.confml")
self.assertEquals(conf.get_root_configuration(),conf)
@@ -64,6 +88,16 @@
self.assertEquals(conf1.ref,conf2.ref)
self.assertEquals(conf1.namespace,conf2.namespace)
+ def test_get_configuration_and_path(self):
+ conf1 = api.Configuration("testmee.confml")
+ fea = conf1.create_feature('test1')
+ conf1.create_feature('test2')
+ subfea = fea.create_feature('child1')
+ self.assertEquals(fea.get_configuration(), conf1)
+ self.assertEquals(fea.get_configuration_path(), 'testmee.confml')
+ self.assertEquals(subfea.get_configuration(), conf1)
+ self.assertEquals(subfea.get_configuration_path(), 'testmee.confml')
+
def test_clone_single_configuration(self):
conf1 = api.Configuration("testmee.confml")
conf1.add_feature(api.Feature('test1'))
@@ -104,28 +138,28 @@
def test_add(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
+ conf.add_configuration(layer)
self.assertEquals(conf.list_configurations()[0],"laa")
def test_add_and_access_via_member(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- self.assertEquals(conf.laa._name,"laa")
+ conf.add_configuration(layer)
+ self.assertEquals(conf.laa.name,"laa")
def test_add_and_add_another_config_under(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf.laa._add(api.Configuration("foo"))
- self.assertEquals(conf.laa.foo._name,"foo")
+ conf.add_configuration(layer)
+ conf.laa.add_configuration(api.Configuration("foo"))
+ self.assertEquals(conf.laa.foo.name,"foo")
def test_add_several_configurations(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf._add(api.Configuration("foo"))
- conf._add(api.Configuration("faa"))
+ conf.add_configuration(layer)
+ conf.add_configuration(api.Configuration("foo"))
+ conf.add_configuration(api.Configuration("faa"))
self.assertEquals(conf.list_configurations()[0],"laa")
self.assertEquals(conf.list_configurations()[1],"foo")
self.assertEquals(conf.list_configurations()[2],"faa")
@@ -133,10 +167,10 @@
def test_add_several_and_remove_one_layer(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf._add(api.Configuration("foo"))
- conf._add(api.Configuration("faa"))
- conf._remove("foo")
+ conf.add_configuration(layer)
+ conf.add_configuration(api.Configuration("foo"))
+ conf.add_configuration(api.Configuration("faa"))
+ conf.remove_configuration("foo")
self.assertEquals(conf.list_configurations()[0],"laa")
self.assertEquals(conf.list_configurations()[1],"faa")
@@ -144,101 +178,108 @@
def test_add_several_and_remove_last_layer(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf._add(api.Configuration("foo"))
- conf._add(api.Configuration("faa"))
- conf._remove("faa")
+ conf.add_configuration(layer)
+ conf.add_configuration(api.Configuration("foo"))
+ conf.add_configuration(api.Configuration("faa"))
+ conf.remove_configuration("faa")
self.assertEquals(conf.list_configurations()[0],"laa")
self.assertEquals(conf.list_configurations()[1],"foo")
def test_add_several_and_remove_all_configurations(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf._add(api.Configuration("foo"))
- conf._add(api.Configuration("faa"))
+ conf.add_configuration(layer)
+ conf.add_configuration(api.Configuration("foo"))
+ conf.add_configuration(api.Configuration("faa"))
for layername in conf.list_configurations():
- conf._remove(layername)
+ conf.remove_configuration(layername)
self.assertTrue(len(conf.list_configurations())==0)
def test_add_several_and_try_to_remove_not_existing(self):
conf = api.Configuration("data/simple.confml")
layer = api.Configuration("laa")
- conf._add(layer)
- conf._add(api.Configuration("foo"))
- conf._add(api.Configuration("faa"))
+ conf.add_configuration(layer)
+ conf.add_configuration(api.Configuration("foo"))
+ conf.add_configuration(api.Configuration("faa"))
try:
- conf._remove("notthere")
+ conf.remove_configuration("notthere")
self.fail("removing of nonexisting layer succeeds!")
except exceptions.NotFound:
pass
- def test_add_view_simple(self):
+ def test_create_view_simple(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
+ conf.create_view("view1")
view = conf.get_view("view1")
- self.assertEquals(view._list(),[])
+ self.assertEquals(view.list_groups(),[])
- def test_add_views_and_list_views(self):
+ def test_create_views_and_list_views(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
- conf.add_view("view2")
+ conf.create_view("view1")
+ conf.create_view("view2")
self.assertEquals(conf.list_views(),['view1','view2'])
- def test_add_views_and_remove_one(self):
+ def test_create_views_and_remove_one(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
- conf.add_view("view2")
- conf.add_view("view3")
+ conf.create_view("view1")
+ conf.create_view("view2")
+ conf.create_view("view3")
conf.remove_view('view2')
self.assertEquals(conf.list_views(),['view1','view3'])
- def test_add_views_and_remove_invalid(self):
+ def test_create_views_and_remove_invalid(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
- conf.add_view("view2")
- conf.add_view("view3")
+ conf.create_view("view1")
+ conf.create_view("view2")
+ conf.create_view("view3")
try:
conf.remove_view('invalid')
self.fail('Removing invalid view succeeds!')
except exceptions.NotFound:
pass
- def test_add_views_and_remove_all(self):
+ def test_create_views_and_remove_all(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
- conf.add_view("view2")
- conf.add_view("view3")
+ conf.create_view("view1")
+ conf.create_view("view2")
+ conf.create_view("view3")
for view in conf.list_views():
conf.remove_view(view)
self.assertEquals(conf.list_views(),[])
- def test_add_view_with_data(self):
+ def test_create_view_with_data(self):
conf = api.Configuration("data/simple.confml")
- conf.add_view("view1")
+ conf.create_view("view1")
view = conf.get_view("view1")
- view._add(api.Group("group1"))
- view._add(api.Group("group2"))
- view._add(api._FeatureProxy("feature1"))
- view.group1._add(api.Group("group21"))
- view.group1.group21._add(api._FeatureProxy("feature211"))
- view.group1.group21._add(api._FeatureProxy("feature212"))
- view.feature1._add(api._FeatureProxy("feature11"))
+ view.add_group(api.Group("group1"))
+ view.add_group(api.Group("group2"))
+ view.create_featurelink("feature1")
+ view.group1.add_group(api.Group("group21"))
+ view.group1.group21.create_featurelink("feature211")
+ view.group1.group21.create_featurelink("feature212")
self.assertEquals(sorted(view._list_traverse()),
sorted(['group1',
- 'group2',
- 'feature1',
- 'group1.group21',
- 'group1.group21.feature211',
- 'group1.group21.feature212',
- 'feature1.feature11']))
+ 'group1.group21',
+ 'group1.group21.link_feature211',
+ 'group1.group21.link_feature212',
+ 'group2',
+ 'link_feature1']))
def test_get_default_view(self):
conf = api.Configuration("data/simple.confml")
dview = conf.get_default_view()
- self.assertEquals(dview.ref,'_default_view')
+ self.assertEquals(dview.ref,'?default_view')
+
+ def test_create_configuration_and_features(self):
+ conf = api.Configuration("data/simple.confml")
+ fea = conf.create_feature("test")
+ self.assertEquals(conf.get_feature('test'), fea)
+ fea = conf.create_feature("test1", name="test name")
+ self.assertEquals(conf.get_feature('test1').name, 'test name')
+ fea.create_feature("subfea", name="subfea name")
+ self.assertEquals(conf.list_all_features(), ['test','test1','test1.subfea'])
def test_get_default_view_and_data_to_it(self):
conf = api.Configuration("data/simple.confml")
@@ -329,14 +370,34 @@
# conf.add_feature(api.Feature("feature1"))
# self.assertEquals(conf.list_all_features(),['com.nokia.feature1'])
# self.assertEquals(conf.feature1, conf.get_default_view().com.nokia.feature1._obj)
+ def test_get_path_for_parent(self):
+ conf = api.Configuration("test.confml")
+ conf.create_configuration("foo/root.confml")
+ conf.get_configuration("foo/root.confml").create_configuration("confml/jee.confml")
+ self.assertEquals(conf.get_path_for_parent(None), "test.confml")
+ self.assertEquals(conf.get_configuration("foo/root.confml").get_path_for_parent(None), "foo/root.confml")
+ foo = conf.get_configuration("foo/root.confml")
+ jee = foo.get_configuration("confml/jee.confml")
+ self.assertEquals(foo.get_path_for_parent(conf), "foo/root.confml")
+ self.assertEquals(jee.get_path_for_parent(conf), "foo/confml/jee.confml")
+ self.assertEquals(jee.get_path_for_parent(foo._obj), "confml/jee.confml")
+
def test_add_subconfiguration(self):
conf = api.Configuration("test",namespace="com.nokia")
conf.create_configuration("foo/root.confml")
conf.create_configuration("platforms/s60.confml")
+ dconf = api.Configuration('confml/data.confml')
+ sconf = conf.get_configuration('foo/root.confml')
+ sconf.add_configuration(dconf)
self.assertEquals(conf.list_configurations(),['foo/root.confml',
'platforms/s60.confml',])
-
+ self.assertEquals(conf.list_all_configurations(),['foo/root.confml',
+ 'foo/confml/data.confml',
+ 'platforms/s60.confml'])
+ self.assertEquals(conf.get_configuration('foo/root.confml').list_all_configurations(),['confml/data.confml'])
+
+
def test_remove_configuration(self):
conf = api.Configuration("test.confml",namespace="com.nokia")
conf.create_configuration("foo/root.confml")
@@ -482,7 +543,7 @@
conf.add_feature(api.Feature('feature11'),'feature1')
conf.add_feature(api.Feature('feature12'),'feature1')
- conf.add_view("rootfeas")
+ conf.create_view("rootfeas")
view = conf.get_view('rootfeas')
for fearef in conf.list_features():
fea = conf.get_feature(fearef)
@@ -504,16 +565,22 @@
conf.add_feature(api.Feature('feature4'))
conf.add_feature(api.Feature('feature11'),'feature1')
conf.add_feature(api.Feature('feature12'),'feature1')
- conf.add_view('fea1')
+ conf.create_view('fea1')
view1 = conf.get_view('fea1')
- view1.add_group('thegruppe1')
+ view1.create_group('thegruppe1')
view1.get_group('thegruppe1').add(api.FeatureLink('feature1.feature11'))
view1.add(api.FeatureLink('feature1.*'))
view1.populate()
- self.assertEquals(view1.list_all_features(),['thegruppe1.feature11','feature11','feature12'])
- fpr = view1.get_feature('thegruppe1.feature11')
+ self.assertEquals(view1.list_all_features(),
+ ['thegruppe1.proxy_feature1_feature11',
+ 'proxy_feature1_feature11',
+ 'proxy_feature1_feature12'])
+ fpr = view1.get_feature('thegruppe1.proxy_feature1_feature11')
self.assertEquals(fpr._obj.fqr,conf.get_default_view().get_feature('feature1.feature11').fqr)
- self.assertEquals(view1.list_all_features(), ['thegruppe1.feature11','feature11','feature12'])
+ self.assertEquals(view1.list_all_features(),
+ ['thegruppe1.proxy_feature1_feature11',
+ 'proxy_feature1_feature11',
+ 'proxy_feature1_feature12'])
def test_add_features_and_create_all_view_with_links(self):
conf = api.Configuration("foo/foo.confml")
@@ -523,12 +590,18 @@
conf.add_feature(api.Feature('feature4'))
conf.add_feature(api.Feature('feature11'),'feature1')
conf.add_feature(api.Feature('feature12'),'feature1')
- conf.add_view("all")
+ conf.create_view("all")
view1 = conf.get_view('all')
view1.add(api.FeatureLink('**'))
view1.populate()
- self.assertEquals(view1.list_all_features(),['feature1', 'feature11', 'feature12', 'feature2', 'feature3', 'feature4'])
- fpr = view1.get_feature('feature11')
+ self.assertEquals(view1.list_all_features(),
+ ['proxy_feature1',
+ 'proxy_feature1_feature11',
+ 'proxy_feature1_feature12',
+ 'proxy_feature2',
+ 'proxy_feature3',
+ 'proxy_feature4'])
+ fpr = view1.get_feature('proxy_feature1_feature11')
self.assertEquals(fpr._obj.fqr,conf.get_default_view().get_feature('feature1.feature11').fqr)
def test_add_a_configuration_and_remove_it(self):
@@ -586,6 +659,76 @@
self.assertEquals(conf.data.feature1.feature12.get_value(),"test")
conf.remove_data('feature1.feature12')
self.assertEquals(conf.list_datas(), ['feature1'])
+
+ def test_add_data_to_configuration_from_list(self):
+ def check(data_objs, policy, expected):
+ conf = api.Configuration("foo/foo.confml")
+ conf.add_data(api.Data(ref='base1', value="foo"))
+ conf.add_data(api.Data(ref='foo', value="foobar"))
+ conf.add_data(api.Data(ref='base2', value="bar"))
+
+ if policy is None:
+ conf.add_data(data_objs)
+ else:
+ conf.add_data(data_objs, policy=policy)
+
+ actual = []
+ for d in conf._traverse(type=api.Data):
+ actual.append((d.fqr, d.value))
+ self.assertEquals(actual, expected)
+
+ # Adding an empty list should do nothing
+ check(data_objs = [],
+ policy = None,
+ expected = [('base1', 'foo'),
+ ('foo', 'foobar'),
+ ('base2', 'bar')])
+
+ # Default policy (replace)
+ check(data_objs = [api.Data(ref="foo", value="1"),
+ api.Data(ref="foo", value="2"),
+ api.Data(ref="foo", value="3"),],
+ policy = None,
+ expected = [('base1', 'foo'),
+ ('foo', '1'),
+ ('foo', '2'),
+ ('foo', '3'),
+ ('base2', 'bar')])
+
+ # Replace explicitly
+ check(data_objs = [api.Data(ref="foo", value="1"),
+ api.Data(ref="foo", value="2"),
+ api.Data(ref="foo", value="3"),],
+ policy = api.container.REPLACE,
+ expected = [('base1', 'foo'),
+ ('foo', '1'),
+ ('foo', '2'),
+ ('foo', '3'),
+ ('base2', 'bar')])
+
+ # Append
+ check(data_objs = [api.Data(ref="foo", value="1"),
+ api.Data(ref="foo", value="2"),
+ api.Data(ref="foo", value="3"),],
+ policy = api.container.APPEND,
+ expected = [('base1', 'foo'),
+ ('foo', 'foobar'),
+ ('foo', '1'),
+ ('foo', '2'),
+ ('foo', '3'),
+ ('base2', 'bar')])
+
+ # Prepend
+ check(data_objs = [api.Data(ref="foo", value="1"),
+ api.Data(ref="foo", value="2"),
+ api.Data(ref="foo", value="3"),],
+ policy = api.container.PREPEND,
+ expected = [('base1', 'foo'),
+ ('foo', '1'),
+ ('foo', '2'),
+ ('foo', '3'),
+ ('foo', 'foobar'),
+ ('base2', 'bar')])
def test_set_data_to_configuration(self):
conf = api.Configuration("foo/foo.confml")
@@ -672,13 +815,12 @@
fea = conf.get_feature('feature1')
fea.set_template(['test1','test2','test3'])
self.assertEquals(fea.get_template(),['test1', 'test2', 'test3'])
- fea.set_template(['test1','test3'])
- self.assertEquals(fea.get_template(),['test1','test3','test3'])
- try:
- fea.set_template(['test1',None,'test3',None])
- self.fail("Able to add more data then allowed")
- except IndexError:
- pass
+ fea.set_template(['Test1','Test2','Test3'])
+ self.assertEquals(fea.get_template(),['Test1','Test2','Test3'])
+
+ self.assertRaises(ValueError, fea.set_template, [])
+ self.assertRaises(ValueError, fea.set_template, ['foo', 'bar'])
+ self.assertRaises(ValueError, fea.set_template, ['foo', 'bar', 'foo', 'bar'])
def test_create_features_with_rfs_data(self):
conf = api.Configuration("foo/foo.confml")
@@ -707,8 +849,8 @@
def test_dumps_add_features(self):
root = api.Configuration("root",namespace="com.nokia")
conf = root.create_configuration("test.confml")
- conf.add_feature(api.Feature("feature1"))
- conf.add_feature(api.Feature("feature2"))
+ conf.add_feature(api.Feature("feature1", name="feature1"))
+ conf.add_feature(api.Feature("feature2", name="feature2"))
dumped = persistentdictionary.DictWriter().dumps(conf)
dict =dumped['Configuration']['dict']
self.assertEquals(dict['path'],'test.confml')
@@ -720,7 +862,6 @@
def test_dumps_root_configuration(self):
root = api.Configuration("root",namespace="com.nokia")
- conf = root.create_configuration("test.confml")
conf = root.create_configuration("foo/root.confml")
conf.add_feature(api.Feature("feature1"))
conf.add_feature(api.Feature("feature2"))
@@ -734,10 +875,10 @@
def test_dumps_feature_hierarchy(self):
root = api.Configuration("root",namespace="com.nokia")
conf = root.create_configuration("test.confml")
- conf.add_feature(api.Feature("feature1"))
- conf.add_feature(api.Feature("feature2"))
- conf.feature1.add_feature(api.Feature("feature11"))
- conf.feature1.add_feature(api.Feature("feature12"))
+ conf.add_feature(api.Feature("feature1", name="feature1"))
+ conf.add_feature(api.Feature("feature2", name="feature2"))
+ conf.feature1.add_feature(api.Feature("feature11", name="feature11"))
+ conf.feature1.add_feature(api.Feature("feature12", name="feature12"))
dumped = persistentdictionary.DictWriter().dumps(conf)
dict =dumped['Configuration']['dict']
self.assertEquals(dict['path'],'test.confml')
@@ -792,9 +933,9 @@
def test_dumps_and_loads_configuration_hierarchy(self):
root = api.Configuration("root.confml")
- root.add_configuration(api.Configuration("layer1.confml"))
- layer = api.Configuration("foo/layer2.confml")
- conf = api.Configuration("foo/test.confml")
+ root.add_configuration(api.Configuration("layer1"))
+ layer = api.Configuration("layer2")
+ conf = api.Configuration("test")
conf.add_feature(api.Feature("feature1"))
conf.add_feature(api.Feature("feature2"))
conf.feature1.add_feature(api.Feature("feature11"))
@@ -809,8 +950,8 @@
def test_dumps_and_loads_configuration_hierarchy_with_data(self):
root = api.Configuration("root.confml")
- layer = api.Configuration("foo/layer1.confml")
- conf = api.Configuration("foo/test.confml")
+ layer = api.Configuration("layer1")
+ conf = api.Configuration("test")
conf.add_feature(api.Feature("feature1"))
conf.add_feature(api.Feature("feature2"))
conf.feature1.add_feature(api.Feature("feature11"))
@@ -819,7 +960,7 @@
conf.feature2.set_value(2)
layer.add_configuration(conf)
root.add_configuration(layer)
- root.add_configuration(api.Configuration("layer2.confml"))
+ root.add_configuration(api.Configuration("layer2"))
root.get_default_view().feature1.feature11.set_value("testing11")
root.get_default_view().feature1.set_value("test1")
dumped = persistentdictionary.DictWriter().dumps(root)
@@ -831,21 +972,54 @@
self.assertEquals(root2.get_default_view().feature1.feature11.get_value(), "testing11")
self.assertEquals([data.find_parent(type=api.Configuration).get_path() for data in root2.get_all_datas()],
- ['foo/test.confml', 'foo/test.confml', 'layer2.confml','layer2.confml'])
+ ['test', 'test', 'layer2','layer2'])
def test_access_via_configuration_proxy(self):
conf = api.Configuration("root.confml")
conf.add_feature(api.Feature("feature1"))
proxy = api.ConfigurationProxy("root.confml")
- proxy.set('_obj',conf)
+ proxy._set_obj(conf)
self.assertEquals(proxy.get_ref(), 'root_confml')
self.assertEquals(proxy.get_path(), 'root.confml')
self.assertEquals(conf.feature1.get_ref(), 'feature1')
self.assertEquals(proxy.feature1.get_ref(), 'feature1')
+class TestConfigurationInclude(unittest.TestCase):
+ class StoreTestInt(object):
+ def load(self, ref):
+ return api.Configuration(ref)
+
+ def dump(self, obj, ref):
+ pass
+
+ def get_store_interface(self):
+ return TestConfigurationInclude.StoreTestInt()
+
+ def _test_include(self):
+ inc = api.Include("foo/bar.txt", self.get_store_interface())
+ objs =inc._objects()
+ self.assertEquals(len(objs),1)
+ self.assertEquals(objs[0].path,"foo/bar.txt")
+
+ def test_include_clone(self):
+ inc = api.Include("foo/bar.txt", store_interface=self.get_store_interface())
+ ci = inc._clone()
+ self.assertEquals(inc.ref, ci.ref)
+ self.assertEquals(inc.get_path(), ci.get_path())
+
+# def test_configuration_with_include(self):
+# conf = api.Configuration("foo.confml")
+# # Set the get_store_interface function to test stub method
+# conf.get_store_interface = self.get_store_interface
+# conf.include_configuration("foo/test.confml")
+# subconfs = conf.list_configurations()
+# self.assertEquals(len(subconfs),1)
+# self.assertTrue(isinstance(subconfs[0], api.Configuration))
+# self.assertEquals(subconfs[0].path,"foo/test.confml")
+
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
"""
{'Configuration': {'dict': {'path': 'root.confml', 'ref': 'root', 'namespace': '', 'desc': ''}, 'children': [{'Configuration': {'dict': {'path': 'foo/layer1.confml', 'ref': 'foo_layer1', 'namespace': '', 'desc': ''}, 'children': [{'Configuration': {'dict': {'path': 'foo/test.confml', 'ref': 'foo_test', 'namespace': '', 'desc': ''}, 'children': [{'Feature': {'dict': {'ref': 'feature1'}, 'children': [{'Feature': {'dict': {'ref': 'feature11'}}}, {'Feature': {'dict': {'ref': 'feature12'}}}]}}, {'Feature': {'dict': {'ref': 'feature2'}}}, {'DataContainer': {'dict': {'ref': 'data'}, 'children': [{'Data': {'dict': {'ref': 'feature1', 'value': 1}}}, {'Data': {'dict': {'ref': 'feature2', 'value': 2}}}]}}]}}]}}, {'Configuration': {'dict': {'path': 'layer2.confml', 'ref': 'layer2', 'namespace': '', 'desc': ''}}}]}}
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_container.py
--- a/configurationengine/source/cone/public/tests/unittest_container.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_container.py Tue Aug 10 14:29:28 2010 +0300
@@ -23,7 +23,6 @@
import unittest
import string
import sys,os,re
-import __init__
from cone.public import utils, container, exceptions
@@ -138,7 +137,7 @@
self.assertEquals(cont.startswith("test"),True)
-def graph(obj):
+def graph(obj, filters=None):
if obj._parent:
return ["%s -> %s" % (obj._parent._name, obj._name)]
return []
@@ -151,7 +150,7 @@
def test_add_incorrect_type(self):
cont = container.ObjectContainer()
try:
- cont._add(container.ObjectProxy())
+ cont._add(container.DataContainer())
self.fail("Adding incorrect class type to container succeeds?")
except exceptions.IncorrectClassError,e:
pass
@@ -164,14 +163,60 @@
cont._add(container.ObjectContainer("foo"))
self.assertEquals(cont._list(),['test','foo'])
self.assertEquals(cont.test,obj)
+
+ def test_add_children_from_list_with_different_policies(self):
+ def check(policy, expected):
+ cont = container.ObjectContainer("root")
+ cont._add(container.ObjectContainer("test1"))
+ cont._add(container.ObjectContainer("foo"))
+ cont._add(container.ObjectContainer("test2"))
+
+ objs = [container.ObjectContainer("foo"),
+ container.ObjectContainer("foo"),
+ container.ObjectContainer("foo")]
+ for i, obj in enumerate(objs): obj.test_attr = i
+
+ cont._add(objs, policy)
+
+ actual = [(o._name, getattr(o, 'test_attr', None)) for o in cont._objects()]
+ self.assertEquals(actual, expected)
+
+ check(container.REPLACE,
+ [('test1', None),
+ ('foo', 0),
+ ('foo', 1),
+ ('foo', 2),
+ ('test2', None),])
+
+ check(container.APPEND,
+ [('test1', None),
+ ('foo', None),
+ ('foo', 0),
+ ('foo', 1),
+ ('foo', 2),
+ ('test2', None),])
+
+ check(container.PREPEND,
+ [('test1', None),
+ ('foo', 0),
+ ('foo', 1),
+ ('foo', 2),
+ ('foo', None),
+ ('test2', None),])
+
def test_add_internal_child(self):
cont = container.ObjectContainer("root")
obj = container.ObjectContainer("?test")
cont._add(obj)
cont._add(container.ObjectContainer("foo"))
- self.assertEquals(cont._list(),['foo'])
+ cont._add(container.ObjectContainer("bar"))
+ self.assertEquals(cont._list(),['foo', 'bar'])
self.assertEquals(cont._get('?test'),obj)
+ self.assertEquals(cont._list(),['foo', 'bar'])
+ cont._remove('?test')
+ self.assertRaises(exceptions.NotFound,cont._get,'?test')
+ self.assertEquals(cont._list(),['foo','bar'])
def test_add_child_to_path(self):
@@ -241,6 +286,17 @@
except exceptions.AlreadyExists, e:
pass
+ def test__traverse_depth(self):
+ cont = container.ObjectContainer("cont")
+ obj1 = container.ObjectContainer("test1")
+ obj2 = container.ObjectContainer("test2")
+ cont._add_to_path("com.nokia", obj1)
+ cont._add_to_path("com.nokia", obj2)
+ self.assertEquals(len(cont._traverse()), 4)
+ self.assertEquals(len(cont._traverse(depth=1)), 1)
+ self.assertEquals(len(cont._traverse(depth=2)), 2)
+ self.assertEquals(len(cont._traverse(depth=3)), 4)
+
def test_add_child_to_existing_path_append(self):
cont = container.ObjectContainer("test")
obj = container.ObjectContainer("test")
@@ -512,6 +568,9 @@
ret = cont._traverse(name="^t.*$")
self.assertEquals(len(ret),1)
self.assertEquals(ret[0]._path(),"default.com.nokia.test")
+# ret = cont._traverse(type=TestC)
+# self.assertEquals(len(ret),1)
+
def test_add_children_and_traverse_filter_name_many(self):
cont = container.ObjectProxyContainer(None,"default")
@@ -569,6 +628,58 @@
self.assertEquals(proxy2.list_resources(''),['test1.txt', 'test2.txt', 'test3.txt'])
os.unlink("unload.pk")
+class TestLoadContainer(unittest.TestCase):
+ def test_create_load_container(self):
+ cont = container.LoadContainer(importpk, container.LoadInterface())
+ cont._load()
+ self.assertEquals(len(cont._objects()), 1)
+
+ def test_create_load_link__unload(self):
+ cont = container.LoadContainer(importpk, container.LoadInterface())
+ cont._load()
+ self.assertEquals(len(cont._objects()), 1)
+ cont._unload()
+ self.assertEquals(cont._container, None)
+
+ def test_create_load_link__get_objects(self):
+ cont = container.LoadContainer(importpk, container.LoadInterface())
+ self.assertEquals(len(cont._objects()), 1)
+
+ def test_create_load_link__traverse(self):
+ cont = container.LoadContainer(importpk, container.LoadInterface())
+ self.assertEquals(len(cont._traverse()), 4)
+ print cont._traverse()
+
+ def test_create_load_link__list(self):
+ cont = container.LoadContainer(importpk, container.LoadInterface())
+ self.assertEquals(os.path.basename(cont._list()[0]), 'Import_pk')
+
+class TestLoadContainerWrite(unittest.TestCase):
+ def test_create_load_container__add_data(self):
+ cont = container.LoadContainer(importpk)
+ cont._add(container.ObjectContainer("Test"))
+ self.assertEquals(len(cont._objects()), 1)
+
+ def test_create_load_container__add_data_unload(self):
+ cont = container.LoadContainer(importpk)
+ cont._add(container.ObjectContainer("Test"))
+ self.assertEquals(len(cont._objects()), 1)
+ cont._unload()
+
+class TestLoadLink(unittest.TestCase):
+ def test_create_load_link(self):
+ link = container.LoadLink(importpk, container.LoadInterface())
+ objs = link._load()
+ self.assertEquals(len(objs), 1)
+
+ def test_create_load_link_and_populate(self):
+ cont = container.ObjectContainer("Test")
+ link = container.LoadLink(importpk, container.LoadInterface())
+ cont._add(link)
+ link.populate()
+ self.assertEquals(len(cont._objects()), 2)
+
if __name__ == '__main__':
unittest.main()
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_data.py
--- a/configurationengine/source/cone/public/tests/unittest_data.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_data.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import unittest
import string
import sys,os
-import __init__
from cone.public import api,exceptions,utils, container
@@ -36,13 +35,6 @@
data = api.Data(fqr="foo.bar", value=123, attr='data')
self.assertEquals(data.attr,'data')
- def test_create_data_with_map(self):
- data = api.Data(ref="StringToString", map="StringToStringSequenceFeature/SequenceSetting[@key='Key 1']")
- self.assertEqual(data.get_map(),"StringToStringSequenceFeature/SequenceSetting[@key='Key 1']")
- self.assertEqual(data.get_map_ref(),"StringToStringSequenceFeature/SequenceSetting")
- self.assertEqual(data.get_map_key_value(),"Key 1")
- self.assertTrue(data)
-
def test_create_data_getters(self):
data = api.Data(ref="foo", value=123)
self.assertEquals(data.fqr, "foo")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_feature.py
--- a/configurationengine/source/cone/public/tests/unittest_feature.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_feature.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,11 +18,8 @@
Test the configuration
"""
import unittest
-import string
-import sys,os
-import __init__
-from cone.public import api,exceptions,utils
+from cone.public import api, exceptions
class TestFeature(unittest.TestCase):
@@ -95,7 +92,47 @@
self.assertEquals(feaproxy.bar.fqr,"foo.bar")
self.assertEquals(feaproxy.bar.name,"bar man")
+ def test_create_feature_proxy_with_options(self):
+ fea= api.Feature("foo", name="foo bar")
+ fea.add_option(api.Option('opt1', '1'))
+
+ opts = {}
+ opts['opt2'] = api.Option('opt2', '2')
+
+ feaproxy = api._FeatureProxy("foo",fea, options=opts)
+ self.assertTrue(feaproxy.get_ref(),"foo")
+ self.assertEquals(feaproxy.namespace,"")
+ self.assertEquals(feaproxy.fqr,"foo")
+ self.assertEquals(feaproxy.name,"foo bar")
+ feaproxy.add_feature(api.Feature("bar", name="bar man"))
+ self.assertTrue(feaproxy.bar.get_ref(),"bar")
+ self.assertEquals(feaproxy.bar.namespace,"foo")
+ self.assertEquals(feaproxy.bar.fqr,"foo.bar")
+ self.assertEquals(feaproxy.bar.name,"bar man")
+ opts2 = {}
+ opts2['opt2'] = api.Option('opt2', '2')
+ opts2['opt1'] = api.Option('opt1', '1')
+ self.assertEquals(feaproxy.list_options(), ['value_1', 'value_2'])
+ self.assertEquals(feaproxy.get_option('value_2').get_value(), '2')
+ self.assertEquals(feaproxy.get_option('value_1').get_value(), '1')
+
+ def test_create_feature_proxy_has_attribute(self):
+ fea= api.Feature("foo", name="foo bar")
+ feaproxy = api._FeatureProxy("foo",fea)
+ self.assertEquals(feaproxy.name, "foo bar")
+ self.assertEquals(feaproxy.has_attribute('name'), False)
+ feaproxy.name = "test"
+ self.assertEquals(feaproxy.has_attribute('name'), True)
+ self.assertEquals(feaproxy.name, "test")
+ def test_feature_proxy_get_proxied_obj(self):
+ fea= api.Feature("foo", name="foo bar")
+ feaproxy = api._FeatureProxy("foo",fea)
+ proxied = feaproxy.get_proxied_obj()
+ self.assertFalse(proxied == None)
+ self.assertEquals(fea, proxied)
+ self.assertEquals(feaproxy.get_proxied_obj(), feaproxy._obj)
+
def test_create_feature_data(self):
dataobj = api.Data(ref="foo", value=132)
self.assertTrue(dataobj.fqr,"foo")
@@ -181,15 +218,22 @@
def test_create_sequence_feature(self):
fea = api.FeatureSequence('test')
- fea.add_feature(api.Feature('child1',type='int'))
- fea.add_feature(api.Feature('child2'))
- fea.add_feature(api.Feature('child3'))
+ fea.create_feature('child1',type='int')
+ fea.create_feature('child2', name="test")
+ fea.create_feature('child3')
self.assertEquals(fea.get_type(), 'sequence')
self.assertEquals(fea.list_features(), ['child1','child2','child3'])
+ self.assertEquals(fea.get_feature('child1').type, 'int')
+ self.assertEquals(fea.get_feature('child2').type, None)
+ self.assertEquals(fea.get_feature('child2').name, 'test')
def test_feature_get_dict(self):
fea= api.Feature("foo", type='int')
- self.assertEquals(fea._dict(), {'ref': 'foo','type': 'int', 'name': 'foo'})
+ self.assertEquals(fea._dict(), {'ref': 'foo',
+ 'type': 'int',
+ 'name': None,
+ 'relevant': None,
+ 'constraint': None })
def test_clone_single_feature(self):
fea= api.Feature("foo", type='int')
@@ -199,7 +243,7 @@
def test_clone_feature_with_subfeatures(self):
fea= api.Feature("foo")
fea.add_feature(api.Feature("child1",type='string'))
- fea.add_feature(api.Feature("child2",type='int'))
+ fea.create_feature("child2",type='int')
fea.child1.add_feature(api.Feature("child12",type='int'))
fea2 = fea._clone()
self.comparefeatures(fea,fea2)
@@ -257,6 +301,9 @@
fea.add_feature(api.Feature('child2'))
fea.add_feature(api.Feature('child3'))
self.assertEquals(fea.list_features(),['child1','child2','child3'])
+ self.assertEquals(fea.get_column_features()[0].ref,'child1')
+ self.assertEquals(fea.get_column_features()[1].ref,'child2')
+ self.assertEquals(fea.get_column_features()[2].ref,'child3')
def test_create_configuration_with_sequence_and_get_default_view(self):
fea= api.FeatureSequence("foo")
@@ -330,6 +377,54 @@
['7','8','9']
])
+ def test_create_configuration_with_sequence_and_get_column_value(self):
+ fea= api.FeatureSequence("foo")
+ c1 = fea.create_feature('child1')
+ c11 = c1.create_feature('child11')
+ c2 = fea.create_feature('child2')
+ c3 = fea.create_feature('child3')
+ config = api.Configuration('foo.confml')
+ config.add_feature(fea)
+ dview = config.get_default_view()
+ foofea = dview.get_feature('foo')
+ # Test adding a data row with array
+ foofea.value = [[['1'],'2','3'],[['4'],'5','6'],[['7'],'8','9']]
+ self.assertEquals(api.get_column_value(foofea, 'child1'), [['1'],['4'],['7']])
+ self.assertEquals(foofea.child1.value, [['1'],['4'],['7']])
+ self.assertEquals(foofea.child1.child11.value, ['1','4','7'])
+ self.assertEquals(foofea.child2.value, ['2','5','8'])
+ self.assertEquals(foofea.value, [[['1'],'2','3'],
+ [['4'],'5','6'],
+ [['7'],'8','9']])
+
+ def test_create_configuration_with_sequence_and_set_value_via_column(self):
+ fea= api.FeatureSequence("foo")
+ fea.add_feature(api.Feature('child1'))
+ fea.add_feature(api.Feature('child2'))
+ fea.add_feature(api.Feature('child3'))
+ config = api.Configuration('foo.confml')
+ config.add_feature(fea)
+ dview = config.get_default_view()
+ foofea = dview.get_feature('foo')
+ # Test adding a data row with array
+ foofea.value = [['1','2','3'],['4','5','6'],['7','8','9']]
+ self.assertEquals(foofea.get_value(), [['1','2','3'],
+ ['4','5','6'],
+ ['7','8','9']
+ ])
+
+ api.set_column_value(foofea, 'child1', ['0','0','0'])
+ self.assertEquals(foofea.get_value(), [['0','2','3'],
+ ['0','5','6'],
+ ['0','8','9']
+ ])
+ self.assertRaises(exceptions.ConeException, api.set_column_value, foofea, 'child2', 'over')
+ self.assertRaises(exceptions.ConeException, api.set_column_value, foofea, 'child2', ['0','0','0', 'over'])
+ foofea.child3.value = ['0','0','0']
+ self.assertEquals(foofea.get_value(), [['0','2','0'],
+ ['0','5','0'],
+ ['0','8','0']
+ ])
def test_create_configuration_with_sequence_and_add_sequence_value_directly(self):
fea= api.FeatureSequence("foo")
@@ -350,6 +445,87 @@
['4','5','6'],
['7','8','9']
])
+
+ # Check the data element values
+ data_elem_values = [(d.fqr, d.value) for d in config._traverse(type=api.Data)]
+ self.assertEquals(data_elem_values,
+ [('foo', None),
+ ('foo.child1', '1'),
+ ('foo.child2', '2'),
+ ('foo.child3', '3'),
+ ('foo', None),
+ ('foo.child1', '4'),
+ ('foo.child2', '5'),
+ ('foo.child3', '6'),
+ ('foo', None),
+ ('foo.child1', '7'),
+ ('foo.child2', '8'),
+ ('foo.child3', '9'),])
+
+ def test_set_sequence_to_empty(self):
+ fea= api.FeatureSequence("foo")
+ fea.add_feature(api.Feature('child1'))
+ fea.add_feature(api.Feature('child2'))
+ fea.add_feature(api.Feature('child3'))
+ config = api.Configuration('foo.confml')
+ config.add_feature(fea)
+ dview = config.get_default_view()
+ foofea = dview.get_feature('foo')
+ # Test adding a data row with array
+ foofea.set_value([['1','2','3'],
+ ['4','5','6'],
+ ['7','8','9']])
+ self.assertEquals(len(foofea.get_data()), 3)
+ self.assertEquals(foofea.get_value(), [['1','2','3'],
+ ['4','5','6'],
+ ['7','8','9']])
+ self.assertEquals(foofea.child1.get_value(), ['1','4','7'])
+ self.assertEquals(foofea.child2.get_value(), ['2','5','8'])
+ self.assertEquals(foofea.child3.get_value(), ['3','6','9'])
+
+ # Set empty and check that the single empty data item is created
+ foofea.set_value([])
+ data_elem_values = [(d.fqr, d.value) for d in config._traverse(type=api.Data)]
+ self.assertEquals(data_elem_values, [('foo', None)])
+
+ # Check that get_value() still works correctly
+ self.assertEquals(foofea.get_value(), [])
+ self.assertEquals(foofea.child1.get_value(), [])
+ self.assertEquals(foofea.child2.get_value(), [])
+ self.assertEquals(foofea.child3.get_value(), [])
+ self.assertEquals(foofea.get_original_value(), [])
+ self.assertEquals(foofea.child1.get_original_value(), [])
+ self.assertEquals(foofea.child2.get_original_value(), [])
+ self.assertEquals(foofea.child3.get_original_value(), [])
+
+ # Check that column-level set_value() reports errors correctly
+ self.assertRaises(exceptions.ConeException, foofea.child1.set_value, ['10', '11'])
+ self.assertRaises(exceptions.ConeException, foofea.child1.set_value, ['10'])
+ foofea.child1.set_value([])
+
+ # Check that calling add_sequence() after set_value([]) works correctly
+ foofea.add_sequence(['1', '2', '3'])
+ self.assertEquals(foofea.get_value(), [['1', '2', '3']])
+ self.assertEquals(foofea.child1.get_value(), ['1'])
+ self.assertEquals(foofea.get_original_value(), [['1', '2', '3']])
+ data_elem_values = [(d.fqr, d.value) for d in config._traverse(type=api.Data)]
+ self.assertEquals(data_elem_values,
+ [('foo', None),
+ ('foo.child1', '1'),
+ ('foo.child2', '2'),
+ ('foo.child3', '3'),])
+
+ # Check that explicitly setting all Nones works
+ foofea.set_value([[None, None, None]])
+ self.assertEquals(foofea.get_value(), [[None, None, None]])
+ self.assertEquals(foofea.child1.get_value(), [None])
+ self.assertEquals(foofea.get_original_value(), [[None, None, None]])
+ data_elem_values = [(d.fqr, d.value) for d in config._traverse(type=api.Data)]
+ self.assertEquals(data_elem_values,
+ [('foo', None),
+ ('foo.child1', None),
+ ('foo.child2', None),
+ ('foo.child3', None),])
def test_create_configuration_and_access_feature_value_with_property(self):
config = api.Configuration('foo.confml')
@@ -424,7 +600,6 @@
self.assertEquals(foofea.value, [])
def test_create_feature_seq_get_sequence_parent(self):
- config = api.Configuration('foo.confml')
fea= api.FeatureSequence("foo")
fea.add_feature(api.Feature('child1'))
fea.add_feature(api.Feature('child11'),'child1')
@@ -452,8 +627,8 @@
dview = config.get_default_view()
seqfea = dview.get_feature("SequenceSetting")
- self.assertEquals(seqfea.get_map_key().name,"KeySubSetting")
- self.assertEquals(seqfea.get_map_value().name,"ValueSubSetting")
+ self.assertEquals(seqfea.mapKey, "KeySubSetting")
+ self.assertEquals(seqfea.mapValue, "ValueSubSetting")
#add item 1
data = api.Data(ref='SequenceSetting')
data._add(api.Data(ref='KeySubSetting',value='Default'))
@@ -468,8 +643,154 @@
self.assertEquals(len(seqfea.get_data()), 2)
- self.assertEquals(seqfea.get_map_key_value('Default'),'Default value')
- self.assertEquals(seqfea.get_map_key_value('Key 1'),'Value 1')
+ def test_get_set_template_single_data_level(self):
+ # Create a sequence feature with only a single level of sub-features
+ # (i.e. no sub-sub-features)
+ config = api.Configuration('foo.confml')
+ seq = api.FeatureSequence("seq")
+ seq.add_feature(api.Feature('child1'))
+ seq.add_feature(api.Feature('child2'))
+ seq.add_feature(api.Feature('child3'))
+ config.add_feature(seq)
+
+ # Add a template for the sequence with the data elements under it
+ # in a different order than what the features were defined in
+ template_data = api.Data(ref='seq', template=True)
+ template_data.add(api.Data(ref='child2', value='foo2'))
+ template_data.add(api.Data(ref='child3', value='foo3'))
+ template_data.add(api.Data(ref='child1', value='foo1'))
+ config.add_data(template_data)
+
+ # Get the template data (should be in order)
+ dview = config.get_default_view()
+ seq = dview.get_feature('seq')
+ self.assertEquals(seq.get_template(), ['foo1', 'foo2', 'foo3'])
+
+ seq.set_template(['x1', 'x2', 'x3'])
+ self.assertEquals(seq.get_template(), ['x1', 'x2', 'x3'])
+
+ seq.set_template(None)
+ self.assertEquals(seq.get_template(), None)
+
+ # Test attempting to set invalid template data
+ self.assertRaises(TypeError, seq.set_template, 'foo')
+ self.assertRaises(ValueError, seq.set_template, [])
+ self.assertRaises(ValueError, seq.set_template, ['foo', 'bar'])
+ self.assertRaises(ValueError, seq.set_template, [['foo', 'x'], 'bar'])
+
+ def test_get_set_template_two_data_levels(self):
+ # Create a sequence feature with two levels of sub-features
+ config = api.Configuration('foo.confml')
+ seq = api.FeatureSequence("seq")
+ seq.add_feature(api.Feature('a1'))
+ seq.add_feature(api.Feature('b1'), 'a1')
+ seq.add_feature(api.Feature('b2'), 'a1')
+ seq.add_feature(api.Feature('a2'))
+ seq.add_feature(api.Feature('a3'))
+ config.add_feature(seq)
+
+ # Add a template for the sequence with the data elements under it
+ # in a different order than what the features were defined in
+ template_data = api.Data(ref='seq', template=True)
+ template_data.add(api.Data(ref='a3', value='t: a3'))
+ data_a1 = api.Data(ref='a1')
+ data_a1.add(api.Data(ref='b2', value='t: a1.b2'))
+ data_a1.add(api.Data(ref='b1', value='t: a1.b1'))
+ template_data.add(data_a1)
+ template_data.add(api.Data(ref='a2', value='t: a2'))
+ config.add_data(template_data)
+
+ template_data = api.Data(ref='seq')
+ template_data.add(api.Data(ref='a3', value='t: a3'))
+ data_a1 = api.Data(ref='a1')
+ data_a1.add(api.Data(ref='b2', value='t: a1.b2'))
+ data_a1.add(api.Data(ref='b1', value='t: a1.b1'))
+ template_data.add(data_a1)
+ template_data.add(api.Data(ref='a2', value='t: a2'))
+ config.add_data(template_data, api.FeatureSequence.POLICY_APPEND)
+
+ # Get the template data (should be in order)
+ dview = config.get_default_view()
+ seq = dview.get_feature('seq')
+ self.assertEquals(seq.value, [[['t: a1.b1', 't: a1.b2'], 't: a2', 't: a3']])
+ self.assertEquals(seq.get_template(), [['t: a1.b1', 't: a1.b2'], 't: a2', 't: a3'])
+
+ # Set the template and get it again
+ seq.set_template([['t: a1.b1 (x)', 't: a1.b2 (x)'], 't: a2 (x)', 't: a3 (x)'])
+ self.assertEquals(seq.get_template(), [['t: a1.b1 (x)', 't: a1.b2 (x)'], 't: a2 (x)', 't: a3 (x)'])
+
+ def test_sequence_add_data_and_set_template(self):
+ # Create a simple configuration with a sequence feature
+ config = api.Configuration('foo.confml')
+ fea = api.Feature('fea')
+ config.add_feature(fea)
+ seq = api.FeatureSequence("seq")
+ fea.add_feature(seq)
+ seq.add_feature(api.Feature('child1'))
+ seq.add_feature(api.Feature('child2'))
+
+ sequence = config.get_default_view().get_feature('fea.seq')
+
+ # Check that initially the sequence is empty
+ self.assertEquals(sequence.get_template(), None)
+ self.assertEquals(sequence.value, [])
+
+ # Add some data and check again
+ sequence.add_sequence(['row1', 'foo'])
+ sequence.add_sequence(['row2', 'foo'])
+ self.assertEquals(sequence.get_template(), None)
+ self.assertEquals(sequence.value, [['row1', 'foo'],
+ ['row2', 'foo']])
+
+ # Setting the template should not affect the data
+ sequence.set_template(['t1', 't2'])
+ self.assertEquals(sequence.get_template(), ['t1', 't2'])
+ self.assertEquals(sequence.value, [['row1', 'foo'],
+ ['row2', 'foo']])
+
+ sequence.set_template(['T1', 'T2'])
+ sequence.add_sequence(['row3', 'foo'])
+ self.assertEquals(sequence.get_template(), ['T1', 'T2'])
+ self.assertEquals(sequence.value, [['row1', 'foo'],
+ ['row2', 'foo'],
+ ['row3', 'foo']])
+
+ def test_set_value_method_for_sequence(self):
+ config = api.Configuration('foo.confml')
+ fea = api.Feature('Some')
+ config.add_feature(fea)
+ seq = api.FeatureSequence("Sequence")
+ fea.add_feature(seq)
+ seq.add_feature(api.Feature('Feature'))
+
+ seq = config.get_default_view().get_feature('Some.Sequence')
+ value = [['foo'], ['bar']]
+ seq.set_value(value)
+
+ self.assertEquals(seq.value, [['foo'], ['bar']])
+ self.assertEquals(seq.Feature.value, ['foo', 'bar'])
+
+ def test_simple_name_id_mapping(self):
+ config = api.Configuration('foo.confml')
+ seq = api.FeatureSequence('seq', mapKey='sub1', mapValue='sub1')
+ seq.add_feature(api.Feature('sub1'))
+ seq.add_feature(api.Feature('sub2'))
+ config.add_feature(seq)
+ config.add_feature(api.Feature('target'))
+
+ config.add_data(api.Data(fqr='seq.sub1', value='foo'))
+ config.add_data(api.Data(fqr='seq.sub2', value='bar'))
+ config.add_data(api.Data(fqr='target', map="seq[@key='foo']"))
+
+ fea = config.get_default_view().get_feature('target')
+ self.assertEquals(fea.value, 'foo')
+ self.assertEquals(fea.get_value(), 'foo')
+ self.assertEquals(fea.get_original_value(), 'foo')
+
+ seq.mapValue = 'sub2'
+ self.assertEquals(fea.value, 'bar')
+ self.assertEquals(fea.get_value(), 'bar')
+ self.assertEquals(fea.get_original_value(), 'bar')
+
if __name__ == '__main__':
- unittest.main()
-
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_layer.py
--- a/configurationengine/source/cone/public/tests/unittest_layer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_layer.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,58 +18,105 @@
Test the configuration
"""
import unittest
-import string
-import sys,os
-import __init__
+
+
+from cone.public import api
+from cone.storage import stringstorage
+
+class TestFolder(unittest.TestCase):
+ storage_class = stringstorage.StringStorage
+ def setUp(self):
+ self.store = self.storage_class.open("temp/layertest.pk","w")
+
+ def test_create_folder(self):
+ folder = api.Folder(self.store, "subfolder")
+ self.assertTrue(folder)
+
+ def test_get_path(self):
+ folder = api.Folder(self.store, "foo")
+ self.assertEquals(folder.get_current_path(),"foo")
+
+ def test_open_resource(self):
+ folder = api.Folder(self.store, "foo")
+ res = folder.open_resource("confml/test.confml","w")
+ res.write("foo.conf")
+ res.close()
+ self.assertEquals(folder.list_resources("", recurse=True),["confml/test.confml"])
+ self.assertEquals(self.store.list_resources("", recurse=True),["foo/confml/test.confml"])
-from cone.public import api,exceptions,utils
-from cone.storage import stringstorage
+ def test_open_non_existing_resource(self):
+ folder = api.Folder(self.store, "foo")
+ try:
+ folder.open_resource("confml/test.confml","r")
+ except Exception:
+ pass
+ self.assertEquals(folder.storage.curpath, '')
+
+ def test_create_two_layers_and_open_resource(self):
+ foo_folder = api.Folder(self.store, "foo")
+ bar_folder = api.Folder(self.store, "bar")
+ res = foo_folder.open_resource("confml/test.confml","w")
+ res.write("foo.conf")
+ res.close()
+ res = foo_folder.open_resource("root.confml","w")
+ res.close()
+ res = bar_folder.open_resource("confml/root.confml","w")
+ res.write("foo.conf")
+ res.close()
+ self.assertEquals(foo_folder.list_resources("", recurse=True),[ 'root.confml',
+ 'confml/test.confml'])
+ self.assertEquals(self.store.list_resources("", recurse=True),['bar/confml/root.confml',
+ 'foo/root.confml',
+ 'foo/confml/test.confml'])
+ foo_folder.delete_resource("confml/test.confml")
+ self.assertEquals(foo_folder.list_resources("", recurse=True),["root.confml"])
+ self.assertEquals(self.store.list_resources("", recurse=True),["bar/confml/root.confml",
+ "foo/root.confml"])
+
class TestLayer(unittest.TestCase):
storage_class = stringstorage.StringStorage
+ def setUp(self):
+ self.store = self.storage_class.open("temp/layertest.pk","w")
def test_create_layer(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
self.assertTrue(layer)
# def test_create_layer_with_kwargs(self):
-# store = self.storage_class.open("temp/layertest.pk","w")
-# layer = api.Layer(store, "foo",confml_path="foobar", implml_path="")
+# self.store = self.storage_class.open("temp/layertest.pk","w")
+# layer = api.Layer(self.store, "foo",confml_path="foobar", implml_path="")
# self.assertTrue(layer)
# self.assertEquals(layer.confml_folder.get_current_path(),"foo/foobar")
# self.assertEquals(layer.implml_folder.get_current_path(),"foo")
-# layer = api.Layer(store, "foo",confml_path="f", implml_path="test", content_path="data", doc_path="foo")
+# layer = api.Layer(self.store, "foo",confml_path="f", implml_path="test", content_path="data", doc_path="foo")
# self.assertEquals(layer.confml_folder.get_current_path(),"foo/f")
# self.assertEquals(layer.implml_folder.get_current_path(),"foo/test")
# self.assertEquals(layer.content_folder.get_current_path(),"foo/data")
# self.assertEquals(layer.doc_folder.get_current_path(),"foo/foo")
-# layer = api.Layer(store, "foo")
+# layer = api.Layer(self.store, "foo")
# self.assertEquals(layer.confml_folder.get_current_path(),"foo/confml")
# self.assertEquals(layer.implml_folder.get_current_path(),"foo/implml")
# self.assertEquals(layer.content_folder.get_current_path(),"foo/content")
# self.assertEquals(layer.doc_folder.get_current_path(),"foo/doc")
def test_get_path(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
self.assertTrue(layer)
self.assertEquals(layer.get_current_path(),"foo")
def test_open_resource(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
self.assertTrue(layer)
res = layer.open_resource("confml/test.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(layer.list_resources("", True),["confml/test.confml"])
- self.assertEquals(store.list_resources("", True),["foo/confml/test.confml"])
+ self.assertEquals(layer.list_resources("", recurse=True),["confml/test.confml"])
+ self.assertEquals(self.store.list_resources("", recurse=True),["foo/confml/test.confml"])
def test_create_two_layers_and_open_resource(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- foo_layer = api.Layer(store, "foo")
- bar_layer = api.Layer(store, "bar")
+ foo_layer = api.Layer(self.store, "foo")
+ bar_layer = api.Layer(self.store, "bar")
res = foo_layer.open_resource("confml/test.confml","w")
res.write("foo.conf")
res.close()
@@ -78,15 +125,14 @@
res = bar_layer.open_resource("confml/root.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(foo_layer.list_resources("", True),['confml/test.confml', 'root.confml'])
- self.assertEquals(store.list_resources("", True),['bar/confml/root.confml','foo/confml/test.confml','foo/root.confml'])
+ self.assertEquals(foo_layer.list_resources("", recurse=True),['root.confml', 'confml/test.confml'])
+ self.assertEquals(self.store.list_resources("", recurse=True),['bar/confml/root.confml', 'foo/root.confml', 'foo/confml/test.confml'])
foo_layer.delete_resource("confml/test.confml")
- self.assertEquals(foo_layer.list_resources("", True),["root.confml"])
- self.assertEquals(store.list_resources("", True),["bar/confml/root.confml","foo/root.confml"])
+ self.assertEquals(foo_layer.list_resources("", recurse=True),["root.confml"])
+ self.assertEquals(self.store.list_resources("", recurse=True),["bar/confml/root.confml","foo/root.confml"])
def test_list_confml(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
res = layer.open_resource("confml/test.confml","w")
res.write("foo.conf")
res.close()
@@ -99,8 +145,7 @@
self.assertEquals(layer.list_confml(),['confml/foo.confml', 'confml/test.confml'])
def test_list_implml(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
res = layer.open_resource("implml/stuff/test.confml","w")
res.write("foo.conf")
res.close()
@@ -113,8 +158,7 @@
self.assertEquals(layer.list_implml(),['implml/stuff/test.confml'])
def test_list_content(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
res = layer.open_resource("content/bar/test.txt","w")
res.write("foo.conf")
res.close()
@@ -124,11 +168,10 @@
res = layer.open_resource("root.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(layer.list_content(),['content/bar/test.txt', 'content/foo.confml'])
+ self.assertEquals(layer.list_content(),[ 'content/foo.confml', 'content/bar/test.txt'])
def test_list_doc(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
res = layer.open_resource("doc/bar/test.txt","w")
res.write("foo.conf")
res.close()
@@ -138,11 +181,10 @@
res = layer.open_resource("root.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(layer.list_doc(),['doc/bar/test.txt', 'doc/foo.confml'])
+ self.assertEquals(layer.list_doc(),['doc/foo.confml', 'doc/bar/test.txt' ])
def test_list_layer_resources(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo")
+ layer = api.Layer(self.store, "foo")
res = layer.open_resource("doc/bar/test.txt","w")
res.write("foo.conf")
res.close()
@@ -164,8 +206,7 @@
'doc/bar/test.txt'])
def test_list_layer_with_sublayer(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- layer = api.Layer(store, "foo", layers=[api.Layer(store, "bar")])
+ layer = api.Layer(self.store, "foo", layers=[api.Layer(self.store, "bar")])
res = layer.open_resource("doc/bar/test.txt","w")
res.write("foo.conf")
res.close()
@@ -203,36 +244,79 @@
self.assertEquals(layer.list_content(),['content/data/abc.txt', 'bar/content/barcode.txt'])
self.assertEquals(layer.list_doc(),['doc/bar/test.txt'])
+ def test_list_all_related(self):
+ layer = api.Layer(self.store, "foo")
+ res = layer.open_resource("doc/bar/test.txt","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("confml/foo.confml","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("confml/bar.confml","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("content/data/abc.txt","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("foo.txt","w")
+ res.write("foo.conf")
+ res.close()
+
+ self.assertEquals(layer.list_all_related(),['content/data/abc.txt', 'doc/bar/test.txt'])
+
+ def test_list_all_related_with_filter(self):
+ store = self.storage_class.open("temp/layertest.pk","w")
+ layer = api.Layer(self.store, "foo")
+ res = layer.open_resource("doc/bar/test.txt","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("confml/foo.confml","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("confml/bar.confml","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("content/data/abc.txt","w")
+ res.write("foo.conf")
+ res.close()
+ res = layer.open_resource("foo.txt","w")
+ res.write("foo.conf")
+ res.close()
+
+ self.assertEquals(layer.list_all_related(exclude_filters={'content':'.*\.txt'}), ['doc/bar/test.txt'])
+ self.assertEquals(layer.list_all_related(exclude_filters={'doc':'.*\.txt'}), ['content/data/abc.txt'])
+
+
+
+
class TestCompositeLayer(unittest.TestCase):
storage_class = stringstorage.StringStorage
+ def setUp(self):
+ self.store = self.storage_class.open("temp/layertest.pk","w")
def test_create_compositelayer(self):
- store = self.storage_class.open("temp/layertestcomposite.pk","w")
- clayer = api.CompositeLayer()
+ clayer = api.CompositeLayer(self.store)
self.assertTrue(clayer)
def test_create_with_layer(self):
- store = self.storage_class.open("temp/layertestcomposite.pk","w")
- clayer = api.CompositeLayer("sub",layers=[api.Layer(store,"test"), api.Layer(store,"foo/bar")])
+ clayer = api.CompositeLayer("sub",layers=[api.Layer(self.store,"test"), api.Layer(self.store,"foo/bar")])
self.assertEquals(clayer.list_layers(),['test', 'foo/bar'])
def test_create_with_layer_and_add(self):
- store = self.storage_class.open("temp/layertestcomposite.pk","w")
- clayer = api.CompositeLayer(layers=[api.Layer(store,"test"), api.Layer(store,"foo/bar")])
+ self.store = self.storage_class.open("temp/layertestcomposite.pk","w")
+ clayer = api.CompositeLayer(self.store, layers=[api.Layer(self.store,"test"), api.Layer(self.store,"foo/bar")])
self.assertEquals(clayer.list_layers(),['test', 'foo/bar'])
- clayer.add_layer(api.Layer(store,"res"))
+ clayer.add_layer(api.Layer(self.store,"res"))
self.assertEquals(clayer.list_layers(),['test', 'foo/bar', 'res'])
def test_get_layer(self):
- store = self.storage_class.open("temp/layertestcomposite.pk","w")
- clayer = api.CompositeLayer(layers=[api.Layer(store,"test"), api.Layer(store,"foo/bar")])
+ clayer = api.CompositeLayer(self.store, layers=[api.Layer(self.store,"test"), api.Layer(self.store,"foo/bar")])
self.assertEquals(clayer.list_layers(),['test', 'foo/bar'])
layer = clayer.get_layer('foo/bar')
self.assertEquals(layer.get_current_path(),'foo/bar')
def test_create_layers_with_resources_and_list_with_composite(self):
- store = self.storage_class.open("temp/layertest.pk","w")
- foolayer = api.Layer(store, "foo")
+ foolayer = api.Layer(self.store, "foo")
res = foolayer.open_resource("doc/bar/test.txt","w")
res.write("foo.conf")
res.close()
@@ -248,7 +332,7 @@
res = foolayer.open_resource("foo.txt","w")
res.write("foo.conf")
res.close()
- barlayer = api.Layer(store, "bar")
+ barlayer = api.Layer(self.store, "bar")
res = barlayer.open_resource("doc/bar/test.txt","w")
res.write("foo.conf")
res.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_mapping.py
--- a/configurationengine/source/cone/public/tests/unittest_mapping.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_mapping.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import sys
import os
import shutil
-import __init__
from cone.public import api, exceptions, mapping
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_options.py
--- a/configurationengine/source/cone/public/tests/unittest_options.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_options.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,12 +18,8 @@
Test sets
"""
import unittest
-import sets
-import sys
-import os
-import __init__
-from cone.public import api,exceptions,utils
+from cone.public import api,exceptions
class TestOption(unittest.TestCase):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_persistence.py
--- a/configurationengine/source/cone/public/tests/unittest_persistence.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_persistence.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import unittest
import string
import sys,os
-import __init__
from cone.public import persistence, exceptions
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_plugin_api.py
--- a/configurationengine/source/cone/public/tests/unittest_plugin_api.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_plugin_api.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,8 +16,7 @@
import unittest
import os
-import logging
-import __init__
+
from cone.public import *
from cone.public import _plugin_reader
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -128,7 +127,7 @@
""".encode('utf-8')
SINGLE_IMPL_2 = """
-
+
""".encode('utf-8')
SINGLE_IMPL_3 = """
@@ -137,25 +136,6 @@
""".encode('utf-8')
-IGNORED_NAMESPACE_IMPL_1 = """
-
-
-
-
-
-
-
-
-
-""".encode('utf-8')
-
-IGNORED_NAMESPACE_IMPL_2 = """
-
-
-
-
-""".encode('utf-8')
-
NO_IMPL = """
@@ -195,12 +175,37 @@
def get_default_view(self):
return MockView(self.features)
+
+ def layered_implml(self):
+ result = container.DataContainer()
+ for res in self.resources.iterkeys():
+ result.add_value(res, res)
+ return result
+
+class SimpleImpl(plugin.ImplBase):
+ def __init__(self, ref, configuration):
+ super(SimpleImpl, self).__init__(ref, configuration)
+ self.generate_invoked = False
+ self.outputfile = ''
+
+ def generate(self, context=None):
+ if context:
+ if self.outputfile:
+ f = context.create_file(self.outputfile, implementation=self)
+ f.close()
+
+ self.generate_invoked = True
class MockImpl(plugin.ImplBase):
+ IMPL_TYPE_ID = 'mock'
+
def __init__(self, data):
self.data = data
self.generate_invoked = False
-
+ self.outputfile = ''
+ self.refs = None
+ self.ref = ''
+
@classmethod
def create(cls, resource_ref, configuration, data):
impl = cls(data)
@@ -230,6 +235,14 @@
else:
return False
+ def get_refs(self):
+ """
+ Return a list of all ConfML setting references that affect this
+ implementation. May also return None if references are not relevant
+ for the implementation.
+ """
+ return self.refs
+
class MockReaderBase(plugin.ReaderBase):
@classmethod
def read_impl(cls, resource_ref, configuration, root_elem):
@@ -240,12 +253,18 @@
class MockReader1(MockReaderBase):
NAMESPACE = "http://www.test.com/xml/1"
+ NAMESPACE_ID = "mock1"
+ ROOT_ELEMENT_NAME = "impl"
FILE_EXTENSIONS = ['mock1ml']
class MockReader2(MockReaderBase):
NAMESPACE = "http://www.test.com/xml/2"
+ NAMESPACE_ID = "mock2"
+ ROOT_ELEMENT_NAME = "impl"
FILE_EXTENSIONS = ['mock2ml']
class MockReader3(MockReaderBase):
NAMESPACE = "http://www.test.com/xml/3"
+ NAMESPACE_ID = "mock3"
+ ROOT_ELEMENT_NAME = "impl"
IGNORED_NAMESPACES = ["http://www.test.com/xml/ignored/3"]
FILE_EXTENSIONS = ['mock3ml', 'test3ml']
@@ -266,12 +285,209 @@
'layer1/implml/single2.mock2ml' : SINGLE_IMPL_2,
'layer1/implml/single3.mock3ml' : SINGLE_IMPL_3,
'layer1/implml/single3.test3ml' : SINGLE_IMPL_3,
- 'layer1/implml/ignored_ns_1.mock3ml' : IGNORED_NAMESPACE_IMPL_1,
- 'layer1/implml/ignored_ns_2.mock3ml' : IGNORED_NAMESPACE_IMPL_2,
'layer1/implml/multi1.dummyml' : MULTI_IMPL_1,
'layer1/implml/dummy' : MULTI_IMPL_1,
})
+
+class TestPluginGenerationContext(unittest.TestCase):
+ def test_generation_context_handle_terminal(self):
+ config = api.Configuration()
+ context = plugin.GenerationContext(configuration=config)
+ self.assertRaises(exceptions.NotFound, context.handle_terminal, 'feature')
+ config.create_feature('feature')
+ # rebuild default view
+ config._remove('?default_view')
+ self.assertEquals(context.handle_terminal('feature'), None)
+
+
+ def test_generation_create_file(self):
+ config = api.Configuration()
+ context = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ mi = MockImpl({})
+ outfile = context.create_file('foobar/test.txt', implementation=mi)
+ outfile.write("Test output file creation")
+ outfile.close()
+ expected = utils.resourceref.norm(os.path.join(context.output, 'foobar/test.txt'))
+ self.assertEquals(len(context.generation_output), 1)
+ self.assertEquals(context.generation_output[0].name, expected)
+ self.assertEquals(context.generation_output[0].implementation, mi)
+ self.assertEquals(context.generation_output[0].phase, "normal")
+ self.assertTrue(os.path.exists(expected))
+ os.unlink(expected)
+
+ absfile = utils.resourceref.norm(os.path.join(ROOT_PATH, 'temp/foobar/abspath.txt'))
+ outfile = context.create_file(absfile, implementation=mi)
+ outfile.write("Test output file creation")
+ outfile.close()
+ self.assertEquals(len(context.generation_output), 2)
+ self.assertEquals(context.generation_output[1].name, absfile)
+ self.assertEquals(context.generation_output[1].implementation, mi)
+ self.assertEquals(context.generation_output[1].phase, "normal")
+ self.assertTrue(os.path.exists(absfile))
+ os.unlink(absfile)
+
+ def test_generation_add_output(self):
+ config = api.Configuration()
+ context = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ mi = MockImpl({})
+ context.add_file('add.txt', implementation=mi)
+
+ self.assertEquals(len(context.generation_output), 1)
+ self.assertEquals(context.generation_output[0].name, utils.resourceref.norm(os.path.join(context.output, 'add.txt')))
+ self.assertEquals(context.generation_output[0].implementation, mi)
+ self.assertEquals(context.generation_output[0].phase, "normal")
+
+ external_output = utils.resourceref.norm(os.path.join(ROOT_PATH, 'temp', 'external/foobar.txt'))
+ context.add_file(external_output, implementation=mi)
+ self.assertEquals(len(context.generation_output), 2)
+ self.assertEquals(context.generation_output[1].name, external_output)
+ self.assertEquals(context.generation_output[1].implementation, mi)
+ self.assertEquals(context.generation_output[1].phase, "normal")
+
+ def test_generation_get_output(self):
+ config = api.Configuration()
+ context = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ mi = MockImpl({})
+ context.add_file('add1.txt', implementation=mi)
+ context.add_file('foo/add2.txt', implementation=None)
+
+ self.assertEquals(len(context.get_output()), 2)
+ self.assertEquals(context.get_output()[1].filename, 'add2.txt')
+ self.assertEquals(context.get_output()[1].abspath, os.path.normpath(os.path.join(context.output,'foo/add2.txt')))
+ self.assertEquals(context.get_output()[1].relpath, os.path.normpath('foo/add2.txt'))
+ self.assertEquals(len(context.get_output(implml_type='mock')), 1)
+ self.assertEquals(context.get_output(implml_type='mock')[0].filename, 'add1.txt')
+
+ def test_generation_get_refs_no_output(self):
+ config = api.Configuration()
+ context = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ self.assertEquals(context.get_refs_with_no_output(),[])
+ self.assertEquals(context.get_refs_with_no_output(['']),[''])
+
+ context.changed_refs = ['foo.bar',
+ 'foo.two',
+ 'foo.three']
+
+ self.assertEquals(context.get_refs_with_no_output(),['foo.bar',
+ 'foo.three',
+ 'foo.two'])
+ mi = MockImpl({})
+ mi.refs = ['foo.bar','nonno.noo','foo.three']
+ context.add_file('add1.txt', implementation=mi)
+ context.add_file('foo/add2.txt', implementation=None)
+
+ self.assertEquals(context.get_refs_with_no_output(),['foo.two'])
+ context.changed_refs = ['foo.bar',
+ 'foo.three']
+ self.assertEquals(context.get_refs_with_no_output(),[])
+ mi.refs = []
+ self.assertEquals(context.get_refs_with_no_output(),['foo.bar',
+ 'foo.three'])
+ mi.refs = None
+ self.assertEquals(context.get_refs_with_no_output(),['foo.bar',
+ 'foo.three'])
+
+ def test_merged_context_get_changed_refs_intersect(self):
+ config = api.Configuration()
+ context1 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ context2 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+
+ context1.changed_refs = ['foo.bar',
+ 'foo.two',
+ 'foo.three']
+ context2.changed_refs = ['foo.bar',
+ 'foo.two1']
+ outs = plugin.MergedContext([context1,context2])
+ self.assertEquals(sorted(outs.get_changed_refs(operation='union')),
+ sorted(['foo.two1',
+ 'foo.bar',
+ 'foo.two',
+ 'foo.three']))
+ self.assertEquals(outs.get_changed_refs(operation='intersection'), ['foo.bar'])
+ self.assertEquals(sorted(outs.get_changed_refs(operation='difference')), sorted(['foo.three',
+ 'foo.two']))
+ self.assertEquals(sorted(outs.get_changed_refs(operation='symmetric_difference')), sorted(['foo.two1',
+ 'foo.three',
+ 'foo.two']))
+
+ def test_generation_get_refs_no_output_with_two_contexts(self):
+ config = api.Configuration()
+ context1 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ context2 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+
+ context1.changed_refs = ['foo.bar',
+ 'foo.two',
+ 'foo.three']
+ context2.changed_refs = ['foo.bar1',
+ 'foo.two1']
+
+
+ mi1 = MockImpl({})
+ mi1.refs = ['foo.bar','nonno.noo','foo.three']
+ mi2 = MockImpl({})
+ mi2.refs = ['foo.bar1']
+ context1.add_file('add1.txt', implementation=mi1)
+ context1.add_file('foo/add2.txt', implementation=None)
+ context2.add_file('add2.txt', implementation=mi2)
+ outs = plugin.MergedContext([context1,context2])
+ self.assertEquals(outs.get_refs_with_no_output(), ['foo.two', 'foo.two1'])
+ self.assertEquals(outs.get_refs_with_no_output(['foo.two']), ['foo.two'])
+ self.assertEquals(outs.get_refs_with_no_output(['foo.bar']), [])
+
+ def test_generation_get_refs_with_no_implementation(self):
+ config = api.Configuration()
+ context1 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+ context2 = plugin.GenerationContext(configuration=config,
+ output=os.path.join(ROOT_PATH, 'temp'),
+ phase="normal")
+
+ context1.changed_refs = ['foo.bar',
+ 'foo.two',
+ 'foo.three']
+ context2.changed_refs = ['foo.bar1',
+ 'foo.two1']
+
+
+ mi1 = MockImpl({})
+ mi1.ref = 'mi1'
+ mi1.refs = ['foo.bar','nonno.noo','foo.three']
+ mi2 = MockImpl({})
+ mi2.ref = 'mi2'
+ mi2.refs = ['foo.bar1']
+ context1.impl_set.add(mi1)
+ context2.impl_set.add(mi2)
+ outs = plugin.MergedContext([context1,context2])
+ self.assertEquals(outs.get_refs_with_no_implementation(), ['foo.two', 'foo.two1'])
+ self.assertEquals(outs.get_refs_with_no_implementation(['foo.bar']), [])
+ self.assertEquals(outs.get_refs_with_no_implementation(['foo.two', 'foo.bar1']), ['foo.two'])
+
+
+ def test_context_data_grep_log(self):
+ context = plugin.GenerationContext()
+ context.log = ['foo bar',
+ 'foo faa',
+ 'jee jee jehu']
+ self.assertEquals(context.grep_log('jee'), [(2,'jee jee jehu')])
+
class TestPluginImplBase(unittest.TestCase):
def setUp(self):
pass
@@ -293,7 +509,24 @@
self.assertEquals(impl.has_tag({'foo': ['foo']}, policy='AND'), False)
self.assertEquals(impl.has_tag({'target': ['foo'], 'foo':['bar']}, policy='AND'), False)
self.assertEquals(impl.has_tag({'target': ['foo'], 'foo':['bar']}, policy='OR'), True)
-
+
+ def test_implbase_output(self):
+ str = api.Storage(utils.relpath(ROOT_PATH))
+ config = api.Configuration('foo')
+ config.storage = str
+ impl = plugin.ImplBase('foo.implml', config)
+ self.assertEquals(impl.output, '')
+ impl.plugin_output = 'test'
+ self.assertEquals(impl.output, 'test')
+ impl.set_output_root('foobar')
+ self.assertEquals(impl.output, 'foobar/test')
+ impl.set_output_root('/foobar')
+ self.assertEquals(impl.output, '/foobar/test')
+
+ self.assertEquals(impl.path, 'foo.implml')
+ self.assertEquals(impl.abspath, os.path.abspath(os.path.join(ROOT_PATH,'foo.implml')))
+
+
def test_implbase_tags_with_refs(self):
config = MockConfiguration({}, features = {
'Foo.Bar' : 'foobar',
@@ -353,106 +586,134 @@
self.assertTrue(impl.has_ref(['Yay', 'Foo.Bar.Baz', 'Fhtagn']))
self.assertTrue(impl.has_ref(['Yay', 'Xyz', 'Fhtagn']))
- def test_impl_container_eval_context_with_tags(self):
- container = plugin.ImplBase("norm", None)
- context = plugin.GenerationContext()
- self.assertTrue(container._eval_context(context))
- container.set_tags({'target':['rofs2','core']})
- context.tags = {'target': ['rofs2'], 'foobar': ['test']}
- self.assertTrue(container._eval_context(context))
- context.tags_policy = "AND"
- self.assertFalse(container._eval_context(context))
- container.set_tags({})
- self.assertFalse(container._eval_context(context))
- context.tags = {'target': ['rofs2']}
- self.assertFalse(container._eval_context(context))
- context.tags = {}
- self.assertTrue(container._eval_context(context))
-class TestPluginImplSet(unittest.TestCase):
+class TestPlugin(plugin.ImplBase):
+ def __init__(self, ref):
+ super(TestPlugin, self).__init__(ref, None)
+ self.refs = None
+ def get_refs(self):
+ return self.refs
+
+class TestPluginImplSet(unittest.TestCase):
def test_add_implementation_and_list(self):
- container = plugin.ImplSet()
+ iset= plugin.ImplSet()
imp1 = plugin.ImplBase("implml/test.content",None)
imp2a = plugin.ImplBase("implml/copy.content",None)
imp2b = plugin.ImplBase("implml/copy.content",None)
- container.add_implementation(imp1)
- container.add_implementation(imp2a)
- container.add_implementation(imp2b)
- self.assertEquals(sorted(container.list_implementation()),
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ iset.add_implementation(imp2b)
+ self.assertEquals(sorted(iset.list_implementation()),
sorted(['implml/test.content',
'implml/copy.content']))
+ def test_add_implementation_and_generate(self):
+ iset = plugin.ImplSet()
+ imp1 = SimpleImpl("implml/test1.content", None)
+ imp1.outputfile = 'test/foo.txt'
+ imp2a = SimpleImpl("implml/test2.content", None)
+ imp2b = SimpleImpl("implml/test3.content", None)
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ iset.add_implementation(imp2b)
+ context = plugin.GenerationContext(output="temp")
+ iset.generate(context)
+ self.assertEquals(sorted(context.executed_impls), sorted([imp1, imp2a, imp2b]))
+ self.assertEquals(context.generation_output[0].name, 'temp/test/foo.txt')
+ self.assertTrue(os.path.exists(context.generation_output[0].name))
+ self.assertEquals(context.generation_output[0].implementation,imp1)
+
+
+ def test__generate_with_exception(self):
+ def generate_exception(*args):
+ raise Exception("test exception %s" % args)
+
+ iset = plugin.ImplSet()
+ imp1 = SimpleImpl("implml/test1.content", None)
+ imp1.outputfile = 'test/foo.txt'
+ imp2a = SimpleImpl("implml/test2.content", None)
+ imp2a.generate = generate_exception
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ context = plugin.GenerationContext(output="temp")
+ iset.generate(context)
+ self.assertEquals(sorted(context.executed_impls), sorted([imp1, imp2a]))
+ self.assertEquals(context.generation_output[1].type, 'exception')
+ self.assertEquals(context.generation_output[1].name, 'exception from implml/test2.content')
+ self.assertEquals(context.generation_output[1].implementation, imp2a)
+
def test_add_implementation_and_get_implementations_by_file(self):
- container = plugin.ImplSet()
+ iset = plugin.ImplSet()
imp1 = plugin.ImplBase("implml/test.content",None)
imp2a = plugin.ImplBase("implml/copy.content",None)
imp2b = plugin.ImplBase("implml/copy.content",None)
- container.add_implementation(imp1)
- container.add_implementation(imp2a)
- container.add_implementation(imp2b)
- self.assertEquals(container.get_implementations_by_file("implml/test.content"), [imp1])
- self.assertEquals(sorted(container.get_implementations_by_file("implml/copy.content")),
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ iset.add_implementation(imp2b)
+ self.assertEquals(iset.get_implementations_by_file("implml/test.content"), [imp1])
+ self.assertEquals(sorted(iset.get_implementations_by_file("implml/copy.content")),
sorted([imp2a, imp2b]))
def test_add_implementation_and_remove_implementation(self):
- container = plugin.ImplSet()
+ iset = plugin.ImplSet()
imp1 = plugin.ImplBase("implml/test.content",None)
imp2a = plugin.ImplBase("implml/copy.content",None)
imp2b = plugin.ImplBase("implml/copy.content",None)
- container.add_implementation(imp1)
- container.add_implementation(imp2a)
- container.add_implementation(imp2b)
- container.remove_implementation("implml/test.content")
- self.assertEquals(len(container.list_implementation()),1)
- self.assertEquals(container.list_implementation()[0],"implml/copy.content")
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ iset.add_implementation(imp2b)
+ iset.remove_implementation("implml/test.content")
+ self.assertEquals(len(iset.list_implementation()),1)
+ self.assertEquals(iset.list_implementation()[0],"implml/copy.content")
def test_add_implementation_and_remove_all(self):
- container = plugin.ImplSet()
+ iset = plugin.ImplSet()
imp1 = plugin.ImplBase("implml/test.content",None)
imp2a = plugin.ImplBase("implml/copy.content",None)
imp2b = plugin.ImplBase("implml/copy.content",None)
imp3 = plugin.ImplBase("implml/foo.content",None)
- container.add_implementation(imp1)
- container.add_implementation(imp2a)
- container.add_implementation(imp2b)
- container.add_implementation(imp3)
- for implref in container.list_implementation():
- container.remove_implementation(implref)
- self.assertEquals(len(container.list_implementation()),0)
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2a)
+ iset.add_implementation(imp2b)
+ iset.add_implementation(imp3)
+ for implref in iset.list_implementation():
+ iset.remove_implementation(implref)
+ self.assertEquals(len(iset.list_implementation()),0)
def test_create_impl_set(self):
plugin.create_impl_set('',None);
pass
def test_add_implementation_find_with_tags(self):
- class TestPlugin(plugin.ImplBase):
- pass
- container = plugin.ImplSet()
- imp1 = TestPlugin("implml/test.content",None)
- imp2 = TestPlugin("implml/copy.content",None)
- imp3 = TestPlugin("implml/foo.content",None)
+ def impl_list(impl_iterable):
+ return sorted(list(impl_iterable), key=lambda impl: impl.ref)
+
+ iset = plugin.ImplSet()
+ imp1 = TestPlugin("implml/test.content")
+ imp2 = TestPlugin("implml/copy.content")
+ imp3 = TestPlugin("implml/foo.content")
imp1.set_tags({'target': ['core','rofs2','rofs3']})
imp2.set_tags({'target': ['rofs3','uda']})
imp3.set_tags({'target': ['mmc','uda']})
- container.add_implementation(imp1)
- container.add_implementation(imp2)
- container.add_implementation(imp3)
- self.assertEquals(list(container.filter_implementations(tags={'target' : ['rofs3']})),
- [imp1,imp2])
- self.assertEquals(list(container.filter_implementations(tags={'target' : ['uda']})),
- [imp2,imp3])
- self.assertEquals(list(container.filter_implementations(tags={'target' : ['mmc','uda']}, policy='AND')),
- [imp3])
- self.assertEquals(list(container.filter_implementations(tags={'target' : ['mmc','uda']}, policy='OR')),
- [imp2, imp3])
- cont = container.filter_implementations(tags={'target' : ['core']}) | container.filter_implementations(tags={'target' : ['mmc']})
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2)
+ iset.add_implementation(imp3)
+ self.assertEquals(impl_list(iset.filter_implementations(tags={'target' : ['rofs3']})),
+ impl_list([imp1,imp2]))
+ self.assertEquals(impl_list(iset.filter_implementations(tags={'target' : ['uda']})),
+ impl_list([imp2,imp3]))
+ self.assertEquals(impl_list(iset.filter_implementations(tags={'target' : ['mmc','uda']}, policy='AND')),
+ impl_list([imp3]))
+ self.assertEquals(impl_list(iset.filter_implementations(tags={'target' : ['mmc','uda']}, policy='OR')),
+ impl_list([imp2, imp3]))
+ cont = iset.filter_implementations(tags={'target' : ['core']}) | iset.filter_implementations(tags={'target' : ['mmc']})
self.assertEquals(len(cont),2)
- self.assertEquals(list(cont), [imp1,imp3])
+ self.assertEquals(impl_list(cont), impl_list([imp1,imp3]))
- cont = container.filter_implementations(tags={'target' : ['rofs3']}) & container.filter_implementations(tags={'target' : ['uda']})
+ cont = iset.filter_implementations(tags={'target' : ['rofs3']}) & iset.filter_implementations(tags={'target' : ['uda']})
self.assertEquals(len(cont),1)
- self.assertEquals(list(cont), [imp2])
+ self.assertEquals(impl_list(cont), impl_list([imp2]))
def test_pre_impl_filter(self):
resources = [
@@ -483,6 +744,40 @@
expected = map(lambda path: path.replace('/', '\\'), expected)
self.assertEquals(expected, plugin.pre_filter_impls(resources))
+ def test_get_implemented_refs(self):
+
+ iset = plugin.ImplSet()
+ imp1 = TestPlugin('imp1')
+ imp2 = TestPlugin('imp2')
+ imp3 = TestPlugin('imp3')
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2)
+ iset.add_implementation(imp3)
+ imp1.refs = ['fea.child1', 'fea.child2']
+ imp2.refs = ['fea.setting1']
+ imp3.refs = ['foo.bar']
+ self.assertEquals(sorted(iset.get_implemented_refs()), sorted(['fea.child1',
+ 'fea.child2',
+ 'fea.setting1',
+ 'foo.bar']))
+
+ def test_get_implementations_with_ref(self):
+
+ iset = plugin.ImplSet()
+ imp1 = TestPlugin('implml1')
+ imp2 = TestPlugin('implml2')
+ imp3 = TestPlugin('implml3')
+ imp4 = TestPlugin('implml3')
+ iset.add_implementation(imp1)
+ iset.add_implementation(imp2)
+ iset.add_implementation(imp3)
+ iset.add_implementation(imp4)
+ imp1.refs = ['fea.child1', 'fea.child2']
+ imp2.refs = ['foo.bar', 'fea.setting1']
+ imp3.refs = ['foo.bar']
+ self.assertEquals(iset.get_implementations_with_ref('fea.child1'), [imp1])
+ self.assertEquals(iset.get_implementations_with_ref('fea.setting1'), [imp2])
+ self.assertEquals(iset.get_implementations_with_ref('foo.bar'), [imp2, imp3])
class TestPluginImplSetCopy(unittest.TestCase):
class TestImpl(plugin.ImplBase):
@@ -509,12 +804,12 @@
return plugin.create_impl_set(impl_files, mock_config)
- def test_get_test_impl_container(self):
- container = self._get_impl_container()
+ def test_get_test_impl_iset(self):
+ iset = self._get_impl_container()
# There are 5 ImplML files
- self.assertEquals(len(container.list_implementation()), 5)
+ self.assertEquals(len(iset.list_implementation()), 5)
# ...but two of them contain 3 implementations each
- self.assertEquals(len(container), 5)
+ self.assertEquals(len(iset), 5)
def _get_phase_test_impl_container(self):
return plugin.ImplSet([
@@ -525,13 +820,13 @@
self.PostImpl('foo.post', None),
])
- def test_get_phase_test_impl_container(self):
- container = self._get_phase_test_impl_container()
- self.assertEquals(5, len(container))
- self.assertEquals(len(container.list_implementation()), 5)
+ def test_get_phase_test_impl_iset(self):
+ iset = self._get_phase_test_impl_container()
+ self.assertEquals(5, len(iset))
+ self.assertEquals(len(iset.list_implementation()), 5)
def check(filename, phase):
- impls = container.get_implementations_by_file(filename)
+ impls = iset.get_implementations_by_file(filename)
self.assertEquals(1, len(impls))
impl = impls[0]
self.assertEquals(impl.ref, filename)
@@ -542,31 +837,31 @@
check('test.post', 'post')
check('foo.post', 'post')
- return container
+ return iset
def test_create_impl_set(self):
- container = self._get_impl_container()
+ iset = self._get_impl_container()
# There are 5 ImplML files
- self.assertEquals(len(container.list_implementation()), 5)
+ self.assertEquals(len(iset.list_implementation()), 5)
# ...but two of them contain 3 implementations each
- self.assertEquals(len(container), 5)
+ self.assertEquals(len(iset), 5)
def test_invocation_phases(self):
- container = self._get_phase_test_impl_container()
- phases = container.invocation_phases()
+ iset = self._get_phase_test_impl_container()
+ phases = iset.invocation_phases()
self.assertEquals(phases,['pre','normal','post'])
def test_copy(self):
- container = self._get_impl_container()
- newcontainer = container.copy()
- self.assertTrue(newcontainer is not container)
+ iset = self._get_impl_container()
+ newcontainer = iset.copy()
+ self.assertTrue(newcontainer is not iset)
self.assertEquals(len(newcontainer), 5)
def test_execute_generate(self):
- container = self._get_impl_container()
- container.execute(container, 'generate')
+ iset = self._get_impl_container()
+ iset.execute(iset, 'generate')
actual_impls = []
- for impl in container:
+ for impl in iset:
if isinstance(impl, plugin.ImplContainer):
actual_impls += impl.get_all_implementations()
else:
@@ -575,14 +870,14 @@
self.assertTrue(impl.generate_invoked)
def test_impl_container_generate(self):
- container = self._get_impl_container()
+ iset = self._get_impl_container()
context = plugin.GenerationContext()
context.history = ""
context.objects = []
- container.generate(context)
+ iset.generate(context)
self.assertEquals(len(context.objects), 9)
actual_impls = []
- for impl in container:
+ for impl in iset:
if isinstance(impl, plugin.ImplContainer):
actual_impls += impl.get_all_implementations()
else:
@@ -591,27 +886,27 @@
self.assertTrue(impl.generate_invoked)
def test_filter_all(self):
- container = self._get_impl_container()
- impl_list = container.filter_implementations()
+ iset = self._get_impl_container()
+ impl_list = iset.filter_implementations()
self.assertEquals(len(impl_list), 5)
def test_filter_for_pre_phase(self):
- container = self._get_phase_test_impl_container()
- impl_list = list(container.filter_implementations(phase='pre'))
+ iset = self._get_phase_test_impl_container()
+ impl_list = list(iset.filter_implementations(phase='pre'))
self.assertEquals(len(impl_list), 1)
self.assertEquals(impl_list[0].invocation_phase(), 'pre')
self.assertEquals(impl_list[0].ref, 'foo.pre')
def test_filter_for_normal_phase(self):
- container = self._get_phase_test_impl_container()
- impl_list = list(container.filter_implementations(phase='normal'))
+ iset = self._get_phase_test_impl_container()
+ impl_list = list(iset.filter_implementations(phase='normal'))
self.assertEquals(len(impl_list), 2)
self.assertEquals(impl_list[0].invocation_phase(), 'normal')
self.assertEquals(impl_list[1].invocation_phase(), 'normal')
def test_filter_for_post_phase(self):
- container = self._get_phase_test_impl_container()
- impl_list = list(container.filter_implementations(phase='post'))
+ iset = self._get_phase_test_impl_container()
+ impl_list = list(iset.filter_implementations(phase='post'))
self.assertEquals(len(impl_list), 2)
self.assertEquals(impl_list[0].invocation_phase(), 'post')
self.assertEquals(impl_list[1].invocation_phase(), 'post')
@@ -628,11 +923,11 @@
def test_plugin_settings(self):
settings.SettingsFactory.cone_parser().read([os.path.join(ROOT_PATH,'test_defaults.cfg')])
impl = TestPluginImplSettings.Test1Impl("",None)
- self.assertEquals(impl.output_root, 'output')
+ self.assertEquals(impl.output_root, '')
self.assertEquals(impl.output_subdir, '')
impl.output_subdir = 'foobar'
self.assertEquals(impl.get_tags(), {})
- self.assertEquals(impl.output, 'output/foobar')
+ self.assertEquals(impl.output, 'foobar')
impl = TestPluginImplSettings.Test2Impl("",None)
self.assertEquals(impl.output_subdir, '')
@@ -740,12 +1035,6 @@
MockImpl(['MockReader2', file, {'a': '1', 'b': '2'}]),],
file)
- file = 'layer1/implml/ignored_ns_1.mock3ml'
- self.assert_read_impls_equal([MockImpl(['MockReader3', file, {'x': '1'}])], file)
-
- file = 'layer1/implml/ignored_ns_2.mock3ml'
- self.assert_read_impls_equal([MockImpl(['MockReader3', file, {'x': '1'}])], file)
-
self.assert_read_impls_equal([], 'layer1/implml/unsupported1.implml')
self.assert_read_impls_equal([], 'layer1/implml/unsupported2.implml')
@@ -788,9 +1077,6 @@
MockImpl(['MockReader3', 'layer1/implml/single3.test3ml', {'x': '1'}]),
- MockImpl(['MockReader3', 'layer1/implml/ignored_ns_1.mock3ml', {'x': '1'}]),
- MockImpl(['MockReader3', 'layer1/implml/ignored_ns_2.mock3ml', {'x': '1'}]),
-
MockImpl(['MockReader1','layer1/implml/multi1.implml', {'y': '2', 'x': '1'}]),
MockImpl(['MockReader2', 'layer1/implml/multi1.implml', {'y': '20', 'x': '10'}]),
MockImpl(['MockReader3', 'layer1/implml/multi1.implml', {'y': '200', 'x': '100'}, {'z': '300'}]),
@@ -878,8 +1164,8 @@
self.assert_contains_feature(config, 'TempFeature.Seq.DefaultType', 'string', [])
fea = config.get_default_view().get_feature('TempFeature.Seq')
- fea.set_value([['test', '1', '2.0', 'true', 'foo']])
- self.assertEquals(fea.get_value(), [['test', '1', '2.0', 'true', 'foo']])
+ fea.set_value([['test', 1, 2.0, True, 'foo']])
+ self.assertEquals(fea.get_value(), [['test', 1, 2.0, True, 'foo']])
def _create_mock_impl(self, temp_var_defs):
impl = Mock()
@@ -950,7 +1236,10 @@
config = api.Configuration("test.confml")
config.add_feature(api.Feature("Int"), "TempFeature")
- self.assertRaises(exceptions.AlreadyExists, impls.create_temp_features, config)
+ #self.assertRaises(exceptions.AlreadyExists, impls.create_temp_features, config)
+ temp_feature_refs = impls.create_temp_features(config)
+ self.assertEquals(temp_feature_refs, ['TempFeature.String', 'TempFeature.Real', 'TempFeature.Boolean'])
+
class TestCommonImplmlDataReader(unittest.TestCase):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_plugin_implcontainer.py
--- a/configurationengine/source/cone/public/tests/unittest_plugin_implcontainer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_plugin_implcontainer.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,8 +17,8 @@
import unittest
import os
import logging
-import __init__
-from cone.public import *
+
+from cone.public import api, plugin, rules
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -28,19 +28,33 @@
def __init__(self,ref,configuration):
plugin.ImplBase.__init__(self,ref,configuration)
self.generate_invoked = False
+ self.output_created = False
self.refs = ["dummy1.too"]
- self.output_files = []
+ self.output_files = ['foo/test.txt']
+ self.context = None
def generate(self, context=None):
self.generate_invoked = True
- if context and hasattr(context, 'objects'):
- context.objects.append(self)
-
+ if context:
+ for outfile in self.list_output_files():
+ context.add_file(outfile, implementation=self)
+
def get_refs(self):
return self.refs
def list_output_files(self):
return self.output_files
+ def get_outputs(self):
+ """
+ Return a list of GenerationOutput objets as a list.
+ """
+ outputs = []
+ phase = None
+ if self.context: phase = self.context.phase
+ for outfile in self.list_output_files():
+ outputs.append( plugin.GenerationOutput(outfile,self,type='file', phase=phase) )
+ return outputs
+
def test_impl_container_add(self):
container = plugin.ImplContainer("norm", None)
imp1 = plugin.ImplBase("implml/test.content",None)
@@ -62,8 +76,6 @@
subcontainer.append(imp2b)
container.append(subcontainer)
self.assertEquals(container.get_all_implementations(),[imp1,imp2a,imp2b])
- for sub in container:
- print sub
self.assertEquals(container.impls, [imp1,subcontainer])
container[0] = subcontainer
self.assertEquals(container.impls, [subcontainer,subcontainer])
@@ -71,6 +83,10 @@
self.assertEquals(container.impls, [subcontainer])
def test_impl_container_with_condition(self):
+ logger = logging.getLogger('cone')
+ ch = logging.StreamHandler()
+ ch.setLevel(logging.DEBUG)
+ logger.addHandler(ch)
context = plugin.GenerationContext()
context.configuration = api.Configuration()
context.configuration.add_feature(api.Feature("test"))
@@ -95,7 +111,6 @@
imp1.generate_invoked = False
condition = rules.SimpleCondition("${test}", "false")
container.condition = condition
- container.append(imp1)
container.generate(context)
self.assertTrue(imp1.generate_invoked)
imp1.generate_invoked = False
@@ -103,6 +118,16 @@
container.generate(context)
self.assertFalse(imp1.generate_invoked)
+ imp1.generate_invoked = False
+ condition = rules.SimpleCondition("${test.intsub}", "1")
+ container.condition = condition
+ container.append(imp1)
+ container.generate(context)
+ self.assertFalse(imp1.generate_invoked)
+ context.configuration.get_default_view().test.intsub.value = 1
+ container.generate(context)
+ self.assertTrue(imp1.generate_invoked)
+
def test_impl_container_generate(self):
container = plugin.ImplContainer("norm", None)
@@ -127,21 +152,20 @@
container.append(imp2a)
container.append(imp2b)
container.append(subcontainer)
- self.assertEquals(container.get_tags(), {})
+ self.assertEquals(container.get_tags(), None)
+ self.assertEquals(container.get_child_tags(), {})
container.set_tags({'test':['foobar']})
- self.assertEquals(container.get_tags(), {'test':['foobar']})
+ self.assertEquals(container.get_tags(), None)
+ self.assertEquals(container.get_child_tags(), {})
imp1.set_tags({'foo':['bar']})
- self.assertEquals(container.get_tags(), {'test':['foobar'],
- 'foo':['bar']})
- imp2a.set_tags({'test':['bar'], 'one' :['more']})
+ self.assertEquals(container.get_child_tags(), {'foo':['bar']})
+ self.assertEquals(container.get_tags(), None)
+ imp2a.set_tags({'test':['bar'], 'foo' :['more']})
+ self.assertEquals(container.get_child_tags(), {'foo':['bar', 'more'], 'test': ['bar']})
- self.assertEquals(container.get_tags(), {'test':['foobar', 'bar'],
- 'foo':['bar'],
- 'one' :['more']})
+ self.assertEquals(container.get_tags(), None)
subcontainer.set_tags({'test':['bar1']})
- self.assertEquals(container.get_tags(), {'test':['foobar', 'bar', 'bar1'],
- 'foo':['bar'],
- 'one' :['more']})
+ self.assertEquals(container.get_tags(), None)
def test_impl_container_get_phase(self):
container = plugin.ImplContainer("norm", None)
@@ -154,16 +178,16 @@
subcontainer1.append(imp2a)
subcontainer1.append(imp2b)
subcontainer1.set_invocation_phase("normal")
- self.assertEquals(container.invocation_phase(), ["normal"])
+ self.assertEquals(container.invocation_phase(), "normal")
imp1.set_invocation_phase('pre')
- self.assertEquals(container.invocation_phase(), ["normal"])
+ self.assertEquals(container.invocation_phase(), "normal")
subcontainer2 = plugin.ImplContainer("norm", None)
subimp = TestPluginImplContainer.ImplTest("implml/copy:24.content",None)
subimp.set_invocation_phase('post')
subcontainer2.append(subimp)
subcontainer2.set_invocation_phase('post')
container.append(subcontainer2)
- self.assertEquals(container.invocation_phase(), ['post','normal'])
+ self.assertEquals(container.invocation_phase(), 'normal')
def test_impl_container_get_refs(self):
container = plugin.ImplContainer("norm", None)
@@ -173,10 +197,14 @@
container.append(imp1)
container.append(imp2a)
container.append(imp2b)
- self.assertEquals(container.get_refs(), ["dummy1.too"])
+ self.assertEquals(container.get_refs(), None)
+ self.assertEquals(container.get_child_refs(), ['dummy1.too'])
imp2b.refs = ['dummy2.foo']
- self.assertEquals(container.get_refs(), ["dummy1.too",
- "dummy2.foo",])
+ self.assertEquals(container.get_refs(), None)
+ self.assertEquals(container.get_child_refs(), ['dummy1.too', 'dummy2.foo'])
+ imp2b.refs = None
+ self.assertEquals(container.get_refs(), None)
+ self.assertEquals(container.get_child_refs(), ['dummy1.too'])
def test_impl_container_list_output_files(self):
container = plugin.ImplContainer("norm", None)
@@ -188,13 +216,35 @@
subcontainer.append(imp1)
subcontainer.append(imp2a)
subcontainer.append(imp2b)
- self.assertEquals(container.list_output_files(), [])
+ self.assertEquals(container.list_output_files(), ['foo/test.txt'])
imp2b.output_files= ['output/dummy2.txt']
- self.assertEquals(container.list_output_files(), ['output/dummy2.txt'])
+ self.assertEquals(container.list_output_files(), ['foo/test.txt', 'output/dummy2.txt'])
imp1.output_files= ['output/foobar/hee.txt']
self.assertEquals(container.list_output_files(), ['output/foobar/hee.txt',
+ 'foo/test.txt',
'output/dummy2.txt'])
+ def test_impl_container_get_outputs(self):
+ container = plugin.ImplContainer("norm", None)
+ subcontainer = plugin.ImplContainer("norm", None)
+ imp1 = TestPluginImplContainer.ImplTest("implml/test.content",None)
+ imp2a = TestPluginImplContainer.ImplTest("implml/copy:21.content",None)
+ imp2b = TestPluginImplContainer.ImplTest("implml/copy:24.content",None)
+ container.append(subcontainer)
+ subcontainer.append(imp1)
+ subcontainer.append(imp2a)
+ subcontainer.append(imp2b)
+ self.assertEquals(len(container.get_outputs()), 3)
+ self.assertEquals(container.get_outputs()[0].name, 'foo/test.txt')
+ self.assertEquals(container.get_outputs()[1].name, 'foo/test.txt')
+ self.assertEquals(container.get_outputs()[2].name, 'foo/test.txt')
+ imp2b.output_files= ['foobar.txt','output/dummy2.txt']
+ self.assertEquals(len(container.get_outputs()),4)
+ self.assertEquals(container.get_outputs()[0].name, 'foo/test.txt')
+ self.assertEquals(container.get_outputs()[1].name, 'foo/test.txt')
+ self.assertEquals(container.get_outputs()[2].name, 'foobar.txt')
+
+
def test_impl_container_set_output_root(self):
container = plugin.ImplContainer("norm", None)
subcontainer = plugin.ImplContainer("norm", None)
@@ -205,7 +255,7 @@
subcontainer.append(imp1)
subcontainer.append(imp2a)
subcontainer.append(imp2b)
- self.assertEquals(imp1.get_output_root(), 'output')
+ self.assertEquals(imp1.get_output_root(), '')
container.set_output_root('foobar/test')
self.assertEquals(imp1.get_output_root(), 'foobar/test')
@@ -238,13 +288,11 @@
container.append(subcontainer)
self.assertEquals(container.impls, [imp1,subcontainer])
context = plugin.GenerationContext()
- context.objects = []
container.generate(context)
self.assertTrue(imp1.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
- self.assertEquals(len(context.objects), 3)
- self.assertEquals(context.objects, [imp1,imp2a,imp2b])
+ self.assertEquals(sorted(context.executed_impls), sorted([imp1,imp2a,imp2b]))
def test_impl_container_generate_with_generation_contexts_tags(self):
container = plugin.ImplContainer("norm", None)
@@ -253,9 +301,10 @@
subcontainer1.append(imp1)
subcontainer2 = plugin.ImplContainer("implml/sub2.implml", None)
- subcontainer2.set_tags({'target': ['rofs3','uda']})
imp2a = TestPluginImplContainer.ImplTest("implml/copy:21.content",None)
+ imp2a.set_tags({'target': ['rofs3','uda']})
imp2b = TestPluginImplContainer.ImplTest("implml/copy:24.content",None)
+ imp2b.set_tags({'target': ['rofs3','uda']})
subcontainer2.append(imp2a)
subcontainer2.append(imp2b)
container.append(subcontainer1)
@@ -263,13 +312,11 @@
context = plugin.GenerationContext()
context.tags = {'target': ['rofs3'], 'foobar' :['test']}
- context.objects = []
container.generate(context)
self.assertFalse(imp1.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
- self.assertEquals(len(context.objects), 2)
- self.assertEquals(context.objects, [imp2a,imp2b])
+ self.assertEquals(sorted(context.executed_impls), sorted([imp2a,imp2b]))
def test_impl_container_generate_with_generation_phase(self):
container = plugin.ImplContainer("norm", None)
@@ -278,21 +325,47 @@
subcontainer1.append(imp1)
subcontainer2 = plugin.ImplContainer("implml/sub2.implml", None)
- subcontainer2.set_invocation_phase("post")
imp2a = TestPluginImplContainer.ImplTest("implml/copy:21.content",None)
+ imp2a.set_invocation_phase("post")
imp2b = TestPluginImplContainer.ImplTest("implml/copy:24.content",None)
+ imp2b.set_invocation_phase("post")
subcontainer2.append(imp2a)
subcontainer2.append(imp2b)
container.append(subcontainer1)
container.append(subcontainer2)
- context = plugin.GenerationContext()
+ context = plugin.GenerationContext(output='')
context.phase = "post"
- context.objects = []
container.generate(context)
self.assertFalse(imp1.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
self.assertTrue(imp2a.generate_invoked)
- self.assertEquals(len(context.objects), 2)
- self.assertEquals(context.objects, [imp2a,imp2b])
+ self.assertEquals(sorted(context.executed_impls), sorted([imp2a,imp2b]))
+ self.assertEquals(context.executed_impls[0].list_output_files(), ['foo/test.txt'])
+ self.assertEquals(len(context.generation_output), 2)
+ self.assertEquals(context.generation_output[0].name, 'foo/test.txt')
+ self.assertEquals(str(context.generation_output[0]), "GenerationOutput(foo/test.txt, ImplTest(ref='implml/copy:21.content', type=None, lineno=None))")
+ self.assertEquals(str(context.generation_output[1]), "GenerationOutput(foo/test.txt, ImplTest(ref='implml/copy:24.content', type=None, lineno=None))")
+ self.assertEquals(context.generation_output[0].implementation, imp2a)
+
+ def test_impl_container_generate_dry_run(self):
+ container = plugin.ImplContainer("norm", None)
+ imp1 = TestPluginImplContainer.ImplTest("implml/test.content",None)
+ container.append(imp1)
+ subcontainer = plugin.ImplContainer("implml/sub.implml", None)
+ imp2a = TestPluginImplContainer.ImplTest("implml/copy:21.content",None)
+ imp2b = TestPluginImplContainer.ImplTest("implml/copy:24.content",None)
+ subcontainer.append(imp2a)
+ subcontainer.append(imp2b)
+ container.append(subcontainer)
+ self.assertEquals(container.impls, [imp1,subcontainer])
+ context = plugin.GenerationContext()
+ context.dry_run= True
+ container.generate(context)
+ self.assertFalse(imp1.generate_invoked)
+ self.assertFalse(imp2a.generate_invoked)
+ self.assertFalse(imp2a.generate_invoked)
+ self.assertEquals(sorted(context.executed_impls), sorted([imp1, imp2a,imp2b]))
+ self.assertEquals(context.executed_impls[0].list_output_files(), ['foo/test.txt'])
+ self.assertEquals(len(context.generation_output), 0)
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_plugin_reader.py
--- a/configurationengine/source/cone/public/tests/unittest_plugin_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_plugin_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,11 +17,60 @@
import unittest
import os
import logging
-import __init__
+
from cone.public import *
from cone.public import _plugin_reader
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class MockImpl(plugin.ImplBase):
+ def __init__(self, data):
+ self.data = data
+ self.generate_invoked = False
+
+ @classmethod
+ def create(cls, resource_ref, configuration, data):
+ impl = cls(data)
+ plugin.ImplBase.__init__(impl, resource_ref, configuration)
+ return impl
+
+ def generate(self, context=None):
+ if context and hasattr(context,'objects'):
+ context.objects.append(self)
+ self.generate_invoked = True
+
+ def __repr__(self):
+ return "MockImpl(%r)" % self.data
+
+ def __eq__(self, other):
+ if type(self) == type(other):
+ return self.data == other.data
+ else:
+ return False
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __lt__(self, other):
+ if type(self) == type(other):
+ return self.data < other.data
+ else:
+ return False
+
+class MockReaderBase(plugin.ReaderBase):
+ @classmethod
+ def read_impl(cls, resource_ref, configuration, root_elem):
+ data = [cls.__name__, resource_ref]
+ for elem in root_elem.findall('{%s}elem' % cls.NAMESPACE):
+ data.append(elem.attrib)
+ return MockImpl.create(resource_ref, configuration, data)
+
+class MockReader(MockReaderBase):
+ NAMESPACE = "http://www.test.com/xml/1"
+ NAMESPACE_ID = "mock"
+ ROOT_ELEMENT_NAME = "impl"
+ FILE_EXTENSIONS = ['mockml']
+
class ImplTest(plugin.ImplBase):
def __init__(self,ref,configuration):
plugin.ImplBase.__init__(self,ref,configuration)
@@ -47,11 +96,10 @@
class TestCommonNamespaceHandling(unittest.TestCase):
def setUp(self):
- pass
-
-
+ plugin.ImplFactory.set_reader_classes_override([MockReader])
+
def tearDown(self):
- pass
+ plugin.ImplFactory.set_reader_classes_override(None)
def test_implcontainer_reader_get_condition(self):
root = utils.etree.fromstring("")
@@ -81,6 +129,35 @@
"""
container = plugin.ImplContainerReader.read_implementation(xml_data)
self.assertTrue(isinstance(container, plugin.ImplContainer))
+
+ def test_get_reader_for_namespace(self):
+ self.assertEquals(plugin.ReaderBase.get_reader_for_namespace('http://www.symbianfoundation.org/Foo'), None)
+ self.assertEquals(plugin.ReaderBase.get_reader_for_namespace('http://www.symbianfoundation.org/xml/implml/1'),
+ plugin.ImplContainerReader)
+
+ def test_read_container_via_common_readerbase(self):
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'testdata')))
+ config = prj.create_configuration("test.confml", True)
+ container = plugin.read_impl_from_location('layer1/implml/test.implml', config, 4)
+ self.assertEquals(container.invocation_phase(), 'normal')
+ self.assertEquals(container.path, 'layer1/implml/test.implml')
+ self.assertEquals(container.lineno, 4)
+ self.assertEquals(container[0].invocation_phase(), 'normal')
+ self.assertEquals(container[0].path, 'layer1/implml/test.implml')
+ self.assertEquals(container[0].lineno, 5)
+
+
+ def test_read_containers_from_location(self):
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'testdata')))
+ config = prj.create_configuration("test.confml", True)
+
+ container = plugin.ImplContainerReader.read_impl_from_location('layer1/implml/test.implml', config, 4)
+ self.assertEquals(container.invocation_phase(), 'normal')
+ self.assertEquals(container.path, 'layer1/implml/test.implml')
+ self.assertEquals(container.lineno, 4)
+ self.assertEquals(container[0].invocation_phase(), 'normal')
+ self.assertEquals(container[0].path, 'layer1/implml/test.implml')
+ self.assertEquals(container[0].lineno, 5)
def test_get_test_container_with_sub_containers(self):
xml_data = """
@@ -98,35 +175,155 @@
def test_containers_with_phases(self):
xml_data = """
-
-
-
+
+
+
+
+
+
-
+
"""
container = plugin.ImplContainerReader.read_implementation(xml_data)
- self.assertEquals(container.invocation_phase(), ['post','normal'])
- self.assertEquals(container[2].invocation_phase(), ['post'])
+ self.assertEquals(container[0].invocation_phase(), 'normal')
+ self.assertEquals(container[1][0].invocation_phase(), 'normal')
+ self.assertEquals(container[2][0].invocation_phase(), 'post')
def test_containers_with_tags(self):
xml_data = """
-
-
+
+
+
+
+
-
+
"""
container = plugin.ImplContainerReader.read_implementation(xml_data)
- self.assertEquals(container[2].get_tags(), {'target': ['rofs3']})
- self.assertEquals(container.get_tags(), {'target': ['rofs2','rofs3'],
- 'foobar': ['test']})
+ self.assertEquals(container[0][0].get_tags(), {'target': ['rofs2'],
+ 'foobar': ['test']})
+ self.assertEquals(container[1][0].get_tags(), {'target': ['rofs3']})
+
+ def test_read_container_impl_line_numbers(self):
+ xml_data = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ container = plugin.ImplContainerReader.read_implementation(xml_data)
+ self.assertEquals(container[0].lineno, 3)
+ self.assertEquals(container[0][0].lineno, 4)
+ self.assertEquals(container[1].lineno, 7)
+ self.assertEquals(container[1][0].lineno, 8)
+ self.assertEquals(container[1][1].lineno, 9)
+ self.assertEquals(container[1][1][0].lineno, 10)
+ self.assertEquals(container[1][1][1].lineno, 11)
+
+ def test_container_common_element_inheritance(self):
+ xml_data = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ container = plugin.ImplContainerReader.read_implementation(xml_data)
+
+ # First impl, with all defaults
+ impl = container[0]
+ self.assertEquals(impl.get_tags(), {})
+ self.assertEquals(impl.invocation_phase(), 'normal')
+ self.assertEquals(impl.get_refs(), None)
+ self.assertEquals(impl.output, '')
+
+ # The sub-container has things overridden, check that they
+ # are all inherited correctly downwards in the implementation
+ # tree
+ def assert_is_expected(impl):
+ self.assertEquals(impl.get_tags(), {'target': ['rofs2', 'rofs3'], 'foo': ['bar']})
+ self.assertEquals(impl.invocation_phase(), 'post')
+ self.assertEquals(impl.get_refs(), ['Foo.Bar', 'Foo.Baz'])
+ self.assertEquals(impl.output, '/foo/root/foosubdir')
+ self.assertEquals(impl.output_subdir, 'foosubdir')
+ assert_is_expected(container[1][0])
+ assert_is_expected(container[1][1][0])
+ assert_is_expected(container[1][1][1][0])
+
+ # The sub-container's second sub-container has things overridden
+ # again, so check that those are correct
+ def assert_is_expected_2(impl):
+ self.assertEquals(impl.get_tags(), {'target': ['core'], 'foo': ['baz']})
+ self.assertEquals(impl.invocation_phase(), 'pre')
+ self.assertEquals(impl.get_refs(), None)
+ self.assertEquals(impl.output, '/foo/root2/foosubdir2')
+ assert_is_expected_2(container[1][2][0])
+ assert_is_expected_2(container[1][2][1][0])
def test_tempfeature_definitions(self):
xml_data = """
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_problem.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/unittest_problem.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,63 @@
+#
+# 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:
+#
+
+import unittest
+
+
+
+from cone.public import api, exceptions
+
+class TestProblems(unittest.TestCase):
+
+ def test_create_from_generic_exception(self):
+ ex = RuntimeError('foobar')
+ self.assertEquals(
+ api.Problem.from_exception(ex),
+ api.Problem('foobar', severity = api.Problem.SEVERITY_ERROR))
+
+ def test_create_from_cone_exception_simple(self):
+ ex = exceptions.ConeException('foobar')
+ self.assertEquals(
+ api.Problem.from_exception(ex),
+ api.Problem('foobar',
+ type = '',
+ severity = api.Problem.SEVERITY_ERROR))
+
+ def test_create_from_cone_exception_all_attributes(self):
+ ex = exceptions.ConeException('foobar',
+ problem_lineno = 101,
+ problem_msg = 'foobar2',
+ problem_type = 'foo.bar')
+ self.assertEquals(
+ api.Problem.from_exception(ex),
+ api.Problem('foobar2',
+ type = 'foo.bar',
+ line = 101,
+ severity = api.Problem.SEVERITY_ERROR))
+
+ def test_create_from_xml_parse_error(self):
+ ex = exceptions.XmlParseError('XML parse error',
+ problem_lineno = 1)
+ self.assertEquals(
+ api.Problem.from_exception(ex),
+ api.Problem('XML parse error',
+ type = 'xml',
+ line = 1,
+ severity = api.Problem.SEVERITY_ERROR))
+
+if __name__ == '__main__':
+ unittest.main()
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_project.py
--- a/configurationengine/source/cone/public/tests/unittest_project.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_project.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,10 +21,7 @@
import string
import sys,os,shutil
-import __init__
-
from cone.public import *
-#from cone.public import stringstorage
from cone.storage import persistentdictionary
class TestProjectOpen(unittest.TestCase):
@@ -37,7 +34,7 @@
def test_open_project_of_non_storage(self):
fs = ""
try:
- p = api.Project(fs)
+ p = api.Project("")
self.fail("Opening on top of non storage succeeds!!")
except exceptions.StorageException:
self.assertTrue(True)
@@ -50,6 +47,25 @@
self.prj.create_configuration("test.confml")
self.assertTrue(self.prj.test_confml)
self.assertEquals(self.prj.test_confml.get_path(),"test.confml")
+
+ def test_create_configuration_already_existing(self):
+ self.prj.create_configuration("test.confml")
+ try:
+ self.prj.create_configuration("test.confml")
+ self.fail("Succeeded to create already existing configuration")
+ except exceptions.AlreadyExists:
+ pass
+ try:
+ self.prj.add_configuration(api.Configuration("test.confml"))
+ self.fail("Succeeded to create already existing configuration")
+ except exceptions.AlreadyExists:
+ pass
+
+ def test_create_configuration_already_existing_with_overwrite(self):
+ self.prj.create_configuration("test.confml")
+ self.prj.create_configuration("test.confml", True)
+ self.prj.add_configuration(api.Configuration("test.confml"), True)
+
def test_create_and_getconfiguration(self):
self.prj.create_configuration("test.confml")
@@ -101,7 +117,10 @@
self.prj.create_configuration("test3.confml")
self.prj.test2_confml.create_configuration("foo/root.confml")
conf = self.prj.test2_confml.create_configuration("fii/root.confml")
- #self.assertEquals(conf.get_full_path(),'')
+ conf.add_configuration(api.Configuration("confml/data.confml"))
+ self.assertEquals(conf.get_full_path(),'fii/root.confml')
+ self.assertEquals(conf.get_configuration("confml/data.confml").get_path(),'confml/data.confml')
+ self.assertEquals(conf.get_configuration("confml/data.confml").get_full_path(),'fii/confml/data.confml')
self.assertTrue(self.prj.is_configuration("test3.confml"))
# TODO: this is not working at the moment due to performance problem in
# Project.list_all_configurations()
@@ -110,9 +129,17 @@
self.assertEquals(self.prj.list_configurations(), ["test1.confml",
"test2.confml",
"test3.confml"])
-
+ self.assertEquals(self.prj.list_all_configurations(), ['test1.confml',
+ 'test2.confml',
+ 'foo/root.confml',
+ 'fii/root.confml',
+ 'fii/confml/data.confml',
+ 'test3.confml'])
self.assertEquals(self.prj.test2_confml.list_configurations(), ["foo/root.confml",
"fii/root.confml",])
+ self.assertEquals(self.prj.test2_confml.list_all_configurations(), ["foo/root.confml",
+ "fii/root.confml",
+ "fii/confml/data.confml"])
def test_create_multi_and_add_subconfigurations_and_features(self):
self.prj.create_configuration("test1.confml")
@@ -133,7 +160,6 @@
'testfea3.testfea31',
'testfea4'])
-
class TestProjectConfigurationsStorage(unittest.TestCase):
def test_create_configuration_and_store_storage(self):
prj = api.Project(api.Storage.open("temp/testproject.pk", "w"))
@@ -242,6 +268,7 @@
prj.test_confml.include_configuration("foo/foo.confml")
prj.test_confml.include_configuration("s60/root.confml")
prj.test_confml.foo__foo_confml.create_configuration("data.confml")
+ prj.test_confml.foo__foo_confml.add_configuration(api.Configuration("confml/test.confml"))
foofea = api.Feature("foofea")
foofea.add_feature(api.Feature("foofea_setting1"))
foofea.add_feature(api.Feature("foofea_setting2"))
@@ -255,13 +282,19 @@
res = layer.content_folder().open_resource("foobar.txt","w")
res.write("foo bar")
res.close()
- self.assertEquals(layer.list_confml(), ['confml/component.confml', 'confml/component1.confml'])
+ self.assertEquals(layer.list_confml(), ['confml/component.confml', 'confml/component1.confml', 'confml/test.confml'])
self.assertEquals(layer.list_content(), ['content/foobar.txt'])
- self.assertEquals(layer.list_all_resources(), ['confml/component.confml', 'confml/component1.confml', 'content/foobar.txt'])
- self.assertEquals(foo_config.list_resources(), ['foo/foo.confml','foo/data.confml', 'foo/confml/component.confml', 'foo/confml/component1.confml', 'foo/content/foobar.txt'])
+ self.assertEquals(layer.list_all_resources(), ['confml/component.confml', 'confml/component1.confml', 'confml/test.confml', 'content/foobar.txt'])
+ self.assertEquals(foo_config.list_resources(), ['foo/foo.confml',
+ 'foo/data.confml',
+ 'foo/confml/test.confml',
+ 'foo/confml/component.confml',
+ 'foo/confml/component1.confml',
+ 'foo/content/foobar.txt'])
self.assertEquals(prj.test_confml.list_resources(), ['test.confml',
'foo/foo.confml',
'foo/data.confml',
+ 'foo/confml/test.confml',
's60/root.confml',
'foo/confml/component.confml',
'foo/confml/component1.confml',
@@ -287,7 +320,6 @@
shutil.rmtree("temp")
-
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_property.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/public/tests/unittest_property.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,156 @@
+#
+# 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:
+#
+
+"""
+Test sets
+"""
+import unittest
+
+from cone.public import api,exceptions
+
+
+class TestProperty(unittest.TestCase):
+ def test_create_property(self):
+ property = api.Property(name='test',value='foo', unit='kB')
+ self.assertEquals(property.name, 'test')
+ self.assertEquals(property.value, 'foo')
+ self.assertEquals(property.unit, 'kB')
+ property.name = 'testnew'
+ property.value = 'foo faa'
+ property.unit = "MB"
+ self.assertEquals(property.name, 'testnew')
+ self.assertEquals(property.value, 'foo faa')
+ self.assertEquals(property.unit, 'MB')
+
+ def test_add_property_to_feature(self):
+ fea = api.Feature("testfea")
+ prop1 = api.Property(name='test',value='foo', unit='kB')
+ fea.add_property(prop1)
+ self.assertEquals(fea.list_properties(),['test'])
+ self.assertEquals(fea.get_property('test'),prop1)
+
+ def test_add_and_remove_property_to_feature(self):
+ fea = api.Feature("testfea")
+ prop1 = api.Property(name='test',value='foo', unit='kB')
+ fea.add_property(prop1)
+ self.assertEquals(fea.list_properties(),['test'])
+ fea.remove_property('test')
+ self.assertEquals(fea.list_properties(),[])
+
+ def test_add_property_invalid_param(self):
+ fea = api.Feature('test')
+ self.assertRaises(TypeError, fea.add_property, object())
+
+ def test_property_compare(self):
+ elem1 = api.Property(name='test1',value='foo', unit='kB')
+ elem2 = api.Property(name='test2',value='bar', unit='MB')
+ elem3 = api.Property(name='test3',value='foobar', unit='B')
+ self.assertFalse(elem1==elem2)
+ self.assertFalse(elem1==elem3)
+
+ def test_get_property_nonexistent(self):
+ fea = api.Feature('test')
+ self.assertRaises(exceptions.NotFound, fea.get_property, 'foo')
+
+ def test_get_property_invalid_type(self):
+ fea = api.Feature('test')
+ fea.add(api.Feature('property_foo'))
+ self.assertRaises(TypeError, fea.get_property, 'foo')
+
+ def test_create_feature_with_properties(self):
+ fea = api.Feature('test')
+ prop1 = api.Property(name='test1',value='foo', unit='kB')
+ prop2 = api.Property(name='test2',value='bar', unit='MB')
+ fea.add_property(prop1)
+ fea.add(prop2)
+ self.assertEquals(fea.list_properties(), ['test1','test2'])
+ self.assertEquals(fea.property_test1.get_name(),'test1')
+ self.assertEquals(fea.property_test1.get_value(),'foo')
+ self.assertEquals(fea.property_test1.get_unit(),'kB')
+ self.assertEquals(fea.get_property('test1').get_name(),'test1')
+ self.assertEquals(fea.get_property('test1').get_value(),'foo')
+ self.assertEquals(fea.get_property('test1').get_unit(),'kB')
+ self.assertEquals(fea.property_test2.get_name(),'test2')
+ self.assertEquals(fea.property_test2.get_value(),'bar')
+ self.assertEquals(fea.property_test2.get_unit(),'MB')
+ fea.add_property(prop2)
+ self.assertEquals(fea.list_properties(), ['test1','test2'])
+
+ def test_resetting_properties(self):
+ fea = api.Feature('test')
+ prop1 = api.Property(name='test1',value='foo', unit='kB')
+ prop2 = api.Property(name='test1',value='bar', unit='MB')
+ fea.add_property(prop1)
+ self.assertEquals(fea.list_properties(), ['test1'])
+ self.assertEquals(fea.get_property('test1').get_name(),'test1')
+ self.assertEquals(fea.get_property('test1').get_value(),'foo')
+ self.assertEquals(fea.get_property('test1').get_unit(),'kB')
+ fea.add_property(prop2)
+ self.assertEquals(fea.get_property('test1').get_name(),'test1')
+ self.assertEquals(fea.get_property('test1').get_value(),'bar')
+ self.assertEquals(fea.get_property('test1').get_unit(),'MB')
+ self.assertEquals(fea.list_properties(), ['test1'])
+
+ def test_adding_and_removing_multiple_properties(self):
+ fea = api.Feature('test')
+ prop1 = api.Property(name='test1',value='foo', unit='kB')
+ prop2 = api.Property(name='test2',value='bar1', unit='MB1')
+ prop3 = api.Property(name='test3',value='bar2', unit='MB2')
+
+ self.assertEquals(fea.list_properties(), [])
+
+ fea.add_property(prop1)
+ self.assertEquals(fea.list_properties(), ['test1'])
+
+ fea.add_property(prop2)
+ self.assertEquals(fea.list_properties(), ['test1', 'test2'])
+
+ fea.add_property(prop3)
+ self.assertEquals(fea.list_properties(), ['test1', 'test2', 'test3'])
+ self.assertEquals(fea.get_property('test1').get_name(),'test1')
+ self.assertEquals(fea.get_property('test1').get_value(),'foo')
+ self.assertEquals(fea.get_property('test1').get_unit(),'kB')
+ self.assertEquals(fea.get_property('test2').get_name(),'test2')
+ self.assertEquals(fea.get_property('test2').get_value(),'bar1')
+ self.assertEquals(fea.get_property('test2').get_unit(),'MB1')
+ self.assertEquals(fea.get_property('test3').get_name(),'test3')
+ self.assertEquals(fea.get_property('test3').get_value(),'bar2')
+ self.assertEquals(fea.get_property('test3').get_unit(),'MB2')
+
+ fea.remove_property('test2')
+ self.assertEquals(fea.list_properties(), ['test1', 'test3'])
+
+ fea.remove_property('test3')
+ self.assertEquals(fea.list_properties(), ['test1'])
+
+ fea.remove_property('test1')
+ self.assertEquals(fea.list_properties(), [])
+
+ def test_remove_property_nonexistent(self):
+ fea = api.Feature('test')
+ self.assertRaises(exceptions.NotFound, fea.remove_property, 'nonexisting')
+
+ def test_remove_property_invalid_param(self):
+ fea = api.Feature('test')
+ fea.add(api.Feature('property_xyz'))
+ self.assertRaises(TypeError, fea.remove_property, 'xyz')
+
+ def test_create_property_without_name(self):
+ try:
+ api.Property(name=None, value='foo', unit='kB')
+ except ValueError:
+ return #ValueError expected
+ self.fail("ValueError expected.")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_public_api.py
--- a/configurationengine/source/cone/public/tests/unittest_public_api.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_public_api.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,7 +16,7 @@
import unittest
import os
-import __init__
+
from cone.public import *
class TestPublicApiConfiguration(unittest.TestCase):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_rules.py
--- a/configurationengine/source/cone/public/tests/unittest_rules.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_rules.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,25 +16,21 @@
#
import unittest
-import sys, os
-import __init__
-from cone.public.api import CompositeConfiguration, Feature
-from cone.public.rules import ASTInterpreter, RelationContainerImpl, RELATIONS, get_tokens
-from cone.public.rules import ParseException, DefaultContext, BaseRelation, RequireExpression, OPERATORS
+from cone.public import rules
#### TEST RELATIONS ####
-AA_BA = 'a.a require b.b'
-AB_BB = 'a.b require b.b'
-BA_CA = 'b.a require c.a and c.b and a.b'
+AA_BA = '${a.a} require ${b.b}'
+AB_BB = '${a.b} require ${b.b}'
+BA_CA = '${b.a} require ${c.a} and ${c.b} and ${a.b}'
-CB_DA = 'c.b require d.a'
-DA_DB = 'd.a require d.b'
+CB_DA = '${c.b} require ${d.a}'
+DA_DB = '${d.a} require ${d.b}'
-AC_AB_BA = 'a.c and a.a require b.a'
+AC_AB_BA = '${a.c} and ${a.a} require ${b.a}'
-EA_FSTAR = 'e.a require f.*'
+EA_FSTAR = '${e.a} require ${f.*}'
TEST_RELATIONS = {
'a.a' : [AA_BA],
@@ -46,18 +42,21 @@
'e.a' : [EA_FSTAR]
}
+#rules.RELATIONS[rules.BaseRelation.KEY] = rules.BaseRelation
+#rules.OPERATORS[rules.BaseRelation.KEY] = rules.BaseRelation
+
class DummyRelationFactory():
def get_relations_for(self, configuration, ref):
rels = TEST_RELATIONS.get(ref)
if rels:
- relation_container = RelationContainerImpl()
+ relation_container = rules.RelationContainerImpl()
for rel in rels:
rel_s = rel.split(' ')
from_ref = rel_s[0]
relation_name = 'require'
to_ref = ' '.join(rel_s[2:])
- relation = RELATIONS.get(relation_name)(configuration, from_ref, to_ref)
+ relation = rules.RELATIONS.get(relation_name)(configuration, from_ref, to_ref)
relation_container.add_relation(relation)
propagated_relations = self.get_relations_for(configuration, to_ref)
if propagated_relations:
@@ -82,11 +81,25 @@
def get_feature(self, ref):
return DummyConfiguration.VALUES.get(ref, False)
-class DummyContext(DefaultContext):
+class DummyContext(rules.DefaultContext):
def handle_terminal(self, expression):
return DummyConfiguration.VALUES.get(expression, False)
-class DummyBaseRelation(BaseRelation):
+class DictContext(rules.DefaultContext):
+ def handle_terminal(self, expression):
+ return self.data.get(expression, None)
+
+ def convert_value(self, value):
+ if isinstance(value, (str, unicode)):
+ return eval(value)
+ else:
+ return value
+
+ def set(self, expression, value):
+ self.data[expression] = value
+
+
+class DummyBaseRelation(rules.BaseRelation):
def __init__(self, data, left, right):
self.context = DummyContext(data)
super(DummyBaseRelation, self).__init__(data, left, right)
@@ -98,8 +111,8 @@
self.context = DummyContext(data)
super(DummyRequireRelation, self).__init__(data, left, right)
-RELATIONS[DummyRequireRelation.KEY] = DummyRequireRelation
-OPERATORS['require'] = RequireExpression
+rules.RELATIONS[DummyRequireRelation.KEY] = DummyRequireRelation
+rules.OPERATORS['require'] = rules.RequireExpression
multilines = \
"""
APs.AP configures KCRUidCommsDatCreator.KCommsDatCreatorInputFileName = 'VariantData_commsdat.xml' and
@@ -141,7 +154,7 @@
factory = DummyRelationFactory()
rels = factory.get_relations_for(self.configuration, 'c.b')
ret = rels.execute()
- self.assertFalse(ret)
+ self.assertTrue(ret)
def test_two_on_the_left(self):
factory = DummyRelationFactory()
@@ -149,46 +162,176 @@
ret = rels.execute()
self.assertTrue(ret)
+class TestExpressions(unittest.TestCase):
+ def test_one_param_expression(self):
+ exp = rules.OneParamExpression(None, rules.ValueTerminal(None, "10"))
+ c = DictContext({})
+ self.assertEquals(exp.eval(c), 10)
+ exp = rules.OneParamExpression(None, rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 'Foo string'})
+ self.assertEquals(exp.eval(c), 'Foo string')
+
+ def test_neg_expression(self):
+ exp = rules.NegExpression(None, rules.ValueTerminal(None, "10"))
+ c = DictContext({})
+ self.assertEquals(exp.eval(c), -10)
+ exp = rules.NegExpression(None, rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 2})
+ self.assertEquals(exp.eval(c), -2)
+
+ def test_and_expression(self):
+ exp = rules.AndExpression(None, rules.ValueTerminal(None, True),
+ rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 1})
+ self.assertEquals(exp.eval(c), True)
+ c = DictContext({'foo' : 0})
+ self.assertEquals(exp.eval(c), False)
+ c = DictContext({'foo' : ""})
+ self.assertEquals(exp.eval(c), False)
+ c = DictContext({'foo' : False})
+ self.assertEquals(exp.eval(c), False)
+ c = DictContext({'foo' : True})
+ self.assertEquals(exp.eval(c), True)
+
+ def test_minus_expression(self):
+ exp = rules.MinusExpression(None, rules.ValueTerminal(None, "10"), rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 10})
+ self.assertEquals(exp.eval(c), 0)
+
+ def test_plus_expression(self):
+ exp = rules.PlusExpression(None, rules.ValueTerminal(None, "10"), rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 10})
+ self.assertEquals(exp.eval(c), 20)
+
+ def test_mul_expression(self):
+ exp = rules.MultiplyExpression(None, rules.ValueTerminal(None, "10"), rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 10})
+ self.assertEquals(exp.eval(c), 100)
+
+ def test_div_expression(self):
+ exp = rules.DivideExpression(None, rules.ValueTerminal(None, "10"), rules.ReferenceTerminal(None, "${foo}"))
+ c = DictContext({'foo' : 10})
+ self.assertEquals(exp.eval(c), 1)
+
+ def test_get_expressions_from_relation(self):
+ rel = rules.RequireRelation(None,"${foo} == True","${test} = 2 and ${aaa} == ${bbb}")
+ self.assertEquals(len(rel.get_expressions()), 11)
+
+ def test_get_refs_from_relation(self):
+ rel = rules.BaseRelation(None,"${foo} == True","${test} = 2 and ${aaa} == ${bbb}")
+ self.assertEquals(rel.get_refs(), ['foo'])
+
+ def test_set_expression(self):
+ exp = rules.SetExpression(None,rules.ReferenceTerminal(None, "${t}"), rules.ValueTerminal(None, "10"))
+ c = DictContext({'foo' : 10, 't' :None})
+ self.assertEquals(exp.eval(c), True)
+ self.assertEquals(c.data['t'], 10)
+
+ def test_set_expression_in_relation(self):
+ rel = rules.RequireRelation(None,"1","${test} = 1")
+ c = DictContext({'test' : None, 't' :None})
+ rel.execute(c)
+ self.assertEquals(c.data['test'], 1)
+ rel = rules.RequireRelation(None,"1","${test} = 2 and ${t} = 3")
+ rel.execute(c)
+ self.assertEquals(c.data['test'], 2)
+ self.assertEquals(c.data['t'], 3)
+
+ def test_set_expression_in_relation_and_get_set_elements(self):
+ rel = rules.RequireRelation(None,"1","${test} = 2")
+ self.assertEquals(rel.get_set_expressions()[0].left.get_ref(), 'test')
+
+ rel = rules.RequireRelation(None,"1","${test} = 2 and ${t} = 3")
+ self.assertEquals(len(rel.get_set_expressions()), 2)
+ self.assertEquals(rel.get_set_expressions()[0].left.get_ref(), 'test')
+ self.assertEquals(rel.get_set_expressions()[1].left.get_ref(), 't')
+
+ def test_set_expression_in_relation_and_get_refs(self):
+ rel = rules.RequireRelation(None,"${foo}","${test} = 2")
+ self.assertEquals(rel.get_refs(), ['foo'])
+ rel = rules.RequireRelation(None,"${foo}","${test} = 2 and ${t} = 3")
+ self.assertEquals(rel.get_refs(), ['foo'])
+
+ def test_set_expression_in_relation_and_get_set_refs(self):
+ rel = rules.RequireRelation(None,"1","${test} = 2")
+ self.assertEquals(rel.get_set_refs(), ['test'])
+
+ rel = rules.RequireRelation(None,"1","${test} = 2 and ${t} = 3")
+ self.assertEquals(rel.get_set_refs(),['test','t'])
+
+ def test_set_expression_in_relation_with_string(self):
+ rel = rules.RequireRelation(None,"1",'${test} = "foo "')
+ c = DictContext({'test' : None, 't' :None})
+ rel.execute(c)
+ self.assertEquals(c.data['test'], 'foo ')
+
+ def test_set_expression_in_relation_with_string_concat(self):
+ rel = rules.RequireRelation(None,"1",'${test} = "foo " + "bar"')
+ c = DictContext({'test' : None, 't' :None})
+ rel.execute(c)
+ self.assertEquals(c.data['test'], 'foo bar')
+
+ def test_set_expression_in_relation_with_ref_concat(self):
+ rel = rules.RequireRelation(None,"1",'${test} = ${s1} + " " + u"bar" + ${s2}')
+ c = DictContext({'test' : None, 's1' : 'test', 's2' : 'one'})
+ rel.execute(c)
+ self.assertEquals(c.data['test'], 'test barone')
+
+class TestRuleUtils(unittest.TestCase):
+ def test_is_str_literal(self):
+ self.assertEquals(rules.is_str_literal(1), False)
+ self.assertEquals(rules.is_str_literal([]), False)
+ self.assertEquals(rules.is_str_literal("foo"), False)
+ self.assertEquals(rules.is_str_literal("'foo'"), True)
+ self.assertEquals(rules.is_str_literal('foo'), False)
+ self.assertEquals(rules.is_str_literal('"foo bar"'), True)
+
+ def test_get_str_literal(self):
+ self.assertEquals(rules.get_str_literal(1), None)
+ self.assertEquals(rules.get_str_literal([]), None)
+ self.assertEquals(rules.get_str_literal("foo"), None)
+ self.assertEquals(rules.get_str_literal("'foo'"), 'foo')
+ self.assertEquals(rules.get_str_literal('foo'), None)
+ self.assertEquals(rules.get_str_literal('"foo bar"'), 'foo bar')
class TestASTInterpreter(unittest.TestCase):
def test_require(self):
- ip = ASTInterpreter('a excludes b require 0')
+ ip = rules.ASTInterpreter('a excludes b require 0')
ret = ip.eval()
def test_get_tokens(self):
- self.assertEquals(get_tokens("foo=(2+1) * 3"),['foo','=','(','2','+','1',')','*','3'])
- self.assertEquals(get_tokens("Arithmetic.MixedResult3 = (Arithmetic.Value2 / 2 + Arithmetic.Value1 * 9) - 7"),['Arithmetic.MixedResult3', '=', '(', 'Arithmetic.Value2', '/', '2', '+', 'Arithmetic.Value1', '*', '9', ')', '-', '7'])
- print get_tokens(multilines)
- self.assertEquals(len(get_tokens(multilines)),25)
+ self.assertEquals(rules.get_tokens("foo=(2+1) * 3"),['foo','=','(','2','+','1',')','*','3'])
+ self.assertEquals(rules.get_tokens("Arithmetic.MixedResult3 = (Arithmetic.Value2 / 2 + Arithmetic.Value1 * 9) - 7"),['Arithmetic.MixedResult3', '=', '(', 'Arithmetic.Value2', '/', '2', '+', 'Arithmetic.Value1', '*', '9', ')', '-', '7'])
+ self.assertEquals(len(rules.get_tokens(multilines)),25)
def test_get_unindented_multiline_tokens(self):
self.assertEquals(
- get_tokens("foo = 2+bar\nand foobar = 3 and\nfubar=4"),
+ rules.get_tokens("foo = 2+bar\nand foobar = 3 and\nfubar=4"),
['foo', '=', '2', '+', 'bar', 'and', 'foobar', '=', '3', 'and', 'fubar', '=', '4'])
def test_get_tab_separated_tokens(self):
self.assertEquals(
- get_tokens("foo\tconfigures\t\tbar\t=\t5"),
+ rules.get_tokens("foo\tconfigures\t\tbar\t=\t5"),
['foo', 'configures', 'bar', '=', '5'])
def test_get_unicode_tokens(self):
self.assertEquals(
- get_tokens(u'xÿz configures xzÿ = ÿxá'),
+ rules.get_tokens(u'xÿz configures xzÿ = ÿxá'),
[u'xÿz', 'configures', u'xzÿ', '=', u'ÿxá'])
def test_get_unicode_tokens_2(self):
self.assertEquals(
- get_tokens(u'ελληνικά configures ünicode = u"test string" + ελληνικά'),
+ rules.get_tokens(u'ελληνικά configures ünicode = u"test string" + ελληνικά'),
[u'ελληνικά', 'configures', u'ünicode', '=', 'u"test string"', '+', u'ελληνικά'])
def test_get_unicode_tokens_3(self):
self.assertEquals(
- get_tokens(u'oöoä äöoö oöo öoö äaäa'),
+ rules.get_tokens(u'oöoä äöoö oöo öoö äaäa'),
[u'oöoä', u'äöoö', u'oöo', u'öoö', u'äaäa'])
def test_get_unicode_tokens_4(self):
self.assertEquals(
- get_tokens(u'ünicode.rêf1 require rêf2 . ελληνικά'),
+ rules.get_tokens(u'ünicode.rêf1 require rêf2 . ελληνικά'),
[u'ünicode.rêf1', u'require', u'rêf2.ελληνικά'])
def test_get_unicode_tokens_multiline(self):
@@ -201,7 +344,7 @@
u'xÿz', 'configures', u'xzÿ', '=', u'ÿxá',
u'ελληνικά', 'configures', u'ünicode', '=', 'u"test string"', '+', u'ελληνικά',
]
- actual = get_tokens(tokenstr)
+ actual = rules.get_tokens(tokenstr)
self.assertEquals(actual, expected, '\n%r \n!= \n%r' % (actual, expected))
def test_multiline_string(self):
@@ -212,30 +355,30 @@
"""
'''
expected = ['"""\ntes-\nti\n"""']
- self.assertEquals(get_tokens(tokenstr), expected)
+ self.assertEquals(rules.get_tokens(tokenstr), expected)
def test_syntax_error(self):
try:
- ip = ASTInterpreter('a and and')
+ ip = rules.ASTInterpreter('a and and')
self.assertTrue(False)
- except ParseException:
+ except rules.ParseException:
self.assertTrue(True)
def test_empty_expression(self):
expression = ''
- ip = ASTInterpreter(expression)
+ ip = rules.ASTInterpreter(expression)
result = ip.eval()
self.assertFalse(result)
def test_no_expression(self):
- ip = ASTInterpreter()
+ ip = rules.ASTInterpreter()
result = ip.eval()
self.assertFalse(result)
try:
ip.create_ast(None)
self.assertFalse(True)
- except ParseException:
+ except rules.ParseException:
self.assertTrue(True)
ip.create_ast('1 and 1')
@@ -243,7 +386,7 @@
self.assertTrue(result)
def test_one_param_ops(self):
- ip = ASTInterpreter('1 and truth 1')
+ ip = rules.ASTInterpreter('1 and truth 1')
result = ip.eval()
self.assertTrue(result)
@@ -257,18 +400,24 @@
def test_infix_to_postfix(self):
expression = '1 and not 1'
- ip = ASTInterpreter(expression)
+ ip = rules.ASTInterpreter(expression)
self.assertEqual(ip.postfix_array, ['1', '1', 'not', 'and'])
self.assertFalse(ip.eval())
+ def test_infix_to_postfix_with_minus(self):
+ expression = '1 - 1'
+ ip = rules.ASTInterpreter(expression)
+ self.assertEqual(ip.postfix_array, ['1', '1', '-'])
+ self.assertFalse(ip.eval())
+
def test_infix_to_postfix_pars(self):
expression = '1 and ( 0 or 1 and 1 )'
- ip = ASTInterpreter(expression)
+ ip = rules.ASTInterpreter(expression)
self.assertEqual(ip.postfix_array, ['1', '0', '1', 'or', '1', 'and', 'and'])
self.assertTrue(ip.eval())
def test_not(self):
- ip = ASTInterpreter(u'not 1',)
+ ip = rules.ASTInterpreter(u'not 1',)
ret = ip.eval()
self.assertFalse(ret)
@@ -281,7 +430,7 @@
self.assertFalse(ret)
def test_not_with_multiple(self):
- ip = ASTInterpreter(u'1 and not 0')
+ ip = rules.ASTInterpreter(u'1 and not 0')
ret = ip.eval()
self.assertTrue(ret)
ip.create_ast(u'1 and not 1')
@@ -289,7 +438,7 @@
self.assertFalse(ret)
def test_and(self):
- ip = ASTInterpreter(u'1 and 1 and 0')
+ ip = rules.ASTInterpreter(u'1 and 1 and 0')
ret = ip.eval()
self.assertFalse(ret)
@@ -298,7 +447,7 @@
self.assertTrue(ret)
def test_nand(self):
- ip = ASTInterpreter(u'1 nand 1 nand 1')
+ ip = rules.ASTInterpreter(u'1 nand 1 nand 1')
ret = ip.eval()
self.assertTrue(ret)
@@ -315,7 +464,7 @@
self.assertTrue(ret)
def test_or(self):
- ip = ASTInterpreter(u'1 or 1 or 0')
+ ip = rules.ASTInterpreter(u'1 or 1 or 0')
ret = ip.eval()
self.assertTrue(ret)
@@ -325,7 +474,7 @@
and the rule evaluation should fail, the exclude rule should
evaluate if PostfixRuleEngine.eval(expression) -> return False
"""
- ip = ASTInterpreter(u'1 or 1 or 1')
+ ip = rules.ASTInterpreter(u'1 or 1 or 1')
ret = ip.eval()
self.assertTrue(ret)
@@ -354,7 +503,7 @@
self.assertFalse(ret)
def test_nor(self):
- ip = ASTInterpreter(u'1 nor 1 nor 1')
+ ip = rules.ASTInterpreter(u'1 nor 1 nor 1')
ret = ip.eval()
self.assertFalse(ret)
@@ -372,7 +521,7 @@
def test_xor(self):
- ip = ASTInterpreter(u'1 xor 1')
+ ip = rules.ASTInterpreter(u'1 xor 1')
ret = ip.eval()
self.assertFalse(ret)
@@ -381,7 +530,7 @@
self.assertTrue(ret)
def test_eq_cmp(self):
- ip = ASTInterpreter(u'1 == 0')
+ ip = rules.ASTInterpreter(u'1 == 0')
ret = ip.eval()
self.assertFalse(ret)
@@ -398,7 +547,7 @@
self.assertFalse(ret)
def test_neq_cmp(self):
- ip = ASTInterpreter(u'1 != 1')
+ ip = rules.ASTInterpreter(u'1 != 1')
ret = ip.eval()
self.assertFalse(ret)
@@ -407,15 +556,15 @@
self.assertTrue(ret)
def test_lt_cmp(self):
- ip = ASTInterpreter(u'0 < 1')
+ ip = rules.ASTInterpreter(u'0 < 1')
ret = ip.eval()
self.assertTrue(ret)
- ip.create_ast(u'-1 < 1')
+ ip.create_ast(u'0-1 < 1')
ret = ip.eval()
self.assertTrue(ret)
- ip.create_ast(u'-1 < -2')
+ ip.create_ast(u'0-1 < 0-2')
ret = ip.eval()
self.assertFalse(ret)
@@ -424,7 +573,7 @@
self.assertFalse(ret)
def test_gt_cmp(self):
- ip = ASTInterpreter(u'0 > -1')
+ ip = rules.ASTInterpreter(u'0 > 0-1')
ret = ip.eval()
self.assertTrue(ret)
@@ -436,12 +585,12 @@
ret = ip.eval()
self.assertFalse(ret)
- ip.create_ast(u'-1 > 1')
+ ip.create_ast(u'0-1 > 1')
ret = ip.eval()
self.assertFalse(ret)
def test_lte_cmp(self):
- ip = ASTInterpreter(u'0 <= 1')
+ ip = rules.ASTInterpreter(u'0 <= 1')
ret = ip.eval()
self.assertTrue(ret)
@@ -454,7 +603,7 @@
self.assertFalse(ret)
def test_gte_cmp(self):
- ip = ASTInterpreter(u'1 >= 0')
+ ip = rules.ASTInterpreter(u'1 >= 0')
ret = ip.eval()
self.assertTrue(ret)
@@ -465,9 +614,9 @@
ip.create_ast(u'0 >= 1')
ret = ip.eval()
self.assertFalse(ret)
-
+
def test_extract_refs(self):
- refs = ASTInterpreter.extract_refs('a.a and ( b.c and d.e )')
+ refs = rules.ASTInterpreter.extract_refs('${a.a} and ( ${b.c} and ${d.e} )')
self.assertTrue('a.a' in refs)
self.assertTrue('b.c' in refs)
self.assertTrue('d.e' in refs)
@@ -476,7 +625,7 @@
def test_one_of(self):
""" Test for showing that relation one-of is basically "LEFT and R1 xor R2"
"""
- ip = ASTInterpreter(u'1 and 1 and 1 xor 0')
+ ip = rules.ASTInterpreter(u'1 and 1 and 1 xor 0')
ret = ip.eval()
self.assertTrue(ret)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_rules_on_configuration.py
--- a/configurationengine/source/cone/public/tests/unittest_rules_on_configuration.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_rules_on_configuration.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,33 +14,28 @@
# Description:
#
-import operator as ops
import unittest
-import sys, os
-import __init__
-import tokenize
-import StringIO
-from cone.public import api,exceptions, utils
-from cone.public.rules import ASTInterpreter, RelationContainerImpl
-from cone.public.rules import ParseException, DefaultContext, BaseRelation
+from cone.public import api,exceptions, plugin
+from cone.public.rules import RelationContainerImpl
+from cone.public.rules import DefaultContext, BaseRelation
from cone.public import rules
#### TEST RELATIONS ####
-AA_BA = 'a.a == "foo" requires b.b != 0'
-AB_BB = 'a.b configures b.b = a.b+":"+ "test"'
-BA_CA = 'b.a requires c.a and c.b and a.b'
+AA_BA = '${a.a} == "foo" requires ${b.b} != 0'
+AB_BB = '${a.b} configures ${b.b} = ${a.b}+":"+ "test"'
+BA_CA = '${b.a} requires ${c.a} and ${c.b} and ${a.b}'
-CB_DA = 'c.b requires d.a'
-DA_DB = 'd.a requires d.b'
+CB_DA = '${c.b} requires ${d.a}'
+DA_DB = '${d.a} requires ${d.b}'
-AC_AB_BA = 'a.c and a.a requires b.a'
+AC_AB_BA = '${a.c} and ${a.a} requires ${b.a}'
-EA_FSTAR = 'e.a requires f.*'
+EA_FSTAR = '${e.a} requires ${f.*}'
TEST_RELATIONS = {
- 'a.a' : [AA_BA, 'a.a == "test" requires b.a'],
+ 'a.a' : [AA_BA, '${a.a} == "test" requires ${b.a}'],
'a.b' : [AB_BB],
'a.c' : [AC_AB_BA],
'b.a' : [BA_CA],
@@ -132,27 +127,40 @@
return eval(expression)
except (NameError,SyntaxError), e:
return expression
-
+
+ def convert_value(self, value):
+ try:
+ # Handle some special literals
+ if value == 'true': return True
+ if value == 'false': return False
+ if value == 'none': return None
+
+ # Values can be any Python literals, so eval() the string to
+ # get the value
+ return eval(value)
+ except Exception:
+ raise RuntimeError("Could not evaluate '%s'" % value)
+
def eval(self, ast, expression, value):
#print "expression %s = %s" % (expression,value)
pass
class ConfigurationBaseRelation(BaseRelation):
def __init__(self, data, left, right):
- self.context = ConfigurationContext(data)
+ self.context = None
super(ConfigurationBaseRelation, self).__init__(data, left, right)
class RequireRelation(ConfigurationBaseRelation):
KEY = 'requires'
def __init__(self, data, left, right):
super(RequireRelation, self).__init__(data, left, right)
- self.context = ConfigurationContext(data)
+ self.context = None
class ConfigureRelation(ConfigurationBaseRelation):
KEY = 'configures'
def __init__(self, data, left, right):
super(ConfigureRelation, self).__init__(data, left, right)
- self.context = ConfigurationContext(data)
+ self.context = None
def handle_configure(self, left, right):
if left and right:
@@ -169,8 +177,8 @@
KEY = 'configures'
OP = handle_configure
- def eval(self, context):
- super(ConfigureExpression, self).eval(context)
+ def eval(self, context, **kwargs):
+ super(ConfigureExpression, self).eval(context, **kwargs)
if not self.value:
left_keys = []
for ref in self.ast.extract_refs(str(self.left)):
@@ -193,20 +201,6 @@
KEY= '+'
OP = handle_plus
-
-class SetExpression(rules.TwoOperatorExpression):
- PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS']
- KEY= '='
- OP = handle_set
-
- def eval(self, context):
- try:
- variable = context.data.get_feature(self.left.expression)
- variable.set_value(self.right.eval(context))
- return True
- except exceptions.NotFound:
- return False
-
class TestRelations(unittest.TestCase):
def setUp(self):
@@ -223,7 +217,6 @@
rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
rules.OPERATORS[ConcatExpression.KEY] = ConcatExpression
- rules.OPERATORS[SetExpression.KEY] = SetExpression
def tearDown(self):
rules.RELATIONS = self.RELATIONS_BACKUP
@@ -237,15 +230,6 @@
rels = factory.get_relations_for(self.configuration, 'a.a')
ret= rels.execute()
self.assertTrue(ret)
-
- def test_has_ref(self):
- """
- Tests the relation and relation container
- """
- factory = TestFactory()
- rels = factory.get_relations_for(self.configuration, 'a.a')
- ret= rels.execute()
- self.assertTrue(ret)
def test_not_has_ref(self):
factory = TestFactory()
@@ -257,7 +241,8 @@
def test_not_has_ref_in_container(self):
factory = TestFactory()
rels = factory.get_relations_for(self.configuration, 'c.b')
- ret = rels.execute()
+ context = plugin.GenerationContext(configuration=self.configuration)
+ ret = rels.execute(context)
self.assertFalse(ret)
def test_two_on_the_left(self):
@@ -269,9 +254,16 @@
def test_configure_right_side(self):
factory = TestFactory()
rels = factory.get_relations_for(self.configuration, 'a.b')
- ret = rels.execute()
+ context = plugin.GenerationContext(configuration=self.configuration)
+ ret = rels.execute(context)
self.assertTrue(ret)
self.assertEquals(self.configuration.get_default_view().get_feature('b.b').get_value(),'hey:test')
+ def test_get_refs_from_relation(self):
+ factory = TestFactory()
+ rels = factory.get_relations_for(self.configuration, 'a.b')
+ self.assertEquals(rels.value_list[0].get_refs(), [u'a.b'])
+ self.assertEquals(rels.value_list[0].get_set_refs(), [u'b.b'])
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_rules_simplecondition.py
--- a/configurationengine/source/cone/public/tests/unittest_rules_simplecondition.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_rules_simplecondition.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,11 +18,13 @@
import os
import re
import logging
-import __init__
+
from cone.public import *
+from cone.public.rules import DefaultContext, ASTInterpreter
+from cone.confml import model
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-class TestContext(object):
+class TestContext(DefaultContext):
""" DefaultContext implements ConE specific context for handling rules
"""
def __init__(self, data):
@@ -39,23 +41,14 @@
pass
def handle_terminal(self, expression):
- try:
- m = re.match("\${(.*)}", expression)
- if m:
- return self.data[m.group(1)]
- elif expression in ['true','1','True']:
- return True
- elif expression in ['false','0','False']:
- return False
- else:
- return eval(expression)
- except:
- return expression
+ return self.data[expression]
class TestPluginCondition(unittest.TestCase):
def test_create_plugin_condition(self):
- condition = rules.SimpleCondition("foo.bar", "True")
+ condition = rules.SimpleCondition("${foo.bar}", "True")
+ self.assertTrue(isinstance(condition.left, rules.ReferenceTerminal))
+ self.assertEquals(str(condition),'(${foo.bar} => None) == True')
def test_create_plugin_and_eval_booleans(self):
context = TestContext(None)
@@ -63,6 +56,235 @@
self.assertTrue(condition.eval(context))
condition = rules.SimpleCondition("0", True)
self.assertFalse(condition.eval(context))
+
+ def test_create_plugin_and_eval_none(self):
+ context = TestContext(None)
+ condition = rules.SimpleCondition("None", "None")
+ self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition("None", None)
+ self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition(None, "None")
+ self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition(None, None)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("True", None)
+ self.assertFalse(condition.eval(context))
+ condition = rules.SimpleCondition(None, "True")
+ self.assertFalse(condition.eval(context))
+
+ def test_create_plugin_and_eval_none_from_ref(self):
+ context = TestContext({'Foo.Bar': None})
+ condition = rules.SimpleCondition("${Foo.Bar}", None)
+ self.assertTrue(condition.eval(context))
+
+ def test_create_plugin_and_eval_unicode(self):
+ context = TestContext({'Foo.Bar': u"foo\u20ac"})
+ condition = rules.SimpleCondition("${Foo.Bar}", u"foo\u20ac")
+ self.assertTrue(condition.eval(context))
+
+ def test_create_plugin_and_eval_number_against_string(self):
+ context = TestContext({'Foo.Int': 123,
+ 'Foo.Real': 123.4})
+ condition = rules.SimpleCondition("${Foo.Int}", "foo")
+ self.assertFalse(condition.eval(context))
+ condition = rules.SimpleCondition("${Foo.Real}", "foo")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${Foo.Int}", "123")
+ self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition("${Foo.Real}", "123.4")
+ self.assertTrue(condition.eval(context))
+
+ def xtest_selection_setting(self):
+ conf = api.Configuration("test.confml", namespace="com.nokia.s60")
+
+ context = TestContext(None)
+ context.configuration = conf
+ fea= api.Feature("foo")
+ fea.add_feature(api.Feature("child1",type='selection'))
+ fea.child1.create_option('one','1')
+ fea.child1.create_option('two','2')
+
+ conf.add_feature(fea)
+
+ fea.child1.add_data(api.Data(value="2"))
+
+ condition = rules.SimpleCondition("${fea.child1}", "2")
+ self.assertTrue(condition.eval(context))
+
+ def test_sequence_setting(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ fea = model.ConfmlSequenceSetting("test")
+ fea.add_feature(model.ConfmlIntSetting('child1'))
+ fea.add_feature(model.ConfmlIntSetting('child2'))
+ fea.add_feature(model.ConfmlIntSetting('child3'))
+ context.configuration.add_feature(fea)
+ seq = context.configuration.get_default_view().get_feature('test')
+ seq.add_sequence(['1','2','3'])
+ seq.add_sequence(['4','5','6'])
+ seq.add_sequence(['7','8','9'])
+
+ condition = rules.SimpleCondition("${test}", [[1,2,3], [4,5,6], [7,8,9]])
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", [['11','22','33'], ['44','55','66'], ['77','88','99']])
+ self.assertFalse(condition.eval(context))
+
+ def test_boolean_setting(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlBooleanSetting("test"))
+
+ context.configuration.get_default_view().test.value = True
+
+ condition = rules.SimpleCondition("${test}", True)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "zoobar")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "1")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "true")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "0")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", None)
+ self.assertFalse(condition.eval(context))
+
+ def test_string_setting(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlStringSetting("test"))
+
+ context.configuration.get_default_view().test.value = "foobar"
+
+ condition = rules.SimpleCondition("${test}", "foobar")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "zoobar")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "1")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "true")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "false")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "0")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", None)
+ self.assertFalse(condition.eval(context))
+
+ def test_int_setting(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlIntSetting("test"))
+
+ context.configuration.get_default_view().test.value = "1"
+
+ condition = rules.SimpleCondition("${test}", "1")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", 2)
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", True)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", False)
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", 0)
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "zoobar")
+ try:
+ self.assertFalse(condition.eval(context))
+ self.fail("Exception expected.")
+ except Exception:
+ pass
+
+ condition = rules.SimpleCondition("${test}", "")
+ try:
+ self.assertFalse(condition.eval(context))
+ self.fail("Exception expected.")
+ except Exception:
+ pass
+
+ condition = rules.SimpleCondition("${test}", None)
+ self.assertFalse(condition.eval(context))
+
+ context.configuration.get_default_view().test.value = "-1"
+
+ condition = rules.SimpleCondition("${test}", -1)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", 0)
+ self.assertFalse(condition.eval(context))
+
+ def test_selection_setting_true(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlSelectionSetting("test"))
+
+ context.configuration.get_default_view().test.value = "True"
+
+ condition = rules.SimpleCondition("${test}", "True")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", True)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "1")
+ self.assertFalse(condition.eval(context))
+
+ def test_selection_setting_false(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlSelectionSetting("test"))
+
+ context.configuration.get_default_view().test.value = "False"
+
+ condition = rules.SimpleCondition("${test}", False)
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "False")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", "0")
+ self.assertFalse(condition.eval(context))
+
+ condition = rules.SimpleCondition("False", "0")
+ self.assertFalse(condition.eval(context))
+
+ def test_selection_setting_int(self):
+ context = plugin.GenerationContext()
+ context.configuration = api.Configuration()
+ context.configuration.add_feature(model.ConfmlSelectionSetting("test"))
+
+ context.configuration.get_default_view().test.value = "2"
+
+ condition = rules.SimpleCondition("${test}", "2")
+ self.assertTrue(condition.eval(context))
+
+ condition = rules.SimpleCondition("${test}", 2)
+ self.assertTrue(condition.eval(context))
def test_create_plugin_and_eval_integers(self):
context = TestContext(None)
@@ -72,8 +294,12 @@
self.assertFalse(condition.eval(context))
condition = rules.SimpleCondition("2", "2")
self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition("2", 2)
+ self.assertTrue(condition.eval(context))
condition = rules.SimpleCondition(2, 2)
self.assertTrue(condition.eval(context))
+ condition = rules.SimpleCondition("-2", -2)
+ self.assertTrue(condition.eval(context))
def test_create_plugin_and_eval_string(self):
context = TestContext(None)
@@ -87,6 +313,7 @@
def test_create_plugin_and_eval_data_reference(self):
context = TestContext({'test' : 1, 'foo' : 2, 'bar' : True})
condition = rules.SimpleCondition("${test}", 1)
+ condition.eval(context)
self.assertTrue(condition.eval(context))
condition = rules.SimpleCondition("${test}", False)
self.assertFalse(condition.eval(context))
@@ -104,6 +331,7 @@
condition = rules.SimpleCondition("${test}", None)
self.assertTrue(condition.eval(context))
condition = rules.SimpleCondition("${test.stringsub}", "None")
+ condition.eval(context)
self.assertTrue(condition.eval(context))
condition = rules.SimpleCondition("${test.intsub}", "None")
self.assertTrue(condition.eval(context))
@@ -131,3 +359,6 @@
self.fail("access of non existing elements succeds?")
except:
pass
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_settings.py
--- a/configurationengine/source/cone/public/tests/unittest_settings.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_settings.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,7 +21,6 @@
import string
import StringIO
import sys,os
-import __init__
from cone.public import api,exceptions,settings
@@ -76,13 +75,13 @@
settings.SettingsFactory.defaultconfig = os.path.join(ROOT_PATH,'test_defaults.cfg')
s = settings.SettingsFactory.cone_parser()
cs = settings.ConeSettings(s)
- self.assertEquals(s.get('DEFAULT','output'),'output//')
+ self.assertEquals(s.get('DEFAULT','output'),'//')
def test_cone_settings(self):
settings.SettingsFactory.defaultconfig = os.path.join(ROOT_PATH,'test_defaults.cfg')
s = settings.SettingsFactory.cone_parser()
cs = settings.ConeSettings(s)
- self.assertEquals(cs.get('output'),'output//')
+ self.assertEquals(cs.get('output'),'//')
self.assertEquals(cs.get('foobar'),None)
self.assertEquals(cs.get('foobar', 'test'),'test')
@@ -91,11 +90,11 @@
settings.SettingsFactory.configsettings = None
s = settings.SettingsFactory.cone_parser()
cs = settings.ConeSettings(s,'FOOBAR')
- self.assertEquals(cs.get('output'),'output//')
+ self.assertEquals(cs.get('output'),'//')
self.assertEquals(cs.get('foobar'),None)
self.assertEquals(cs.get('foobar', 'test'),'test')
self.assertEquals(cs.get('output','',{'output_subdir':'content',
- 'output_subdir':'content'}),'output/content/')
+ 'output_subdir':'content'}),'/content/')
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_storage.py
--- a/configurationengine/source/cone/public/tests/unittest_storage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_storage.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,7 +21,6 @@
import string
import sys,os
import pickle
-import __init__
from cone.public import api, exceptions, utils
@@ -177,7 +176,7 @@
res1.close()
res1 = store.open_resource("test/foo.txt","w")
res1.close()
- self.assertEquals(store.list_resources('', True),['test/foo.txt'])
+ self.assertEquals(store.list_resources('', recurse=True),['test/foo.txt'])
def test_open_many(self):
store = api.Storage.open(storage_path,"w")
@@ -206,7 +205,7 @@
self.assertEquals(store.list_resources('/'), ['root.txt'])
self.assertEquals(store.list_resources('/test'), ['test/bar.txt',
'test/foo.txt'])
- self.assertEquals(store.list_resources('/',True), ['root.txt',
+ self.assertEquals(store.list_resources('/',recurse=True), ['root.txt',
'test/bar.txt',
'test/foo.txt'])
@@ -367,7 +366,7 @@
res.close()
self.assertEquals(store.list_resources(""), ["foo.txt"])
store.set_current_path("/")
- self.assertEquals(store.list_resources("", True), ["subdir/foo.txt"])
+ self.assertEquals(store.list_resources("", recurse=True), ["subdir/foo.txt"])
store.close()
os.unlink(temp_file)
@@ -406,8 +405,8 @@
res = layer.open_resource("confml/test.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(layer.list_resources("", True),["confml/test.confml"])
- self.assertEquals(store.list_resources("", True),["foo/confml/test.confml"])
+ self.assertEquals(layer.list_resources("", recurse=True),["confml/test.confml"])
+ self.assertEquals(store.list_resources("", recurse=True),["foo/confml/test.confml"])
def test_create_two_layers_and_open_resource(self):
store = api.Storage.open(storage_path,"w")
@@ -421,12 +420,15 @@
res = bar_layer.open_resource("confml/root.confml","w")
res.write("foo.conf")
res.close()
- self.assertEquals(foo_layer.list_resources("", True),['confml/test.confml', 'root.confml'])
- self.assertEquals(store.list_resources("", True),['bar/confml/root.confml','foo/confml/test.confml','foo/root.confml'])
+ self.assertEquals(foo_layer.list_resources("", recurse=True),['root.confml', 'confml/test.confml'])
+ self.assertEquals(store.list_resources("", recurse=True),['bar/confml/root.confml',
+ 'foo/root.confml',
+ 'foo/confml/test.confml'])
foo_layer.delete_resource("confml/test.confml")
- self.assertEquals(foo_layer.list_resources("", True),["root.confml"])
- self.assertEquals(store.list_resources("", True),["bar/confml/root.confml","foo/root.confml"])
+ self.assertEquals(foo_layer.list_resources("", recurse=True),["root.confml"])
+ self.assertEquals(store.list_resources("", recurse=True),["bar/confml/root.confml",
+ "foo/root.confml"])
if __name__ == '__main__':
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/tests/unittest_utils.py
--- a/configurationengine/source/cone/public/tests/unittest_utils.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/public/tests/unittest_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,14 +20,11 @@
Test the CPF root file parsing routines
"""
-import zipfile
import unittest
-import string
-import token
-import sys,os,re
-import __init__
+import StringIO
+import os,re
-from cone.public import utils, rules, api, exceptions
+from cone.public import utils, api, exceptions
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
testdata = os.path.abspath(os.path.join(ROOT_PATH,'utils-testdata'))
@@ -78,7 +75,7 @@
filtered = utils.resourceref.filter_resources(['test.txt','foo.dat','teat/data/bar.confml'],".*\.dat")
self.assertEquals(filtered[0],'foo.dat')
- def test_neg_filter_resources(self):
+ def test_neg_filter_resources2(self):
filtered = utils.resourceref.neg_filter_resources(['/test/.svn/test.txt','.svn/test/foo.dat','teat/data/bar.confml'],"\.svn")
self.assertEquals(filtered[0],'teat/data/bar.confml')
@@ -138,7 +135,7 @@
self.assertEquals(utils.resourceref.norm('./skeleton.txt'),
'skeleton.txt')
- def test_norm_ref_with_begin_dot(self):
+ def test_norm_ref_with_begin_dot2(self):
self.assertEquals(utils.resourceref.norm('.svn'),
'.svn')
@@ -275,9 +272,6 @@
def test_to_objref_dotted_start(self):
self.assertEquals(utils.resourceref.to_objref('../foo/bar/test.confml'),'____foo__bar__test_confml')
- def test_to_objref_dot_in_name_start(self):
- self.assertEquals(utils.resourceref.to_objref('/foo.bar/test.confml'),'_foo_bar_test_confml')
-
def test_to_objref_number_in_name_start(self):
self.assertEquals(utils.resourceref.to_objref('_1.0.test_one'),'_1_0_test_one')
self.assertEquals(utils.resourceref.to_objref('0.test_one'),'_0_test_one')
@@ -293,6 +287,13 @@
def test_to_objref_dot_in_name_start(self):
self.assertEquals(utils.resourceref.to_objref('/foo.bar/test.confml'),'__foo_bar__test_confml')
+ def test_to_objref_with_python_comment(self):
+ ##STRATEGIC## Customization offering for ##PROD_CODE##
+ self.assertEquals(utils.resourceref.to_objref('##STRATEGIC## Customization offering for ##PROD_CODE##'),
+ '__STRATEGIC__Customizationofferingfor__PROD_CODE__')
+ self.assertEquals(utils.resourceref.to_objref('Feature A ## Testing ##'),
+ 'FeatureA__Testing__')
+
def test_to_hash_dotted_start(self):
self.assertEquals(utils.resourceref.to_hash('../foo/bar/test.confml'),'0x5a063087')
self.assertEquals(utils.resourceref.to_hash('../foo/bar/test.confml'),'0x5a063087')
@@ -312,11 +313,17 @@
def test_to_dref_from_dotted(self):
self.assertEquals(utils.resourceref.to_dref('fii.faa.foo'),'fii.faa')
+ def test_is_path(self):
+ self.assertEquals(utils.resourceref.is_path('foo'),False)
+ self.assertEquals(utils.resourceref.is_path('foo.txt'),True)
+ self.assertEquals(utils.resourceref.is_path('bar/foo'),True)
+ self.assertEquals(utils.resourceref.is_path('bar/foo.txt'),True)
+
class TestUtils(unittest.TestCase):
def test_distinct_array_with_single_values(self):
self.assertEquals(utils.distinct_array(['1','2','1','1']),['1','2'])
- def test_distinct_array_with_single_values(self):
+ def test_distinct_array_with_single_values2(self):
self.assertEquals(utils.distinct_array(['1','2','3','1','2','4']),['1','2','3','4'])
def test_list_files_from_testdata(self):
@@ -337,7 +344,7 @@
def test_pathmatch_with_star(self):
self.assertEquals(utils.pathmatch('test.foo.*','test.foo.bar'),True)
- def test_pathmatch_with_star(self):
+ def test_pathmatch_with_star2(self):
self.assertEquals(utils.pathmatch('test.foo.*','test.foo.bar.fiba'),False)
def test_pathmatch_with_twostar(self):
@@ -368,6 +375,28 @@
filters.append(lambda x: isinstance(x,F))
self.assertEquals(utils.filter(obj,filters),False)
+ def test_is_float(self):
+ self.assertEquals(utils.is_float(-10), False)
+ self.assertEquals(utils.is_float(0), False)
+ self.assertEquals(utils.is_float(1), False)
+ self.assertEquals(utils.is_float(10), False)
+ self.assertEquals(utils.is_float(212), False)
+ self.assertEquals(utils.is_float('-10'), False)
+ self.assertEquals(utils.is_float('0'), False)
+ self.assertEquals(utils.is_float('1'), False)
+ self.assertEquals(utils.is_float('10'), False)
+ self.assertEquals(utils.is_float('212'), False)
+ self.assertEquals(utils.is_float(-10.1), True)
+ self.assertEquals(utils.is_float(0.1), True)
+ self.assertEquals(utils.is_float(1.1), True)
+ self.assertEquals(utils.is_float(10.1), True)
+ self.assertEquals(utils.is_float(212.1), True)
+ self.assertEquals(utils.is_float('-10.1'), True)
+ self.assertEquals(utils.is_float('0.00001'), True)
+ self.assertEquals(utils.is_float('1.1231'), True)
+ self.assertEquals(utils.is_float('10.000000001'), True)
+ self.assertEquals(utils.is_float('212.1'), True)
+
class TestDottedRefs(unittest.TestCase):
def test_join_two_refs(self):
self.assertEquals(utils.dottedref.join_refs(['foo.bar.test','fancy.ref']),'foo.bar.test.fancy.ref')
@@ -544,6 +573,23 @@
default_value_for_missing = 'giraffe')
self.assertEquals(result, "The quick brown giraffe jumps over the lazy dog.")
+ def test_has_wildcard(self):
+ self.assertEquals(utils.dottedref.has_wildcard('fii.*'),True)
+ self.assertEquals(utils.dottedref.has_wildcard('fii.faa'),False)
+ self.assertEquals(utils.dottedref.has_wildcard('fii.faa.*'),True)
+ self.assertEquals(utils.dottedref.has_wildcard('fii.faa.**'),True)
+ self.assertEquals(utils.dottedref.has_wildcard('fii.faa.foo'),False)
+ self.assertEquals(utils.dottedref.has_wildcard('fii.*.faa'),True)
+ self.assertEquals(utils.dottedref.has_wildcard('*'),True)
+
+ def test_get_wildcard_prefix(self):
+ self.assertEquals(utils.dottedref.get_static_ref('fii.*'),'fii')
+ self.assertEquals(utils.dottedref.get_static_ref('fii.faa'),'fii.faa')
+ self.assertEquals(utils.dottedref.get_static_ref('fii.faa.*'),'fii.faa')
+ self.assertEquals(utils.dottedref.get_static_ref('fii.faa.**'),'fii.faa')
+ self.assertEquals(utils.dottedref.get_static_ref('fii.faa.foo'),'fii.faa.foo')
+ self.assertEquals(utils.dottedref.get_static_ref('fii.*.faa'),'fii')
+ self.assertEquals(utils.dottedref.get_static_ref('*'),'')
class TestUtilsSubclasses(unittest.TestCase):
@@ -564,21 +610,6 @@
classnames = utils.all_subclasses(base)
self.assertEquals(len(classnames),4)
-class TestUtilsDataMapRef(unittest.TestCase):
-
- def setUp(self):
- pass
-
- def test_get_feature_ref(self):
- map = "foo/bar[@key='key 1']"
- ref = utils.DataMapRef.get_feature_ref(map)
- self.assertEquals(ref,'foo/bar')
-
- def test_get_key_value(self):
- map = "foo/bar[@key='key 1']"
- value = utils.DataMapRef.get_key_value(map)
- self.assertEquals(value,'key 1')
-
class TestMakeList(unittest.TestCase):
def test_get_list_string(self):
@@ -638,6 +669,116 @@
utils.xml.split_tag_namespace("{http://www.test.com/xml/1}test"),
('http://www.test.com/xml/1', 'test'))
+
+ def test_get_xml_root_without_namespace_1(self):
+ resource = StringIO.StringIO("""
+
+
+
+
+ testing
+ """)
+ namespace, name = utils.xml.get_xml_root(resource)
+ self.assertEquals(namespace, 'http://www.test.com/xml/1')
+ self.assertEquals(name, 'root')
+
+ def test_get_xml_root_with_namespace_2(self):
+ resource = StringIO.StringIO("""
+
+
+ testing
+ """.encode('utf-16'))
+ namespace, name = utils.xml.get_xml_root(resource)
+ self.assertEquals(namespace, 'http://www.test.com/xml/1')
+ self.assertEquals(name, 'root')
+
+ def test_get_xml_root_with_namespace_3(self):
+ resource = StringIO.StringIO("""
+ """)
+ namespace, name = utils.xml.get_xml_root(resource)
+ self.assertEquals(namespace, 'http://www.s60.com/xml/confml/2')
+ self.assertEquals(name, 'configuration')
+
+ def test_get_xml_root_invalid_xml_1(self):
+ resource = StringIO.StringIO("""
+ confml
+ 1. get file name
+ @return: a reference. E.g. (foo/test.confml) => test.confml
"""
return ref.rsplit('/', 1)[-1]
@classmethod
def get_path(cls, ref):
"""
- get file name part from ref
- 1. get file extension
- @return: a reference. E.g. (foo/test.confml) => confml
+ get path part from ref
+ 1. get path from ref
+ @return: a reference. E.g. (foo/test.confml) => foo
"""
if len(ref.rsplit('/', 1)) == 2:
return ref.rsplit('/', 1)[0]
@@ -232,6 +235,9 @@
@return: a dotted reference. E.g. (foo/test.confml) => foo_test
"""
ref = ref.replace('/', '__')
+ # Change the python comment character also as underscore so that the tokenizer
+ # does not leave anything out
+ ref = ref.replace('#', '_')
newref = ''
first_token = True
try:
@@ -274,6 +280,16 @@
"""
return "%s" % hex(hash(ref))
+ @classmethod
+ def is_path(cls, ref):
+ """
+ returns true if the ref seems like a path
+ @return: Boolean value [True|False]
+ """
+ if cls.get_ext(ref) or cls.get_path(ref):
+ return True
+ return False
+
class dottedref(object):
"""
Class container for set of dotted reference related functions
@@ -378,6 +394,28 @@
elems.append(refelem.replace("*","[^\.]*"))
return "\\.".join(elems)+"$"
+ @classmethod
+ def has_wildcard(cls, ref):
+ """
+ Tests if the ref has any wildcards '*' in it.
+ @return: Boolean value. True when wildcards are found.
+ """
+ return ref.find('*') != -1
+
+ @classmethod
+ def get_static_ref(cls, ref):
+ """
+ Checks if the ref has any wildcards and return the non wildcard part of ref.
+ @return: string.
+ """
+ retparts = []
+ for part in cls.split_ref(ref):
+ if cls.has_wildcard(part):
+ break
+ else:
+ retparts.append(part)
+ return ".".join(retparts)
+
def extract_delimited_tokens(string, delimiters=('${', '}')):
"""
Return a list of all tokens delimited by the given strings in the given string.
@@ -388,7 +426,7 @@
['my.ref1', 'my.ref2']
"""
ref_tuples = extract_delimited_token_tuples(string, delimiters)
- return distinct_array([ref for ref, raw_ref in ref_tuples])
+ return distinct_array([u'%s' % ref for ref, raw_ref in ref_tuples])
def extract_delimited_token_tuples(string, delimiters=('${', '}')):
"""
@@ -443,19 +481,26 @@
result = result.replace(raw_token, entry.value)
return result
-def expand_refs_by_default_view(string, default_view, delimiters=('${', '}'), default_value_for_missing=''):
+def expand_refs_by_default_view(string, default_view, delimiters=('${', '}'), default_value_for_missing='',
+ catch_not_found=True):
"""
Convenience function for expanding the refs in a string using setting values.
@param default_value_for_missing: The default value used if a setting for
- a reference cannot be found.
+ a reference cannot be found. Has no effect if catch_not_found is False.
+ @param catch_not_found: If True, the NotFound exception raised when a setting
+ is not found is caught and the value of default_value_for_missing is inserted
+ in its place.
@return: The expanded string.
"""
def expand(ref, index):
- try:
+ if catch_not_found:
+ try:
+ return default_view.get_feature(ref).get_original_value()
+ except exceptions.NotFound:
+ logging.getLogger('cone').error("Feature '%s' not found" % ref)
+ return default_value_for_missing
+ else:
return default_view.get_feature(ref).get_original_value()
- except exceptions.NotFound:
- logging.getLogger('cone').error("Feature '%s' not found" % ref)
- return default_value_for_missing
return expand_delimited_tokens(string, expand, delimiters)
def distinct_array(arr):
@@ -527,6 +572,15 @@
def is_list(elem):
return isinstance(elem, list)
+def is_float(value):
+ """
+ Test if the fiven value (which can be a string) is a floating point value.
+ """
+ fvalue = float(value)
+ ivalue = int(fvalue)
+
+ return (fvalue - ivalue) != 0
+
def get_class(modelinstance, classinstance):
"""
Get the actual model specific implementation class for a classinstance
@@ -538,31 +592,40 @@
return modelclass
return classinstance
-class DataMapRef(object):
- """
- Utility class for handling map attributes in data section
- """
- @classmethod
- def get_feature_ref(cls, map):
- index = map.find("@")
- if index != -1:
- parts = map.split("@")
- return parts[0][:-1]
+class OProperty(object):
+ """Based on the emulation of PyProperty_Type() in Objects/descrobject.c
+ from http://infinitesque.net/articles/2005/enhancing%20Python%27s%20property.xhtml"""
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None):
+ self.fget = fget
+ self.fset = fset
+ self.fdel = fdel
+ self.__doc__ = doc
+
+ def __get__(self, obj, objtype=None):
+ if obj is None:
+ return self
+ if self.fget is None:
+ raise AttributeError, "unreadable attribute"
+ if self.fget.__name__ == '' or not self.fget.__name__:
+ return self.fget(obj)
else:
- return None
-
- @classmethod
- def get_key_value(cls, map):
- index = map.find("@")
- if index != -1:
- parts = map.split("@")
- key = parts[1][:-1]
- keys = key.split("=")
- value = keys[1].strip()
- return value[1:-1]
+ return getattr(obj, self.fget.__name__)()
+
+ def __set__(self, obj, value):
+ if self.fset is None:
+ raise AttributeError, "can't set attribute"
+ if self.fset.__name__ == '' or not self.fset.__name__:
+ self.fset(obj, value)
else:
- return None
-
+ getattr(obj, self.fset.__name__)(value)
+
+ def __delete__(self, obj):
+ if self.fdel is None:
+ raise AttributeError, "can't delete attribute"
+ if self.fdel.__name__ == '' or not self.fdel.__name__:
+ self.fdel(obj)
+ else:
+ getattr(obj, self.fdel.__name__)()
class xml(object):
"""
@@ -585,6 +648,56 @@
else:
return (None, xml_tag)
+ @classmethod
+ def get_xml_root(cls, resource):
+ """
+ Get a (namespace, tag) tuple of the root element in the XML data
+ read from the given resource.
+
+ @param resource: The resource from which to read data. Should be a
+ file-like object (i.e. should have a read() method).
+ @return: A (namespace, tag) tuple. Note that the namespace may
+ be None.
+
+ @raise exceptions.XmlParseError: The resource contains invalid XML data.
+ """
+ class RootElementFound(RuntimeError):
+ def __init__(self, root_name):
+ self.root_name = root_name
+
+ def handle_start(name, attrs):
+ raise RootElementFound(name)
+
+ p = expat.ParserCreate(namespace_separator=':')
+ p.StartElementHandler = handle_start
+
+ BUFSIZE = 128
+ while True:
+ data = resource.read(BUFSIZE)
+ try:
+ p.Parse(data, len(data) < BUFSIZE)
+ except RootElementFound, e:
+ parts = e.root_name.rsplit(':', 1)
+ if len(parts) > 1:
+ return parts[0], parts[1]
+ else:
+ return None, parts[0]
+ except expat.ExpatError, e:
+ raise exceptions.XmlParseError(
+ "XML parse error on line %d: %s" % (e.lineno, e),
+ e.lineno, str(e))
+
+def update_dict(todict, fromdict):
+ """
+ Merges the elements of two dictionaries together.
+ @param todict: the target dictionary where data is merged.
+ @param fromdict: the source dict where data is read
+ @return: the modified todict.
+ """
+ for key in fromdict:
+ todict.setdefault(key, []).extend(fromdict[key])
+ return todict
+
def log_exception(logger, msg, msg_level=logging.ERROR, traceback_level=logging.DEBUG):
"""
Log an exception so that the given message and the exception's
@@ -600,22 +713,85 @@
logger.log(msg_level, msg)
logger.log(traceback_level, traceback.format_exc())
-def make_content_info(resource, data):
+
+def grep(string,list):
+ """
+ Grep throught the items in the given list to find matching entries.
+ """
+ expr = re.compile(string)
+ return filter(expr.search,list)
+
+def grep_tuple(string,list):
+ """
+ Grep throught the items in the given list to find matching entries.
+ @return: a list of tuples (index,text)
"""
- Factory for ContentInfo
+ results = []
+ expr = re.compile(string)
+ for (index,text) in enumerate(list):
+ match = expr.search(text)
+ if match != None:
+ results.append((index,match.string))
+ return results
+
+def grep_dict(string,list):
"""
- cnt_inf = None
+ Grep throught the items in the given list to find matching entries.
+ @return: a dictionary with list index as key and matching text as value.
+ """
+ results = {}
+ expr = re.compile(string)
+ for (index,text) in enumerate(list):
+ match = expr.search(text)
+ if match != None:
+ results[index] = match.string
+ return results
+
+def cmdsplit(s, comments=False, os_name='nt'):
+ """
+ Copy of shlex split method to allow parsing of command line parameters in operating system specific mode.
- if resource != None:
- guessed_type = mimetypes.guess_type(resource.get_path())
- mimetype = None
- mimesubtype = None
-
- if guessed_type != None:
- mimetype, mimesubtype = guessed_type[0].split('/')
-
- if mimetype == 'image' and mimesubtype == 'x-ms-bmp':
- cnt_inf = api.BmpImageContentInfo(resource, data)
+ """
+ posix = True
+ lex = shlex.shlex(s, posix=posix)
+ lex.whitespace_split = True
+ if not comments:
+ lex.commenters = ''
+ if os_name == 'nt':
+ lex.escape = '^'
+ return list(lex)
+
+
+import sys
+sys_version = "%d.%d" % (sys.version_info[0],sys.version_info[1])
+if sys_version >= "2.6":
+ def relpath(path, start=os.curdir):
+ return os.path.relpath(path, start)
+else:
+ def relpath(path, start=os.curdir):
+ """Return a relative version of a path"""
+
+ if not path:
+ raise ValueError("no path specified")
+ start_list = os.path.abspath(start).split(os.sep)
+ path_list = os.path.abspath(path).split(os.sep)
+ if start_list[0].lower() != path_list[0].lower():
+ unc_path, rest = os.path.splitunc(path)
+ unc_start, rest = os.path.splitunc(start)
+ if bool(unc_path) ^ bool(unc_start):
+ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+ % (path, start))
+ else:
+ raise ValueError("path is on drive %s, start on drive %s"
+ % (path_list[0], start_list[0]))
+ # Work out how much of the filepath is shared by start and path.
+ for i in range(min(len(start_list), len(path_list))):
+ if start_list[i].lower() != path_list[i].lower():
+ break
else:
- cnt_inf = api.ContentInfo(mimetype, mimesubtype)
- return cnt_inf
+ i += 1
+
+ rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:]
+ if not rel_list:
+ return os.curdir
+ return os.path.join(*rel_list)
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+#
+# 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:
+#
+
+import sys,os
+
+__all__ = []
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/generation_report.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/generation_report.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,211 @@
+#
+# 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:
+#
+
+import os, logging, pickle
+import time
+from time import strftime
+from cone.public import api, exceptions, utils, plugin
+from cone.confml import model
+from cone.report import report_util
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+SERIALISATION_FORMAT = 'pickle'
+
+def save_report_data(rep_data, file_path):
+ """
+ Save report data into an intermediary report data file.
+ """
+ dir = os.path.dirname(file_path)
+ if dir != '' and not os.path.exists(dir):
+ os.makedirs(dir)
+ f = open(file_path, 'wb')
+ try:
+ if SERIALISATION_FORMAT == 'yaml':
+ yaml.dump(rep_data, f)
+ elif SERIALISATION_FORMAT == 'pickle':
+ pickle.dump(rep_data, f)
+ elif SERIALISATION_FORMAT == 'pickle/2':
+ pickle.dump(rep_data, f, 2)
+ finally:
+ f.close()
+
+def load_report_data(file_path):
+ """
+ Load report data from an intermediary report data file.
+ """
+ try:
+ f = open(file_path, "rb")
+ if SERIALISATION_FORMAT == 'yaml':
+ data = yaml.load(f)
+ elif SERIALISATION_FORMAT == 'pickle':
+ data = pickle.load(f)
+ elif SERIALISATION_FORMAT == 'pickle/2':
+ data = pickle.load(f)
+ finally:
+ f.close()
+
+ data.label = get_generation_run_label(file_path)
+ return data
+
+def get_generation_run_label(datafile_path):
+ filename = os.path.split(datafile_path)[1]
+ filename_noext = os.path.splitext(filename)[0]
+ return filename_noext
+
+def _get_parent_sequence_or_self(feature):
+ current = feature._parent
+ while current is not None:
+ if isinstance(current, api.FeatureSequence):
+ return current
+ current = current._parent
+ return feature
+
+
+def generate_report(rep_data, report_file_path, template_file_path=None, template_paths=[], report_options=[]):
+ """
+ Generate a generation report based on the given report data.
+ @param rep_data: The report data.
+ @param report_file_path: Path to the report file to generate.
+ @param template_file_path: Path to the template file to use.
+ If None, the default template is used.
+ @param template_paths: the additional search paths for templates. The default location cone.report is
+ always included.
+ """
+ # Determine the template file and directory to use
+ if template_file_path is None:
+ template_file_path = 'gen_report_template.html'
+ contexts = [report_data.context for report_data in rep_data]
+ report_data = {'rep_data' : rep_data,
+ 'report_options' : report_options,
+ 'merged_context' : plugin.MergedContext(contexts)}
+ report_util.generate_report(template_file_path, report_file_path, report_data, template_paths)
+
+def normalize_slash(path):
+ """
+ Normalize backslashes to slashes to make testing easier (no differences
+ between reports in linux and windows).
+ """
+ return path.replace('\\', '/')
+
+class ReportData(object):
+ """
+ Data object that stores all information used in report generation.
+ """
+
+ def __init__(self):
+ self.project = None
+ self.generation_timestamp = time.time()
+ self.generation_time = strftime("%d.%m.%Y %H:%M:%S")
+ self.options = None
+ self.duration = 0
+ self.output_dir = os.getcwd()
+ self.project_dir = ''
+ self.context = None
+ self.label = ''
+
+ def set_output_dir(self, dir):
+ self.output_dir = os.path.abspath(os.path.normpath(dir))
+
+ def set_duration(self, duration):
+ self.duration = duration
+
+ def set_options(self, options):
+ self.options = options
+ self.project_dir = os.path.abspath(options.project)
+
+ def set_report_filename(self, filename):
+ self.report_filename = filename
+
+ def __repr__(self):
+ return "ReportData(%s)" % [self.generation_timestamp,
+ self.generation_time,
+ self.options,
+ self.duration,
+ self.output_dir,
+ self.project_dir]
+
+
+class RefLine(object):
+ """
+ Data object that stores information for one ref in report generation.
+ """
+
+ def __init__(self, ref, type):
+ self.ref = ref
+ self.feat_type = type
+ self.feat_name = None
+ self.feat_value = None
+ self.config_path = None
+ self.impls = []
+ self.output = None
+ self.nbr_impls = 0
+ self.nbr_outputfiles = 0
+ self.datas = []
+ self.nbr_of_datas = 0
+ self.nbr_of_rows = 0
+ self.seq_data = []
+ self.is_temp_feature = False
+
+ def add_impl(self, impl_file, impl_type, outputfiles):
+ self.impls.append(ImplLine(impl_file, impl_type, outputfiles))
+ self.nbr_impls = len(self.impls)
+ self.nbr_outputfiles = len(outputfiles) + self.nbr_outputfiles
+
+ def add_data(self, layer, value):
+ self.datas.append(DataLine(layer,value))
+ self.nbr_of_datas = len(self.datas)
+
+ def add_sequence(self, subsetting, values):
+ self.seq_data.append([subsetting, values])
+
+ def set_feat_name(self, name):
+ self.feat_name = name
+
+ def set_feat_value(self, value):
+ self.feat_value = value
+
+ def set_config_path(self, filename):
+ self.config_path = normalize_slash(os.path.normpath(filename))
+
+
+class ImplLine():
+ def __init__(self, impl_file, impl_type, outputfiles, generation_runs=[]):
+ self.name = normalize_slash(os.path.normpath(impl_file))
+ self.type = impl_type
+ files = []
+
+ for outputfile in outputfiles:
+ files.append(Outputfile(outputfile))
+
+ self.outputfiles = files
+ self.generation_runs = generation_runs
+
+class Outputfile():
+ def __init__(self, filename):
+ self.filename = normalize_slash(os.path.normpath(filename))
+ self.abs_filename = normalize_slash(os.path.abspath(filename))
+ self.exists = os.path.isfile(self.abs_filename)
+
+ def __eq__(self, other):
+ if type(self) is type(other):
+ return self.filename == other.filename
+ else:
+ return False
+
+class DataLine():
+ def __init__(self, layer, value):
+ self.layer = normalize_slash(os.path.normpath(layer))
+ self.value = value
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/report_util.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/report_util.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,205 @@
+#
+# 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:
+#
+
+import os
+import urllib
+import logging
+from jinja2 import Environment, FileSystemLoader
+from cone.public import utils
+
+ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+
+log = logging.getLogger('cone.report_util')
+
+class ReportShortcut(object):
+ def __init__(self, template_file, report_file, description):
+ self.template_file = template_file
+ self.report_file = report_file
+ self.description = description
+
+class ReportShortcutContainer(object):
+ """
+ Container for report shortcuts.
+
+ A report shortcut describes a pre-defined report option that
+ has a default template, report file and description. The shortcut
+ container holds a set of shortcuts and can be used to generate
+
+ """
+ def __init__(self, shortcuts, default_shortcut):
+ """
+ @param shortcuts: The shortcuts, a dictionary mapping shortcut
+ names to ReportShortcut objects.
+ @param default_shortcut: The default shortcut name to use
+ """
+ if not isinstance(shortcuts, dict):
+ raise ValueError("'shortcuts' must a dictionary (%s given)!" % type(shortcuts))
+ if default_shortcut is not None and default_shortcut not in shortcuts:
+ raise ValueError("'default_shortcut' must be either None or exist ing 'shortcuts'!")
+ self.shortcuts = shortcuts
+ self.default_shortcut = default_shortcut
+
+ def get_shortcut_help_text(self):
+ """
+ Create the text to append to the option description for the
+ option used to specify the used shortcut.
+ """
+ shortcuts_text = []
+ refs = sorted(self.shortcuts.keys())
+ if refs:
+ for ref in refs:
+ sc = self.shortcuts[ref]
+ text = "%s - %s" % (ref, sc.description)
+ COLUMN_WIDTH = (80 - 25)
+ space_count = COLUMN_WIDTH - (len(text) % COLUMN_WIDTH)
+ shortcuts_text.append(text + space_count * ' ')
+ else:
+ shortcuts_text.append("None")
+ shortcuts_text = '\n'.join(shortcuts_text)
+ return shortcuts_text
+
+ def is_valid_shortcut(self, shortcut):
+ """
+ Return whether the given shortcut is valid within the context
+ of this container.
+ """
+ return shortcut is None or shortcut in self.shortcuts
+
+ def determine_template_and_report(self, shortcut, template_file, report_file, report_file_name_without_ext):
+ """
+ Determine the actual template and report files based on the shortcuts
+ and given options.
+ @param shortcut: The used shortcut or None.
+ @param template_file: Explicitly given template file or None.
+ @param report_file: Explicitly given report file or None.
+ @param report_file_name_without_ext: Prefix used to determine the
+ report file name if the template was explicitly given, but the
+ report file was not. E.g. if this is 'test' and the explicitly
+ given template file is 'my_template.html', the report file would
+ be 'test.html'.
+ @return: Tuple (template_file, report_file) specifying the actual
+ template and report files.
+ """
+ actual_shortcut = None
+ actual_template_file = None
+ actual_report_file = None
+
+ # Handle report shortcut (set to default or check the given one)
+ if not shortcut:
+ actual_shortcut = self.default_shortcut
+ else:
+ actual_shortcut = shortcut
+
+ # Determine template file
+ if template_file:
+ actual_template_file = template_file
+ else:
+ actual_template_file = self.shortcuts[actual_shortcut].template_file
+
+ # Determine report output file
+ if report_file:
+ actual_report_file = report_file
+ else:
+ if template_file:
+ # Determine report file name based on the template file name
+ # if the template was explicitly given
+ actual_report_file = report_file_name_without_ext + os.path.splitext(template_file)[1]
+ else:
+ actual_report_file = self.shortcuts[actual_shortcut].report_file
+
+ return actual_template_file, actual_report_file
+
+def generate_report(template_file, report_file, report_data, template_paths=[], extra_filters={}):
+ """
+ Generate a report based on the given template file, report file
+ and data dictionary.
+ @param template_file: Path to the template file to use.
+ @param report_file: Path to the output report file.
+ @param report_data: The report data dictionary used when rendering
+ the report from the template.
+ @param template_paths: the additional search paths for templates. The default location cone.report is
+ always included.
+ @return: True if successful, False if not.
+ """
+ template_paths.insert(0, ROOT_PATH)
+ template_paths.insert(0, os.path.dirname(template_file))
+ template_paths = utils.distinct_array(template_paths)
+ log.debug('generate_report(template_file=%r, report_file=%r, , template_paths=%s)' % (template_file, report_file, template_paths))
+ if not isinstance(report_data, dict):
+ raise ValueError("report_data must be a dictionary!")
+
+ try:
+ template_file = os.path.abspath(template_file)
+
+ loader = FileSystemLoader(template_paths)
+ env = Environment(loader=loader)
+ set_filters(env,extra_filters)
+
+ template = env.get_template(os.path.basename(template_file))
+ file_string = template.render(report_data)
+
+ # Create directories for the report
+ report_dir = os.path.dirname(report_file)
+ if report_dir != '' and not os.path.exists(report_dir):
+ os.makedirs(report_dir)
+
+ # Write the rendered report to file
+ f = open(report_file, 'wb')
+ try: f.write(file_string.encode('utf-8'))
+ finally: f.close()
+
+ print "Generated report to '%s'" % report_file
+ return True
+ except Exception, e:
+ utils.log_exception(log, "Failed to generate report: %s %s" % (type(e), e))
+ return False
+
+def _set_default_filters(env):
+ """
+ Set default filters to the given Jinja environment
+ """
+ env.filters['xml_charref_replace'] = lambda value: unicode(value).encode('ascii', 'xmlcharrefreplace')
+ env.filters['pathname_to_url'] = lambda value: urllib.pathname2url(value)
+ env.filters['csv_escape'] = _csv_escape
+ env.filters['csv_escape_partial'] = lambda value: unicode(value).replace('"', '""')
+
+def set_filters(env, filters={}):
+ """
+ First set the default filters and then possible extra filters from filters dict
+ @param filters: the filters dictionary where the key is the filter name and value the method pointer
+
+ """
+ _set_default_filters(env)
+ for name, filter in filters.iteritems():
+ env.filters[name]=filter
+
+def _csv_escape(value):
+ """
+ Escape a string value so that it can be used as a field in a CSV file.
+ """
+ value = unicode(value)
+
+ needs_quoting = False
+ for special_char in '",\n':
+ if special_char in value:
+ needs_quoting = True
+
+ if needs_quoting:
+ if '"' in value:
+ value = value.replace('"', '""')
+ value = '"' + value + '"'
+
+ return value
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/layer1/confml/accessoryserver.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/layer1/confml/accessoryserver.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,92 @@
+
+
+ Central repository for accessory related UI settings.
+
+ Setting used to detect properly some connected accessories (e.g. TTY, Loopset).
+
+Phone may support some HW devices that are not properly identified when they are connected to phone. To properly identify such devices user has to tell by using appropriate user interface setting the type of connected device.
+
+
+ Lights setting for wired headset mode. User may force lights on when wired headset is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for wireless headset mode. User may force lights on when wireless headset is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for wired car kit mode. User may force lights on when wired car kit is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for wireless car kit mode. User may force lights on when wireless car kit is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for text device mode. User may force lights on when text device is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for loopset. User may force lights on when loopset is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for music stand. User may force lights on when music stand is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+ Lights setting for synchronization stand. User may force lights on when synchronization stand is connected to phone.
+Possible integer values:
+0 lights off
+1 lights on
+
+
+
+
+
+ 8
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/layer1/confml/feature1.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/layer1/confml/feature1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,89 @@
+
+
+
+ Feature with all supported setting types for ConfML v1.0
+
+ A real setting
+
+
+ An int setting
+
+
+ A string setting
+
+
+ A boolean setting
+
+
+ A selection setting
+
+
+
+
+
+
+
+ A sequence setting
+
+ A real sub-setting
+
+
+ An int sub-setting
+
+
+ A string sub-setting
+
+
+ A boolean sub-setting
+
+
+ A selection sub-setting
+
+
+
+
+
+
+
+
+
+
+ 3.14
+ 10
+ default string
+ true
+ 1
+
+ 1.0
+ 1
+ template
+ false
+ 0
+
+
+ 1.25
+ 128
+ def1
+ false
+ 1
+
+
+ 1.5
+ 256
+ def2
+ false
+ 1
+
+
+
+
+
+
+ true
+ false
+ false
+ true
+ true
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/layer1/implml/accessoryserver_1020505A.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/layer1/implml/accessoryserver_1020505A.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/layer1/implml/test.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/layer1/implml/test.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ ${Feature1.IntSetting} configures ${Feature1.StringSetting} = 'set from rule'
+
+ def test_function2(foo):
+ return foo
+
+
+
+
+ Feature1.IntSetting configures Feature1.SelectionSetting = '0'
+
+ def test_function2(foo):
+ return foo
+
+
+
+
+
+ Test output: {{ feat_tree.Feature1.StringSetting._value }}
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/project/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/project/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/report/tests/unittest_report.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/report/tests/unittest_report.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,102 @@
+#
+# 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:
+#
+
+import os
+import unittest
+
+from cone.report import generation_report
+from cone.public import plugin, api
+from testautomation.utils import remove_if_exists
+
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TEMP_DIR = os.path.normpath(os.path.join(ROOT_PATH, 'temp'))
+
+class TestGenerateReport(unittest.TestCase):
+ def setUp(self):
+ remove_if_exists(TEMP_DIR)
+
+ def test_create_report_data(self):
+ rdata = generation_report.ReportData()
+ self.assertEquals(rdata.context, None)
+
+ def test_save_load_empty_report_data(self):
+ rdata = generation_report.ReportData()
+ tmpfile = os.path.join(TEMP_DIR, 'repdata.dat')
+ generation_report.save_report_data(rdata, tmpfile)
+ rdata2 = generation_report.load_report_data(tmpfile)
+ self.assertEquals(repr(rdata), repr(rdata2))
+
+ def test_save_load_report_data_with_some_content(self):
+ rdata = generation_report.ReportData()
+ p = api.Project(api.Storage.open(TEMP_DIR, 'w'))
+ config = api.Configuration('test.confml')
+ fea = config.create_feature('Foo')
+ fea.create_feature('Child1')
+ fea.create_feature('Child2')
+ c3 = fea.create_feature('Child3')
+ c3.value = 'test'
+ rdata.log = ['one',
+ 'two',
+ 'three']
+ p.add_configuration(config)
+ p.save()
+ rdata.context = plugin.GenerationContext(phase="pre",
+ tags={'target' : 'rofs3'},
+ output='foo',
+ configuration=config,
+ project=p)
+
+ tmpfile = os.path.join(TEMP_DIR, 'repdata.dat')
+ generation_report.save_report_data(rdata, tmpfile)
+ rdata2 = generation_report.load_report_data(tmpfile)
+ self.assertEquals(repr(rdata), repr(rdata2))
+ self.assertEquals(rdata.log, rdata2.log)
+ self.assertEquals(rdata.log, rdata2.log)
+ self.assertEquals(rdata2.context.phase, 'pre')
+ self.assertEquals(rdata2.context.tags, {'target' : 'rofs3'})
+ self.assertEquals(rdata2.context.output, 'foo')
+ self.assertEquals(rdata2.context.configuration.Foo.Child3.fqr, 'Foo.Child3')
+ self.assertEquals(rdata2.context.configuration.Foo.Child3.get_value(), 'test')
+ self.assertEquals(rdata2.context.configuration.Foo.Child3.value, 'test')
+
+ def test_save_load_report_data_with_real_content(self):
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'project')))
+ config = prj.get_configuration('root.confml')
+ impls = plugin.get_impl_set(config)
+ context = plugin.GenerationContext(phase="normal",
+ tags={'target' : ['rofs2']},
+ output='temp',
+ configuration=config)
+
+ impls.generate(context)
+ prj = config.get_project()
+ c1 = config.get_configuration('layer1/root.confml')
+
+ self.assertEquals(len(context.generation_output), 4)
+ rdata = generation_report.ReportData()
+ rdata.context = context
+ rdata.project = prj
+ tmpfile = os.path.join(TEMP_DIR, 'repdata_real.dat')
+ generation_report.save_report_data(rdata, tmpfile)
+ rdata2 = generation_report.load_report_data(tmpfile)
+ self.assertEquals(repr(rdata), repr(rdata2))
+ dview = rdata2.context.configuration.get_default_view()
+ self.assertEquals(len(rdata2.context.generation_output), 4)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/runtests.py
--- a/configurationengine/source/cone/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,28 +15,6 @@
#
-import os,sys,unittest
-from optparse import OptionParser, OptionGroup
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-sys.path.insert(0, os.path.join(ROOT_PATH,'..'))
-#sys.path.insert(0, os.path.join(ROOT_PATH,'../testautomation'))
-
-import cone.storage.tests
-import cone.core.tests
-import cone.confml.tests
-import cone.carbon.tests
-import cone.public.tests
-#from testautomation import testcli
-
-def collect_suite():
- suite = unittest.TestSuite()
- suite.addTests(cone.storage.tests.collect_suite())
- suite.addTests(cone.core.tests.collect_suite())
- suite.addTests(cone.confml.tests.collect_suite())
- suite.addTests(cone.carbon.tests.collect_suite())
- suite.addTests(cone.public.tests.collect_suite())
- return suite
if __name__ == '__main__':
import nose
@@ -49,9 +27,5 @@
conf = nose.config.Config(files=allfiles,
plugins=plugins)
conf.configure(argv=['collector'])
- print "conf :", conf.include
nose.main(config=conf)
-#if __name__ == '__main__':
-# testcli.run(collect_suite())
-
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/authenticate.py
--- a/configurationengine/source/cone/storage/authenticate.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/authenticate.py Tue Aug 10 14:29:28 2010 +0300
@@ -38,6 +38,8 @@
The data is saved in varables inside class
"""
def __init__(self, *argv, **kwargs):
+ self.username_func = kwargs.pop('username_func',None)
+ self.password_func = kwargs.pop('password_func',None)
HTMLParser.__init__(self, *argv, **kwargs)
self.html_end = False
self.httpdata = {}
@@ -45,8 +47,6 @@
self.input_entered = False
self.method = ''
self.action = ''
- self.username = kwargs.get('username')
- self.password = kwargs.get('password')
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
@@ -64,13 +64,13 @@
self.httpdata[attrs.get('name')] = attrs.get('value')
if inputtype == 'password':
self.input_requested = True
- data = self.password
+ data = self.password_func()
if data:
self.input_entered = True
self.httpdata[attrs.get('name')] = data
if inputtype == 'text':
self.input_requested = True
- data = raw_input()
+ data = self.username_func()
if data:
self.input_entered = True
self.httpdata[attrs.get('name')] = data
@@ -95,13 +95,47 @@
class CarbonAuthHandler(urllib2.AbstractHTTPHandler):
handler_order = 600
+ def __init__(self):
+ urllib2.AbstractHTTPHandler.__init__(self)
+ self.auth_count = 0
+ self.auth_max = 5
+ self.username = ""
+ self.password = ""
+ self.username_func = None
+ self.password_func = None
+
- def add_password(self, username, password):
+ def add_username_func(self, username_func):
+ """
+ Add password getting function
+ """
+ self.username_func = username_func
+
+ def add_password_func(self, password_func):
+ """
+ Add password getting function
"""
- Add username and password
+ self.password_func = password_func
+
+ def get_username(self):
+ """
+ Add password getting function
"""
- self.username = username
- self.password = password
+ if self.auth_count == 0 and self.username_func:
+ return self.username_func()
+ else:
+ self.username = raw_input("Username: ")
+ return self.username
+
+ def get_password(self):
+ """
+ Add password getting function
+ """
+ if self.auth_count == 0 and self.password_func:
+ return self.password_func()
+ else:
+ self.password = getpass.getpass()
+ return self.password
def https_response(self, request, response):
"""
@@ -111,8 +145,13 @@
original page.
"""
if (re.match('login.*\.europe\.nokia\.com', request.get_host())):
- sso_parser = SSOHTMLParser(username=self.username, password=self.password)
+ if self.auth_count > self.auth_max:
+ print "Authentication failed!"
+ return response
+ sso_parser = SSOHTMLParser(username_func=self.get_username, password_func=self.get_password)
sso_parser.feed(response.read())
+ self.auth_count += 1
+
# !sso_parser.input_requested when we have posted the form and
# are reading the redirect back. We don't want to handle that
if sso_parser.input_requested:
@@ -140,14 +179,18 @@
original page.
"""
if response.code == 200 and (re.match('.*/extauth/login/?.*', request.get_full_url())):
+ if self.auth_count > self.auth_max:
+ raise urllib2.HTTPError("Authentication failed!")
+
loginreq = urllib2.Request(request.get_full_url(),
- urllib.urlencode({ 'username' : self.username,
- 'password' : self.password,
+ urllib.urlencode({ 'username' : self.get_username(),
+ 'password' : self.get_password(),
'submit' : 'login'}
),
origin_req_host=request.get_origin_req_host(),
unverifiable=True,
)
+ self.auth_count += 1
return self.parent.open(loginreq)
else:
return response
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/common.py
--- a/configurationengine/source/cone/storage/common.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/common.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,18 +17,20 @@
import logging
import xml.parsers.expat
-from cone.public import api, utils
+from cone.public.api import Storage
+from cone.public import utils
from cone.storage import metadata
-class StorageBase(api.Storage):
+class StorageBase(Storage):
"""
A general base class for all storage type classes
"""
METADATA_FILENAME = ".metadata"
- def __init__(self,path):
- super(StorageBase, self).__init__(path)
+ def __init__(self, path, mode):
+ super(StorageBase, self).__init__(path, mode)
self.meta = self.read_metadata()
+
def get_active_configuration(self):
"""
@@ -37,7 +39,7 @@
"""
root_confmls = self.list_resources("/")
root_confmls = utils.resourceref.filter_resources(root_confmls,"\.confml")
- if self.meta.get_root_file() == '' and len(root_confmls) == 1:
+ if self.meta.get_root_file() == None and len(root_confmls) == 1:
return root_confmls[0]
else:
return self.meta.get_root_file()
@@ -68,7 +70,7 @@
# Try to update the metadata, which might fail on ZipStorage
try:
- if self.get_mode(self.mode) != api.Storage.MODE_READ:
+ if self.get_mode(self.mode) != Storage.MODE_READ:
# update the active configuration
self.set_active_configuration(self.get_active_configuration())
metares = self.open_resource(self.METADATA_FILENAME,"wb")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/filestorage.py
--- a/configurationengine/source/cone/storage/filestorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/filestorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -26,13 +26,13 @@
except ImportError:
try:
from xml.etree import cElementTree as ElementTree
- except ImpotError:
+ except ImportError:
from xml.etree import ElementTree
from cone.public import exceptions
-from cone.public import api, utils
+from cone.public import api, utils, parsecontext
#from cone.storage.configurationpersistence import ConfigurationReader, ConfigurationWriter
-from cone.storage import metadata, common
+from cone.storage import metadata, common, zipstorage
from cone.confml import persistentconfml
debug = 0
@@ -43,12 +43,10 @@
@param mode: the mode for the folder. Default is a=append that expects the folder to exist.
"""
- def __init__(self,path,mode="r", **kwargs):
- super(FileStorage, self).__init__(path)
- self.logger = logging.getLogger('cone')
- self.logger.debug("FileStorage path %s" % self.get_path())
+ def __init__(self, path, mode="r", **kwargs):
+ super(FileStorage, self).__init__(path, mode)
+ logging.getLogger('cone').debug("FileStorage path %s" % self.get_path())
self.persistentmodule = persistentconfml
- self.mode = mode
if mode.find("a")!=-1 or mode.find("r")!=-1:
# check that the given folder exists and is a folder
if not os.path.isdir(self.get_path()):
@@ -151,7 +149,7 @@
return entry
- def list_resources(self,path,recurse=False,empty_folders=False):
+ def list_resources(self, path, **kwargs):
"""
Get an array of files in a folder
"""
@@ -162,16 +160,20 @@
joined = os.path.join(self.get_path(), self.get_current_path())
current_root = os.path.normpath(os.path.abspath(joined))
# return always unix type file paths
- if recurse:
+ if kwargs.get('recurse', False):
# Walk through all files in the layer
for root, dirs, files in os.walk(fullpath):
+ # ensure that the directories and files are returned
+ # with alphabetical sorting in all platforms (e.g linux)
+ dirs.sort()
+ files.sort()
for name in files:
entry = os.path.join(root, name)
entry = os.path.normpath(os.path.abspath(entry))
if os.path.isfile(entry):
retarray.append(self.fix_entry(entry,current_root))
- if empty_folders:
+ if kwargs.get('empty_folders', False):
for name in dirs:
entry = os.path.join(root, name)
entry = os.path.normpath(os.path.abspath(entry))
@@ -179,7 +181,7 @@
retarray.append(self.fix_entry(entry,current_root))
else:
- filelist = os.listdir(fullpath)
+ filelist = sorted(os.listdir(fullpath))
for name in filelist:
entry = os.path.join(path, name)
entry = os.path.normpath(entry)
@@ -191,7 +193,7 @@
if debug: print "list_resources adding %s" % entry
retarray.append(entry)
- if os.path.isdir(fileentry) and empty_folders:
+ if os.path.isdir(fileentry) and kwargs.get('empty_folders', False):
if debug: print "list_resources adding %s" % entry
retarray.append(entry)
return retarray
@@ -217,11 +219,19 @@
logging.getLogger('cone').warning("The given path is not a Resource in this storage %s! Ignoring from export!" % path)
continue
if self.is_resource(path):
- wres = storage.open_resource(path,'wb')
- res = self.open_resource(path,"rb")
- wres.write(res.read())
- wres.close()
- res.close()
+ # Optimization for direct file to ZIP export.
+ # There's no need to juggle the data through ConE code
+ # when we can just write the file directly into the ZIP
+ if isinstance(storage, zipstorage.ZipStorage):
+ source_abspath = os.path.join(self.rootpath, path)
+ logging.getLogger("cone").debug("Exporting directly from file to ZIP: %r -> %r" % (source_abspath, path))
+ storage.zipfile.write(source_abspath, path)
+ else:
+ wres = storage.open_resource(path,'wb')
+ res = self.open_resource(path,"rb")
+ wres.write(res.read())
+ wres.close()
+ res.close()
if self.is_folder(path) and empty_folders:
@@ -235,7 +245,7 @@
Create a folder entry to a path
@param path : path to the folder
"""
-
+ path = utils.resourceref.remove_begin_slash(path)
path = utils.resourceref.join_refs([self.get_path(), self.get_current_path(), path])
if not os.path.exists(path):
os.makedirs(path)
@@ -289,13 +299,15 @@
if self.is_resource(path):
res = self.open_resource(path,"r")
# read the resource with persistentmodule
+ parsecontext.get_confml_context().current_file = path
try:
obj = self.persistentmodule.loads(res.read())
#obj.set_path(path)
res.close()
return obj
except exceptions.ParseError,e:
- logging.getLogger('cone').error("Resource %s parsing failed with exception: %s" % (path,e))
+ parsecontext.get_confml_context().handle_exception(e)
+ #logging.getLogger('cone').error("Resource %s parsing failed with exception: %s" % (path,e))
# returning an empty config in case of xml parsing failure.
return api.Configuration(path)
else:
@@ -345,6 +357,6 @@
data = self.handle.read()
self.handle.seek(orig_pos, os.SEEK_SET)
if self.content_info == None:
- self.content_info = utils.make_content_info(self, data)
+ self.content_info = api.make_content_info(self, data)
return self.content_info
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/metadata.py
--- a/configurationengine/source/cone/storage/metadata.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/metadata.py Tue Aug 10 14:29:28 2010 +0300
@@ -24,8 +24,10 @@
from xml.etree import cElementTree as ElementTree
except ImportError:
from xml.etree import ElementTree
+
import StringIO
import os
+import logging
from cone.public import exceptions, persistence
@@ -42,13 +44,13 @@
self.data = {}
if copyobj != None:
self.data = copyobj.data.copy()
- pass
def get_root_file(self):
- return self.data.get(self.META_ROOT_FILE,"")
+ return self.data.get(self.META_ROOT_FILE, None)
def set_root_file(self,filename):
- self.data[self.META_ROOT_FILE] = filename
+ if filename:
+ self.data[self.META_ROOT_FILE] = filename
class MetadataReader(persistence.ConeReader):
"""
@@ -56,16 +58,16 @@
"""
class_type = "Metadata"
NAMESPACES = ['http://www.nokia.com/xml/ns/confml-core/metadata-2.0']
- def __init__(self):
- return
def fromstring(self, xml_as_string):
meta = Metadata()
- etree = ElementTree.fromstring(xml_as_string)
- iter = etree.getiterator("{%s}property" % self.NAMESPACES[0])
- for elem in iter:
- (key,value) = self.get_property(elem)
- meta.data[key] = value
+ try:
+ etree = ElementTree.fromstring(xml_as_string)
+ for elem in etree.getiterator("{%s}property" % self.NAMESPACES[0]):
+ (key,value) = self.get_property(elem)
+ meta.data[key] = value
+ except Exception,e:
+ logging.getLogger('cone').warning("Could not read metadata! Exception %s" % (e))
return meta
def get_property(self, elem):
@@ -82,6 +84,7 @@
NAMESPACES = ['http://www.nokia.com/xml/ns/confml-core/metadata-2.0']
DEFAULT_ENCODING = "ASCII"
def __init__(self):
+ super(MetadataWriter, self).__init__()
self.encoding = self.DEFAULT_ENCODING
return
@@ -100,6 +103,18 @@
self.set_property(prop, key, obj.data[key])
if indent:
persistence.indent(root)
+
+ # To make the output the same in linux and windows
+ # (needed to make testing easier)
+ class LinesepNormalizerResource(object):
+ def __init__(self, resource):
+ self.resource = resource
+ def write(self, data):
+ if os.linesep != '\r\n':
+ data = data.replace(os.linesep, '\r\n')
+ self.resource.write(data)
+ res = LinesepNormalizerResource(res)
+
# some smarter way to implement adding of the encoding to the beginning of file
res.write('%s' % (self.encoding,os.linesep))
ElementTree.ElementTree(root).write(res)
@@ -108,4 +123,4 @@
elem.attrib['name'] = key
if value != '':
elem.attrib['value'] = value
- return elem
\ No newline at end of file
+ return elem
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/stringstorage.py
--- a/configurationengine/source/cone/storage/stringstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/stringstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -62,9 +62,12 @@
A general base class for all storage type classes
@param path : the reference to the root of the storage.
"""
- def __init__(self, path):
+ def __init__(self, path, mode='r'):
container.ObjectContainer.__init__(self,"")
- api.Storage.__init__(self,path)
+ api.Storage.__init__(self, path, mode)
+
+ def __reduce_ex__(self, protocol_version):
+ return super(container.ObjectContainer, self).__reduce_ex__(protocol_version)
def __getstate__(self):
dict = self.__dict__.copy()
@@ -189,7 +192,7 @@
if not res.get_mode() == api.Storage.MODE_READ:
self._get(utils.resourceref.to_dref(res.path)).data = res.getvalue()
except KeyError,e:
- raise StorageException("No such %s open resource! %s" % (res.path,e))
+ raise exceptions.StorageException("No such %s open resource! %s" % (res.path,e))
def save_resource(self, res):
@@ -213,7 +216,7 @@
path = utils.resourceref.join_refs([self.get_current_path(), path])
return self._has(utils.resourceref.to_dref(path))
- def list_resources(self,path,recurse=False,empty_folders=False):
+ def list_resources(self, path, **kwargs):
"""
find the resources under certain path/path
@param path : reference to path where resources are searched
@@ -224,14 +227,17 @@
try:
curelem = self._get(utils.resourceref.to_dref(self.get_current_path()))
dref = utils.resourceref.to_dref(path)
- if recurse:
- return sorted([child.path_to_elem(curelem) for child in curelem._get(dref)._traverse(type=_StringStorageObject)])
- else:
- return sorted([child.path_to_elem(curelem) for child in curelem._get(dref)._objects(type=_StringStorageObject)])
+ elems = sorted([child.path_to_elem(curelem) for child in curelem._get(dref)._objects(type=_StringStorageObject)])
+ if kwargs.get('recurse', False):
+ # Recursively call list_resources to subelements that are of 'folder' type
+ folders = [child._name for child in curelem._get(dref)._objects() if child.__class__ == container.ObjectContainer]
+ for folderpath in sorted(folders):
+ elems += self.list_resources(utils.resourceref.join_refs([path,folderpath]), **kwargs)
+ return elems
except exceptions.NotFound:
return []
- def import_resources(self,paths,storage,empty_folders=False):
+ def import_resources(self, paths, storage, **kwargs):
for path in paths:
if not storage.is_resource(path):
logging.getLogger('cone').warning("The given path is not a Resource in the storage %s! Ignoring from export!" % path)
@@ -328,11 +334,11 @@
else:
self.handle.write(string)
- def read(self, bytes=0):
- if self.get_mode() == api.Storage.MODE_WRITE:
- raise exceptions.StorageException("Reading attempted to %s in write-only mode." % self.path)
- else:
- self.handle.read(string)
+# def read(self, length=0):
+# if self.get_mode() == api.Storage.MODE_WRITE:
+# raise exceptions.StorageException("Reading attempted to %s in write-only mode." % self.path)
+# else:
+# self.handle.read(length)
def save(self):
self.storage.save_resource(self)
@@ -348,6 +354,6 @@
def get_content_info(self):
if self.content_info == None:
- self.content_info = utils.make_content_info(self, self.handle.getvalue())
+ self.content_info = api.make_content_info(self, self.handle.getvalue())
return self.content_info
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/__init__.py
--- a/configurationengine/source/cone/storage/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,37 +13,3 @@
#
# Description:
#
-
-import unittest, os, sys
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../..'))
-TESTAUTO_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../testautomation'))
-if SOURCE_ROOT not in sys.path:
- sys.path.insert(0,SOURCE_ROOT)
-if TESTAUTO_ROOT not in sys.path:
- sys.path.insert(0,TESTAUTO_ROOT)
-
-# Find all unittest_*.py files in this folder
-import re
-__all__ = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(ROOT_PATH))
-# Strip .py endings
-__all__ = map(lambda name: name[:-3], __all__)
-
-def collect_suite():
- sys.path.insert(0, ROOT_PATH)
- try:
- suite = unittest.TestSuite()
- for test_module in __all__:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- del sys.path[0]
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/fileres_test/test_getsize.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/storage/tests/fileres_test/test_getsize.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Writing foobar
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/runtests.py
--- a/configurationengine/source/cone/storage/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
\ No newline at end of file
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_authenticate.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/storage/tests/unittest_authenticate.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,46 @@
+#
+# 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:
+#
+
+import unittest
+import os
+
+from cone.storage import authenticate
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class TestCarbonAuthHandler(unittest.TestCase):
+ def setUp(self):
+ self.test_user = "admin"
+ self.test_passwd = "minda"
+
+ def callback_username(self):
+ return self.test_user
+
+ def callback_password(self):
+ return self.test_passwd
+
+ def test_username_password_func(self):
+ carbon_handler = authenticate.CarbonAuthHandler()
+ carbon_handler.add_username_func(self.callback_username)
+ carbon_handler.add_password_func(self.callback_password)
+ username = carbon_handler.get_username()
+ password = carbon_handler.get_password()
+ self.assertEqual(self.test_user,username)
+ self.assertEqual(self.test_passwd,password)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_fileresource.py
--- a/configurationengine/source/cone/storage/tests/unittest_fileresource.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_fileresource.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,14 +19,11 @@
Test the CPF root file parsing routines
"""
-import zipfile
import unittest
-import string
-import sys,os
+import os
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-import __init__
-from cone.public.exceptions import NotResource, StorageException
+from cone.public.exceptions import StorageException
from cone.public import api
from cone.storage import filestorage
@@ -151,12 +148,12 @@
res.close()
def test_get_content_info_and_read_data(self):
- res = self.storage.open_resource("testread.txt", "r")
+ res = self.storage.open_resource("testread.txt", "rb")
ci = res.get_content_info()
self.assertEquals('text/plain', ci.content_type)
data = res.read()
- self.assertEquals('foo bar test.\n', data)
+ self.assertEquals('foo bar test.\r\n', data)
res.close()
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_filestorage.py
--- a/configurationengine/source/cone/storage/tests/unittest_filestorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_filestorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -25,7 +25,6 @@
import sys,os,shutil
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-import __init__
from cone.public.exceptions import NotResource,StorageException
from cone.public import api
from cone.storage import filestorage
@@ -35,103 +34,118 @@
datafolder= os.path.join(ROOT_PATH,"data")
-class TestFileStorageCreation(unittest.TestCase):
- def setUp(self):
- pass
-
- def test_create_storage_on_non_existing_path_fails(self):
- try:
- storage = filestorage.FileStorage("dummydatafolder")
- self.fail("opening on dummydatafolder succeeds?")
- except StorageException,e:
- self.assertTrue(True)
-
- def test_create_storage_on_file_fails(self):
- try:
- storage = filestorage.FileStorage(datazip)
- self.fail("opening on data file succeeds?")
- except StorageException,e:
- self.assertTrue(True)
-
- def test_create_storage_on_new_directory(self):
- storage = filestorage.FileStorage("dummytest/storage","w")
- self.assertTrue(os.path.exists("dummytest/storage"))
- shutil.rmtree("dummytest")
-
+#class TestFileStorageCreation(unittest.TestCase):
+# def setUp(self):
+# pass
+# def test_create_storage_on_non_existing_path_fails(self):
+# try:
+# storage = filestorage.FileStorage("dummydatafolder")
+# self.fail("opening on dummydatafolder succeeds?")
+# except StorageException,e:
+# self.assertTrue(True)
+#
+# def test_create_storage_on_file_fails(self):
+# try:
+# storage = filestorage.FileStorage(datazip)
+# self.fail("opening on data file succeeds?")
+# except StorageException,e:
+# self.assertTrue(True)
+#
+# def test_create_storage_on_new_directory(self):
+# storage = filestorage.FileStorage("dummytest/storage","w")
+# self.assertTrue(os.path.exists("dummytest/storage"))
+# shutil.rmtree("dummytest")
+#
class TestFileStorage(unittest.TestCase):
- def setUp(self):
- self.storage = filestorage.FileStorage(datafolder)
-
- def test_supported_storage(self):
- self.assertTrue(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir/cone_vs_ct2/pf7132_020.006/config_project/"))
- self.assertTrue(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir"))
- self.assertFalse(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir.zip"))
-
- def test_open_resource_existing_file_for_reading(self):
- res = self.storage.open_resource("simple.confml")
- self.assertTrue(res)
- self.assertTrue(isinstance(res,api.Resource))
-
- def test_open_resource_new_file(self):
- res = self.storage.open_resource("newfile.txt","w")
- self.assertTrue(res)
- self.assertTrue(isinstance(res,api.Resource))
- res.close()
- self.assertTrue(os.path.exists(datafolder+"/newfile.txt"))
- os.remove(datafolder+"/newfile.txt")
-
- def test_list_resources(self):
- self.assertEquals(self.storage.list_resources("."),
- ['.metadata', 'morestuff.confml', 'prodX.confml', 'simple.confml'])
-
- def test_delete_resource(self):
- tf = open(os.path.join(datafolder,"tempfile.txt"),"w")
- tf.close()
- res = self.storage.delete_resource("tempfile.txt")
- self.assertFalse(os.path.exists(datafolder+"tempfile.txt"))
-
- def test_open_resource_nonexisting(self):
- try:
- res = self.storage.open_resource("iamnothere.txt")
- self.fail("Opening of a non existing file succeeds!??")
- except NotResource:
- self.assertTrue(True)
-
- def test_list_resources_nonrecurse(self):
- file_array = self.storage.list_resources("")
- self.assertEquals(file_array[0],".metadata")
-
- def test_list_resources_nonrecurse_from_root(self):
- file_array = self.storage.list_resources("/")
- self.assertTrue(file_array.index(".metadata")==0)
-
- def test_list_resources_recurse_from_root(self):
- file_array = self.storage.list_resources("",True)
- self.assertEquals(file_array[0],".metadata")
-
- def test_list_resources_from_subfolder(self):
- file_array = self.storage.list_resources("familyX")
- self.assertEquals(file_array[0],"familyX/root.confml")
-
- def test_list_resources_recurse_from_subfolder(self):
- file_array = self.storage.list_resources("familyX", True)
- self.assertEquals(file_array[0],"familyX/root.confml")
- # Count only non-SVN files
- self.assertEquals(len(filter(lambda x: x.find('.svn') == -1, file_array)), 7)
-
- def test_is_resource_true(self):
- self.assertTrue(self.storage.is_resource("simple.confml"))
-
- def test_is_resource_true_with_begin_slash(self):
- self.assertTrue(self.storage.is_resource("/simple.confml"))
-
- def test_is_resource_false(self):
- self.assertFalse(self.storage.is_resource("data"))
-
- def test_open_resource_existing_file_with_root(self):
- res = self.storage.open_resource("/simple.confml")
- self.assertTrue(res)
- self.assertTrue(isinstance(res,api.Resource))
+# def setUp(self):
+# self.storage = filestorage.FileStorage(datafolder)
+#
+# def test_supported_storage(self):
+# self.assertTrue(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir/cone_vs_ct2/pf7132_020.006/config_project/"))
+# self.assertTrue(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir"))
+# self.assertFalse(filestorage.FileStorage.supported_storage("C:/GenerationRegressionTest/wc/genregtest_workdir.zip"))
+#
+# def test_open_resource_existing_file_for_reading(self):
+# res = self.storage.open_resource("simple.confml")
+# self.assertTrue(res)
+# self.assertTrue(isinstance(res,api.Resource))
+#
+# def test_open_resource_new_file(self):
+# res = self.storage.open_resource("newfile.txt","w")
+# self.assertTrue(res)
+# self.assertTrue(isinstance(res,api.Resource))
+# res.close()
+# self.assertTrue(os.path.exists(datafolder+"/newfile.txt"))
+# os.remove(datafolder+"/newfile.txt")
+#
+# def test_list_resources(self):
+# self.assertEquals(sorted(self.storage.list_resources(".")),
+# sorted(['.metadata', 'morestuff.confml', 'prodX.confml', 'simple.confml']))
+#
+# def test_delete_resource(self):
+# tf = open(os.path.join(datafolder,"tempfile.txt"),"w")
+# tf.close()
+# res = self.storage.delete_resource("tempfile.txt")
+# self.assertFalse(os.path.exists(datafolder+"tempfile.txt"))
+#
+# def test_open_resource_nonexisting(self):
+# try:
+# res = self.storage.open_resource("iamnothere.txt")
+# self.fail("Opening of a non existing file succeeds!??")
+# except NotResource:
+# self.assertTrue(True)
+#
+# def test_list_resources_nonrecurse(self):
+# file_array = self.storage.list_resources("")
+# self.assertTrue(".metadata" in file_array)
+#
+# def test_list_resources_nonrecurse_from_root(self):
+# file_array = self.storage.list_resources("/")
+# self.assertTrue(".metadata" in file_array)
+#
+# def test_list_resources_recurse_from_root(self):
+# file_array = self.storage.list_resources("",True)
+# self.assertTrue(".metadata" in file_array)
+#
+# def test_list_resources_from_subfolder(self):
+# file_array = self.storage.list_resources("familyX")
+# self.assertTrue("familyX/root.confml" in file_array)
+#
+# def test_list_resources_recurse_from_subfolder(self):
+# file_array = self.storage.list_resources("familyX", True)
+# self.assertTrue("familyX/root.confml" in file_array)
+# # Count only non-SVN files
+# self.assertEquals(len(filter(lambda x: x.find('.svn') == -1, file_array)), 7)
+#
+# def test_is_resource_true(self):
+# self.assertTrue(self.storage.is_resource("simple.confml"))
+#
+# def test_is_resource_true_with_begin_slash(self):
+# self.assertTrue(self.storage.is_resource("/simple.confml"))
+#
+# def test_is_resource_false(self):
+# self.assertFalse(self.storage.is_resource("data"))
+#
+# def test_open_resource_existing_file_with_root(self):
+# res = self.storage.open_resource("/simple.confml")
+# self.assertTrue(res)
+# self.assertTrue(isinstance(res,api.Resource))
+#
+#
+# def test_create_folder(self):
+# store = filestorage.FileStorage("newtestfolder","w")
+# store.create_folder("subdir")
+# self.assertTrue(store.is_folder("subdir"))
+# self.assertTrue(os.path.exists("newtestfolder/subdir"))
+# store.create_folder('foo')
+# layer = api.Folder(store, "foo")
+# self.assertTrue(store.is_folder("foo"))
+# self.assertTrue(layer)
+# self.assertTrue(os.path.exists("newtestfolder/subdir"))
+# layer.create_folder("foosubdir")
+# self.assertTrue(store.is_folder("foo/foosubdir"))
+# self.assertTrue(os.path.exists("newtestfolder/foo/foosubdir"))
+# shutil.rmtree('newtestfolder')
def test_metadata_writing(self):
fs = filestorage.FileStorage("testtemp","w")
@@ -141,21 +155,7 @@
self.assertEquals(fs.get_active_configuration(),'testing.confml')
fs.close()
shutil.rmtree("testtemp")
-
- def test_create_folder(self):
- store = filestorage.FileStorage("newtestfolder","w")
- store.create_folder("subdir")
- self.assertTrue(store.is_folder("subdir"))
- self.assertTrue(os.path.exists("newtestfolder/subdir"))
- store.create_folder('foo')
- layer = api.Folder(store, "foo")
- self.assertTrue(store.is_folder("foo"))
- self.assertTrue(layer)
- self.assertTrue(os.path.exists("newtestfolder/subdir"))
- layer.create_folder("foosubdir")
- self.assertTrue(store.is_folder("foo/foosubdir"))
- self.assertTrue(os.path.exists("newtestfolder/foo/foosubdir"))
- shutil.rmtree('newtestfolder')
+
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_filestorage_layer.py
--- a/configurationengine/source/cone/storage/tests/unittest_filestorage_layer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_filestorage_layer.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,137 +18,69 @@
Test the configuration
"""
import unittest
-import string
-import sys,os, shutil
-import __init__
+import os
-from cone.public import api,exceptions,utils
-from cone.storage import filestorage
+from cone.storage import filestorage, zipstorage
+from cone.public.tests import unittest_layer
+from testautomation.utils import remove_if_exists
-class TestLayer(unittest.TestCase):
- storage_class = filestorage.FileStorage
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+LAYER_TMP_FOLDER = os.path.join(ROOT_PATH, "temp/layertest")
+LAYER_TMP_ZIP = os.path.join(ROOT_PATH, "temp/layertest.zip")
- def test_create_layer(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- self.assertTrue(layer)
- shutil.rmtree("temp/layertest")
+##########################################################################
+# FileStorage tests for folder and layer actions
-# def test_create_layer_with_kwargs(self):
-# store = self.storage_class("temp/layertest","w")
-# layer = api.Layer(store, "foo",confml_path="foobar", implml_path="")
-# self.assertTrue(layer)
-# self.assertEquals(layer.confml_folder.get_current_path(),"foo/foobar")
-# self.assertEquals(layer.implml_folder.get_current_path(),"foo")
-# layer = api.Layer(store, "foo",confml_path="f", implml_path="test", content_path="data", doc_path="foo")
-# self.assertEquals(layer.confml_folder.get_current_path(),"foo/f")
-# self.assertEquals(layer.implml_folder.get_current_path(),"foo/test")
-# self.assertEquals(layer.content_folder.get_current_path(),"foo/data")
-# self.assertEquals(layer.doc_folder.get_current_path(),"foo/foo")
-# layer = api.Layer(store, "foo")
-# self.assertEquals(layer.confml_folder.get_current_path(),"foo/confml")
-# self.assertEquals(layer.implml_folder.get_current_path(),"foo/implml")
-# self.assertEquals(layer.content_folder.get_current_path(),"foo/content")
-# self.assertEquals(layer.doc_folder.get_current_path(),"foo/doc")
-# shutil.rmtree("temp/layertest")
+class TestFolderOnFileStorage(unittest_layer.TestFolder):
+ def setUp(self):
+ self.store = filestorage.FileStorage(LAYER_TMP_FOLDER,"w")
+
+ def tearDown(self):
+ remove_if_exists(LAYER_TMP_FOLDER)
- def test_get_path(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- self.assertTrue(layer)
- self.assertEquals(layer.get_current_path(),"foo")
- shutil.rmtree("temp/layertest")
+class TestLayerOnFileStorage(unittest_layer.TestLayer):
+ def setUp(self):
+ self.store = filestorage.FileStorage(LAYER_TMP_FOLDER,"w")
- def test_open_resource(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- self.assertTrue(layer)
- res = layer.open_resource("confml/test.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(layer.list_resources("", True),["confml/test.confml"])
- self.assertEquals(store.list_resources("", True),["foo/confml/test.confml"])
- shutil.rmtree("temp/layertest")
+ def tearDown(self):
+ remove_if_exists(LAYER_TMP_FOLDER)
+
+class TestCompositeLayerOnFileStorage(unittest_layer.TestCompositeLayer):
+ def setUp(self):
+ self.store = filestorage.FileStorage(LAYER_TMP_FOLDER,"w")
- def test_create_two_layers_and_open_resource(self):
- store = self.storage_class("temp/layertest","w")
- foo_layer = api.Layer(store, "foo")
- bar_layer = api.Layer(store, "bar")
- res = foo_layer.open_resource("confml/test.confml","w")
- res.write("foo.conf")
- res.close()
- res = foo_layer.open_resource("root.confml","w")
- res.close()
- res = bar_layer.open_resource("confml/root.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(foo_layer.list_resources("", True),['root.confml', 'confml/test.confml'])
- self.assertEquals(store.list_resources("", True),['bar/confml/root.confml','foo/root.confml','foo/confml/test.confml'])
- foo_layer.delete_resource("confml/test.confml")
- self.assertEquals(foo_layer.list_resources("", True),["root.confml"])
- self.assertEquals(store.list_resources("", True),["bar/confml/root.confml","foo/root.confml"])
- shutil.rmtree("temp/layertest")
+ def tearDown(self):
+ remove_if_exists(LAYER_TMP_FOLDER)
- def test_list_confml(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- res = layer.open_resource("confml/test.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("confml/foo.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("root.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(layer.list_confml(),['confml/foo.confml', 'confml/test.confml'])
- shutil.rmtree("temp/layertest")
+##########################################################################
+# ZipStorage
+
- def test_list_implml(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- res = layer.open_resource("implml/stuff/test.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("confml/foo.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("root.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(layer.list_implml(),['implml/stuff/test.confml'])
- shutil.rmtree("temp/layertest")
+#class TestFolderOnZipStorage(unittest_layer.TestFolder):
+# def setUp(self):
+# self.store = zipstorage.ZipStorage(LAYER_TMP_ZIP,"w")
+#
+# def tearDown(self):
+# self.store.close()
+# remove_if_exists(LAYER_TMP_ZIP)
+#
+#class TestLayerOnZipStorage(unittest_layer.TestLayer):
+# def setUp(self):
+# self.store = zipstorage.ZipStorage(LAYER_TMP_ZIP,"w")
+#
+# def tearDown(self):
+# self.store.close()
+# remove_if_exists(LAYER_TMP_ZIP)
+#
+#class TestCompositeLayerOnZipStorage(unittest_layer.TestCompositeLayer):
+# def setUp(self):
+# self.store = zipstorage.ZipStorage(LAYER_TMP_ZIP,"w")
+#
+# def tearDown(self):
+# self.store.close()
+# remove_if_exists(LAYER_TMP_ZIP)
- def test_list_content(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- res = layer.open_resource("content/bar/test.txt","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("content/foo.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("root.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(layer.list_content(),['content/foo.confml', 'content/bar/test.txt'])
- shutil.rmtree("temp/layertest")
-
- def test_list_doc(self):
- store = self.storage_class("temp/layertest","w")
- layer = api.Layer(store, "foo")
- res = layer.open_resource("doc/bar/test.txt","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("doc/foo.confml","w")
- res.write("foo.conf")
- res.close()
- res = layer.open_resource("root.confml","w")
- res.write("foo.conf")
- res.close()
- self.assertEquals(layer.list_doc(),['doc/foo.confml', 'doc/bar/test.txt'])
- shutil.rmtree("temp/layertest")
if __name__ == '__main__':
- unittest.main()
-
+ unittest.main()
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_filestorage_vs_zipstorage.py
--- a/configurationengine/source/cone/storage/tests/unittest_filestorage_vs_zipstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_filestorage_vs_zipstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,7 +21,6 @@
import unittest
import sys, os, shutil
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_metadata.py
--- a/configurationengine/source/cone/storage/tests/unittest_metadata.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_metadata.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,7 +18,7 @@
"""
Test the CPF metadata file parsing routines
"""
-import os, sys, unittest
+import os, unittest
try:
from cElementTree import ElementTree
except ImportError:
@@ -30,9 +30,7 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
-
-from cone.public import utils, exceptions, api
+from cone.public import exceptions
from cone.storage import metadata, stringstorage
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
emptytestdata = ''\
@@ -64,7 +62,7 @@
m = metadata.MetadataReader().fromstring(testdata)
self.assertTrue(m)
- def test_create_meta_fromstring(self):
+ def test_create_meta_fromstring_test_has_key(self):
m = metadata.MetadataReader().fromstring(testdata)
self.assertTrue(m.data.has_key('cpf.name'))
self.assertTrue(m.data.has_key('cpf.description'))
@@ -125,6 +123,12 @@
meta2 = metadata.MetadataReader().fromstring(str)
self.assertEqual(meta.data,meta2.data)
+ def test_metadata_write_with_empty_data(self):
+ meta = metadata.Metadata()
+ str = metadata.MetadataWriter().tostring(meta)
+ meta2 = metadata.MetadataReader().fromstring(str)
+ self.assertEqual(meta.data,meta2.data)
+
def test_incorrect_class_fails(self):
try:
class dummy:
@@ -137,9 +141,10 @@
def test_set_property(self):
elem = ElementTree.Element('property')
- prop = metadata.MetadataWriter().set_property(elem,'test','foof')
- self.assertTrue(prop.get('name'),'test')
- self.assertTrue(prop.get('value'),'foof')
+ mwriter = metadata.MetadataWriter()
+ prop_elem = mwriter.set_property(elem,'test','foof')
+ self.assertTrue(prop_elem.get('name'),'test')
+ self.assertTrue(prop_elem.get('value'),'foof')
def test_set_property_with_only_key(self):
elem = ElementTree.Element('property')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_resource.py
--- a/configurationengine/source/cone/storage/tests/unittest_resource.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_resource.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
import unittest
import string
import sys,os
-import __init__
from cone.public.api import Resource
from cone.storage.stringstorage import StringResource
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_stringstorage.py
--- a/configurationengine/source/cone/storage/tests/unittest_stringstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_stringstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,7 +18,6 @@
import string
import sys,os
import pickle
-import __init__
from cone.public import api
from cone.storage import stringstorage
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_webstorage.py
--- a/configurationengine/source/cone/storage/tests/unittest_webstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_webstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,19 +15,14 @@
#
import unittest
-import string
-import sys,os
-import pickle
-import time
-import __init__
+import os
-from cone.public import api, exceptions
from cone.storage import webstorage
from cone.carbon import model
import simplewebserver
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-TEST_SERVER = simplewebserver.SimpleWebServer(os.path.join(ROOT_PATH,'carbondata'), 8001)
+#TEST_SERVER = simplewebserver.SimpleWebServer(os.path.join(ROOT_PATH,'carbondata'), 8001)
#
#def runserver():
# if not TEST_SERVER.active:
@@ -102,9 +97,15 @@
self.assertEquals(rc.get_resource_link('test.confml'), 'test.configurationroot')
self.assertEquals(rc.get_resource_link('featurelists/test.confml'), 'test.featurelist')
self.assertEquals(rc.get_resource_link('test/root.confml'), 'test.configurationlayer')
+
+
+class TestCarbonExtapi(unittest.TestCase):
+ def test_username_password(self):
+ extapi = webstorage.CarbonExtapi("/")
+ self.assertNotEqual(extapi,None)
+ self.assertNotEqual(extapi.get_username(),"")
-
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_webstorage_carbon.py
--- a/configurationengine/source/cone/storage/tests/unittest_webstorage_carbon.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_webstorage_carbon.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,7 +19,6 @@
import sys,os
import pickle
import time
-import __init__
from cone.public import api, exceptions
from cone.storage import webstorage
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_zipresource.py
--- a/configurationengine/source/cone/storage/tests/unittest_zipresource.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_zipresource.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,14 +21,11 @@
import zipfile
import unittest
-import string
-import sys,os,shutil
+import os,shutil
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-import __init__
-from cone.public.exceptions import *
-from cone.public.api import Resource
+from cone.public import exceptions
from cone.storage import zipstorage
TEMP_DIR = os.path.join(ROOT_PATH, 'temp')
@@ -99,7 +96,7 @@
store = zipstorage.ZipStorage(ZIPFILE, "w")
res = store.open_resource("test_getsize.txt", "w")
res.write("Writing foobar")
- self.assertRaises(StorageException, res.get_size)
+ self.assertRaises(exceptions.StorageException, res.get_size)
res.close()
store.close()
@@ -116,4 +113,4 @@
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/tests/unittest_zipstorage.py
--- a/configurationengine/source/cone/storage/tests/unittest_zipstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/tests/unittest_zipstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,14 +19,11 @@
Test the CPF root file parsing routines
"""
-import zipfile
import unittest
-import string
-import sys,os,shutil
+import os,shutil
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-import __init__
from cone.public import exceptions, api
from cone.storage import zipstorage
@@ -95,7 +92,7 @@
self.assertTrue(res)
self.assertTrue(isinstance(res,api.Resource))
res.close()
- self.assertEquals(storage.list_resources("",True), ['data/newfile.txt'])
+ self.assertEquals(storage.list_resources("",recurse=True), ['data/newfile.txt'])
storage.close()
os.unlink("testnewfile.zip")
@@ -127,7 +124,7 @@
res.close()
res = storage.open_resource("data/ncp11/confml/jallaa.confml","w")
res.close()
- file_array = storage.list_resources("data",True)
+ file_array = storage.list_resources("data",recurse=True)
self.assertEquals(file_array,['data/foo/morestuff.confml', 'data/prodX.confml', 'data/ncp11/confml/jallaa.confml'])
storage.close()
os.unlink("testrecurse.zip")
@@ -185,13 +182,13 @@
res.close()
storage.close()
storage2 = api.Storage.open("testdelete.zip","a")
- #self.assertEquals(storage2.list_resources("",True), ['.metadata', 'data/newfile.txt', 'readme.txt'])
+ #self.assertEquals(storage2.list_resources("",recurse=True), ['.metadata', 'data/newfile.txt', 'readme.txt'])
self.assertEquals(storage2.open_resource("data/newfile.txt").read(),"test write")
storage2.delete_resource("data/newfile.txt")
- self.assertEquals(len(storage2.list_resources("",True)),2)
+ self.assertEquals(len(storage2.list_resources("",recurse=True)),2)
storage2.close()
storage3 = api.Storage.open("testdelete.zip","a")
- self.assertEquals(storage3.list_resources("",True), ['readme.txt','.metadata'])
+ self.assertEquals(storage3.list_resources("",recurse=True), ['readme.txt','.metadata'])
storage3.close()
os.unlink("testdelete.zip")
@@ -210,7 +207,7 @@
self.assertEquals(storage2.is_folder("data"),True)
self.assertEquals(storage2.is_folder("data2/folder1"),True)
self.assertEquals(storage2.is_folder("data3"),True)
- self.assertEquals(storage2.list_resources('.',True),['test.txt','.metadata'])
+ self.assertEquals(storage2.list_resources('.',recurse=True),['test.txt','.metadata'])
self.assertEquals(storage2.list_resources(''),['test.txt','.metadata'])
storage2.close()
os.unlink("empty_folder.zip")
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/webstorage.py
--- a/configurationengine/source/cone/storage/webstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/webstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -28,7 +28,7 @@
import posixpath
from cone.public import *
-from cone.carbon import persistentjson, model
+from cone.carbon import persistentjson, model, resourcemapper
from cone.storage import authenticate
class WebStorage(api.Storage):
@@ -55,9 +55,9 @@
try:
object_type = object.meta.get('type')
except (TypeError,AttributeError):
- logging.getLogger('cone').error('Cannot dump configuration %s to webstorage without a type.' % path)
+ logging.getLogger('cone').info('Cannot dump configuration %s to webstorage without a type.' % path)
return False
- carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path)
+ carbonpath = resourcemapper.CarbonResourceMapper().map_confml_resource(object_type, path)
if object_type == 'featurelist':
# Create a featurelist
success = self.extapi.create_featurelist(carbonpath, object)
@@ -93,7 +93,11 @@
"""
if not self._resource_cache:
self._resource_cache = ResourceCache()
- reslist = self.extapi.list_resources("/", True)
+ try:
+ reslist = self.extapi.list_resources("/", True)
+ except urllib2.HTTPError, e:
+ print e
+ return []
# Append all resources to resource cache
for res in reslist:
self._resource_cache.add_resource(res)
@@ -103,7 +107,7 @@
# self._resource_cache.add_featurelist(res)
return self._resource_cache
- def list_resources(self,path, recurse=False, empty_folders=False):
+ def list_resources(self,path, **kwargs):
"""
find the resources under certain path/path
@param path : reference to path where resources are searched
@@ -112,7 +116,7 @@
@param empty_folders: parameters that defined whether empty folders are included. This parameter is ignored
in WebStorage.
"""
- return self.resource_cache.list_resources(path,recurse)
+ return self.resource_cache.list_resources(path, kwargs.get('recurse', False))
def open_resource(self,path,mode="r"):
@@ -141,7 +145,14 @@
raise exceptions.NotResource("The given resource is not found %s" % path)
def is_resource(self,path):
- return self.resource_cache.is_resource(path)
+ ret= self.resource_cache.is_resource(path)
+ if not ret:
+ try:
+ mapped = self.resource_cache.get_mapped_resource(path)
+ ret = self.extapi.is_resource(mapped)
+ except Exception:
+ pass
+ return ret
# path = path.replace(".confml", ".configuration")
# path = utils.resourceref.join_refs([self.get_current_path(), path])
# try:
@@ -191,19 +202,23 @@
if self.get_mode(self.mode) != api.Storage.MODE_READ:
if self.resource_cache.get_resource_link(path):
path = self.resource_cache.get_resource_link(path)
+ elif self.is_resource(path):
+ path = self.resource_cache.get_mapped_resource(path)
else:
""" otherwise create the new resource first before update"""
if self._create_resource(path, object):
path = self.resource_cache.get_resource_link(path)
else:
# Creation failed
- logging.getLogger('cone').error('Creation of %s resource failed' % path)
+ logging.getLogger('cone').info('Creation of %s resource failed' % path)
return
data = persistentjson.dumps(object)
self.extapi.update_resource(path, data)
else:
raise exceptions.StorageException("Cannot dump object to readonly storage")
return
+
+
def load(self, path):
"""
@@ -298,21 +313,20 @@
if len(pathelems) > 1:
self.service_path = pathelems[1]
self._username = kwargs.get('username', None)
- self._password = kwargs.get('password', None)
+ self._password = kwargs.get('password', None)
authhandler = authenticate.CarbonAuthHandler()
- authhandler.add_password(self.username, self.password)
+ authhandler.add_username_func(self.get_username)
+ authhandler.add_password_func(self.get_password)
self.conn = urllib2.build_opener(urllib2.HTTPCookieProcessor, authhandler, urllib2.ProxyHandler({}))
- @property
- def username(self):
+ def get_username(self):
if self._username == None:
self._username = getpass.getuser()
return self._username
- @property
- def password(self):
+ def get_password(self):
if self._password == None:
- self._password = getpass.getpass()
+ self._password = getpass.getpass("Password (%s):" % self._username)
return self._password
def checklogin(self):
@@ -389,14 +403,29 @@
resp = self.conn.open(req)
if resp.code == httplib.OK:
bytes = resp.read()
- reslist = simplejson.loads(bytes)
- return reslist.get('resources',[])
+ if bytes:
+ reslist = simplejson.loads(bytes)
+ return reslist.get('resources',[])
else:
return []
except exceptions.NotFound:
return []
+ def is_resource(self, path):
+ try:
+ query = self._get_action_url('is_resource', path)
+ req = urllib2.Request(query)
+ resp = self.conn.open(req)
+ if resp.code == httplib.OK:
+ reader = persistentjson.HasResourceReader()
+ ret = resp.read()
+ return reader.loads(ret)
+ else:
+ return False
+ except exceptions.NotFound:
+ return False
+
def update_resource(self, path, data):
"""
Update a resource to carbon. The resource can be a CarbonConfiguration or FeatureList object.
@@ -417,7 +446,12 @@
if success:
logging.getLogger('cone').info('Carbon update succeeds to path %s.' % (respdata.get('path')))
else:
- logging.getLogger('cone').error('Carbon update %s failed %s' % (path,respdata.get('errors')))
+ logging.getLogger('cone').error('Carbon update %s failed!' % (path))
+ if respdata.get('errors'):
+ formatted_err = ""
+ for error in respdata.get('errors'):
+ formatted_err += "%s: %s\n" % (error,respdata.get('errors')[error])
+ logging.getLogger('cone').info('Carbon update to path %s returned %s' % (respdata.get('path'),formatted_err))
return success
else:
logging.getLogger('cone').error('Carbon update %s failed %s: %s' % (path,resp.code, resp))
@@ -558,7 +592,7 @@
"""
Add a resource
"""
- confmlpath = persistentjson.CarbonResourceMapper().map_carbon_resource(resourcepath)
+ confmlpath = resourcemapper.CarbonResourceMapper().map_carbon_resource(resourcepath)
self._cache[confmlpath] = resourcepath
def list_resources(self, path, recurse=False):
@@ -599,7 +633,7 @@
object_type = 'configurationlayer'
else:
object_type = 'configurationroot'
- carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path)
+ carbonpath = resourcemapper.CarbonResourceMapper().map_confml_resource(object_type, path)
return carbonpath
def add_resource_link(self,link, path):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/storage/zipstorage.py
--- a/configurationengine/source/cone/storage/zipstorage.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/storage/zipstorage.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,6 +13,7 @@
#
# Description:
#
+import shutil
import zipfile,zlib, StringIO, os, logging
import datetime
@@ -29,7 +30,7 @@
except ImportError:
from xml.etree import ElementTree
-from cone.public import api, utils, persistence, exceptions
+from cone.public import api, utils, persistence, exceptions, parsecontext
from cone.public.api import Resource, Storage, Configuration, Folder
from cone.storage import metadata, common
from cone.confml import persistentconfml
@@ -46,8 +47,7 @@
"""
A storage for zip file
"""
- TEMP_FILE = '_temp_%i.zip' % os.getpid()
- def __init__(self, path ,mode, **kwargs):
+ def __init__(self, path, mode, **kwargs):
"""
Open the given filename object as a cpf zipfile
"""
@@ -61,11 +61,16 @@
# If opening the file in read/append mode check that the given file is a zipfile
if self.get_mode(mode) != self.MODE_WRITE:
if os.path.exists(path) and not zipfile.is_zipfile(path):
- raise ZipException("The file %s is not a zip file!" % path)
+ raise ZipException("The file %s is not a zip file!" % path)
+ # If creating a new file make sure that the path to the file exists
+ elif self.get_mode(mode) in (self.MODE_APPEND, self.MODE_WRITE):
+ dirname = os.path.dirname(path)
+ if dirname != '' and not os.path.exists(dirname):
+ os.makedirs(dirname)
self.zipfile = zipfile.ZipFile(path,self.mode,self.compression)
except IOError,e:
raise ZipException("ZipFile open error: %s" % e)
- super(ZipStorage, self).__init__(path)
+ super(ZipStorage, self).__init__(path, mode)
def _zippath(self, path):
"""
@@ -140,7 +145,7 @@
except KeyError:
return False
- def list_resources(self,path,recurse=False, empty_folders=False):
+ def list_resources(self, path, **kwargs):
"""
Get an array of files in a folder
"""
@@ -153,19 +158,20 @@
(filepath,filename) = os.path.split(name)
curname = utils.resourceref.replace_dir(name, self.get_current_path(),'')
# return directories only if specified
- if empty_folders == True or not self.is_dir(name):
+ if kwargs.get('empty_folders', False) == True or not self.is_dir(name):
# Skip the filename if it is marked as deleted
if self.__has_open__(name) and self.__get_open__(name)[-1].get_mode() == api.Storage.MODE_DELETE:
continue
if filepath == fullpath:
retarray.append(curname)
- elif recurse and filepath.startswith(fullpath):
+ elif kwargs.get('recurse', False) and filepath.startswith(fullpath):
retarray.append(curname)
#retarray = sorted(utils.distinct_array(retarray))
return retarray
def import_resources(self,paths,storage,empty_folders=False):
for path in paths:
+ path = utils.resourceref.remove_begin_slash(utils.resourceref.norm(path))
if not storage.is_resource(path) and empty_folders==False:
logging.getLogger('cone').warning("The given path is not a Resource in the storage %s! Ignoring from export!" % path)
continue
@@ -281,14 +287,15 @@
if self.modified:
oldfile = None
newzipfile = None
- tmp_path = os.path.join(tempfile.gettempdir(), self.TEMP_FILE)
- os.rename(self.path, tmp_path)
+ fh, tmp_path = tempfile.mkstemp(suffix='.zip')
+ shutil.move(self.path, tmp_path)
oldfile = zipfile.ZipFile(tmp_path,"r")
newzipfile = zipfile.ZipFile(self.path,"w",self.compression)
for fileinfo in oldfile.infolist():
newzipfile.writestr(fileinfo, oldfile.read(fileinfo.filename))
if oldfile: oldfile.close()
if newzipfile: newzipfile.close()
+ os.close(fh)
os.unlink(tmp_path)
self.zipfile = None
else:
@@ -322,13 +329,15 @@
if self.is_resource(path):
res = self.open_resource(path,"r")
# read the resource with persistentmodule
+ parsecontext.get_confml_context().current_file = path
try:
obj = self.persistentmodule.loads(res.read())
obj.set_path(path)
res.close()
return obj
except exceptions.ParseError,e:
- logging.getLogger('cone').error("Resource %s parsing failed with exception: %s" % (path,e))
+ parsecontext.get_confml_context().handle_exception(e)
+ #logging.getLogger('cone').error("Resource %s parsing failed with exception: %s" % (path,e))
# returning an empty config in case of xml parsing failure.
return api.Configuration(path)
else:
@@ -372,6 +381,6 @@
def get_content_info(self):
if self.content_info == None:
- self.content_info = utils.make_content_info(self, self.handle.getvalue())
+ self.content_info = api.make_content_info(self, self.handle.getvalue())
return self.content_info
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/test.xml
--- a/configurationengine/source/cone/test.xml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/cone/test.xml Tue Aug 10 14:29:28 2010 +0300
@@ -9,6 +9,7 @@
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+#
+# 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:
+#
+
+import sys,os
+
+__all__ = []
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+#
+# 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:
+#
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/confml.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/confml.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,233 @@
+#
+# 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:
+#
+
+import logging
+
+from cone.public import api, exceptions, container, utils
+from cone.confml import model
+
+from cone.validation.confmlvalidation import ValidatorBase, FixerBase
+
+class SettingValidatorBase(ValidatorBase):
+ """
+ Base class for validators that validate ConfML settings
+ (sub-classes of cone.confml.model.ConfmlSetting).
+ """
+ def validate(self):
+ for ref, feature in self.context.feature_dict.iteritems():
+ if isinstance(feature._obj, model.ConfmlSetting):
+ self.validate_setting(ref, feature)
+
+ def validate_setting(self, ref, setting):
+ raise NotImplementedError()
+
+class LengthConstraintValidator(SettingValidatorBase):
+ """
+ Validator for validating xs:length, xs:minLength and xs:maxLength
+ constraints on setting data values.
+ """
+ PROBLEM_TYPES = ['model.confml.invalid_value.length',
+ 'model.confml.invalid_value.minlength',
+ 'model.confml.invalid_value.maxlength']
+
+ def validate_setting(self, ref, setting):
+ if setting.length:
+ value = setting.get_value()
+ if isinstance(value, basestring) and len(value) != setting.length:
+ self._add_problem(
+ setting = setting,
+ msg = "Setting %s: Exact number of characters must be %s (value has %s)" % (ref, setting.length, len(value)),
+ prob_type = self.PROBLEM_TYPES[0])
+
+ if setting.minLength:
+ value = setting.get_value()
+ if isinstance(value, basestring) and len(value) < setting.minLength:
+ self._add_problem(
+ setting = setting,
+ msg = "Setting %s: Minimum number of characters is %s (value has %s)" % (ref, setting.minLength, len(value)),
+ prob_type = self.PROBLEM_TYPES[1])
+
+ if setting.maxLength:
+ value = setting.get_value()
+ if isinstance(value, basestring) and len(value) > setting.maxLength:
+ self._add_problem(
+ setting = setting,
+ msg = "Setting %s: Maximum number of characters is %s (value has %s)" % (ref, setting.maxLength, len(value)),
+ prob_type = self.PROBLEM_TYPES[2])
+
+ def _add_problem(self, setting, msg, prob_type):
+ dataobj = setting.datas['data'][-1]
+ prob = api.Problem(
+ msg = msg,
+ type = prob_type,
+ line = dataobj.lineno,
+ file = dataobj.get_configuration_path())
+ self.context.problems.append(prob)
+
+class MissingFeatureForDataValidator(ValidatorBase):
+ """
+ Validator for validating data elements that do not have a
+ corresponding feature/setting in the configuration.
+ """
+ PROBLEM_TYPES = ['model.confml.missing_feature_for_data']
+
+ def validate(self):
+ for dataobj in self.context.configuration._traverse(type=api.Data):
+ try:
+ self.context.dview.get_feature(dataobj.fqr)
+ except exceptions.NotFound:
+ prob = api.Problem(
+ msg = "Feature '%s' not found" % dataobj.fqr,
+ type = self.PROBLEM_TYPES[0],
+ line = dataobj.lineno,
+ file = dataobj.get_configuration_path())
+ self.context.problems.append(prob)
+
+class MissingDescriptionValidator(SettingValidatorBase):
+ """
+ Validator for validating missing descriptions in feature/setting in the configuration.
+ """
+ PROBLEM_TYPES = ['model.confml.missing_desc']
+
+ def validate_setting(self, ref, setting):
+ print 'Validating missing desc!'
+ if not setting.desc or setting.desc == '':
+ prob = api.Problem(
+ msg = "Setting/Feature %s: has no description" % (ref),
+ type = self.PROBLEM_TYPES[0],
+ line = setting.lineno,
+ file = setting.get_configuration_path(),
+ severity = api.Problem.SEVERITY_WARNING)
+ self.context.problems.append(prob)
+
+class DuplicateSettingValidator(ValidatorBase):
+ """
+ Validator for validating that there are no settings with same ref in given
+ configuration.
+ """
+ PROBLEM_TYPES = ['model.confml.duplicate.setting']
+
+ def validate(self):
+ settings_container = container.DataContainer()
+ # Traverse through the configuration model and store each feature to
+ # the settings_container.
+ for setting in self.context.configuration._traverse(type=model.ConfmlSetting):
+ settings_container.add_value(setting.fqr, setting)
+ # Go though the settings_container to see if any features have more than one
+ # definition and report those as problems
+ for fqr in settings_container.list_keys():
+ if len(settings_container.get_values(fqr)) > 1:
+ files = [setting.get_configuration_path() for setting in settings_container.get_values(fqr)]
+ prob = api.Problem(
+ msg = "Feature %s has '%s' definitions in files %s" % (fqr, len(settings_container.get_values(fqr)), files),
+ type = self.PROBLEM_TYPES[0],
+ severity = api.Problem.SEVERITY_WARNING,
+ line = settings_container.get_value(fqr).lineno,
+ file = files[-1],
+ problem_data = settings_container.get_values(fqr))
+ self.context.problems.append(prob)
+
+class DuplicateFeatureValidator(ValidatorBase):
+ """
+ Validator for validating that there are no features with same ref in given
+ configuration.
+ """
+ PROBLEM_TYPES = ['model.confml.duplicate.feature']
+
+ def validate(self):
+ settings_container = container.DataContainer()
+ # Traverse through the configuration model and store each feature to
+ # the settings_container.
+ for setting in self.context.configuration._traverse(type=model.ConfmlFeature):
+ settings_container.add_value(setting.fqr, setting)
+ # Go though the settings_container to see if any features have more than one
+ # definition and report those as problems
+ for fqr in settings_container.list_keys():
+ if len(settings_container.get_values(fqr)) > 1:
+ files = [setting.get_configuration_path() for setting in settings_container.get_values(fqr)]
+ prob = api.Problem(
+ msg = "Feature %s has '%s' definitions in files %s" % (fqr, len(settings_container.get_values(fqr)), files),
+ type = self.PROBLEM_TYPES[0],
+ severity = api.Problem.SEVERITY_INFO,
+ line = settings_container.get_value(fqr).lineno,
+ file = files[-1],
+ problem_data = settings_container.get_values(fqr))
+ self.context.problems.append(prob)
+
+class DuplicateSettingFixer(FixerBase):
+ """
+ A Fix class for duplicate settings that removes all but the last definition of the element.
+ """
+ PROBLEM_TYPES = ['model.confml.duplicate.setting']
+
+ def fix(self, context):
+ for problem in self.filter_problems(context.problems, self.PROBLEM_TYPES[0]):
+ logging.getLogger('cone.validation').info("Fixing problem %s" % problem.msg)
+ context.fixes.append("Fixed problem: %s" % problem.msg)
+ # The problem data is expected to have those duplicate settings and the
+ # actual setting as a last element
+ for setting in problem.problem_data[0:-1]:
+ parent_fea = setting.find_parent(type=api.Feature)
+ logging.getLogger('cone.validation').info("Remove setting %s from %s" % (setting.fqr, parent_fea.get_configuration_path()))
+ try:
+ parent_fea.remove_feature(setting.ref)
+ except exceptions.NotFound:
+ logging.getLogger('cone.validation').info("Already removed %s from %s" % (setting.ref, parent_fea.get_configuration_path()))
+
+class DuplicateFeatureFixer(FixerBase):
+ """
+ A Fix class for duplicate features that merges all setting under a duplicate feature
+ to the first instance of the feature and removes the duplicates.
+ """
+ PROBLEM_TYPES = ['model.confml.duplicate.feature']
+
+ def fix(self, context):
+ for problem in self.filter_problems(context.problems, self.PROBLEM_TYPES[0]):
+ logging.getLogger('cone.validation').info("Fixing problem %s" % problem.msg)
+ context.fixes.append("Fixed problem: %s" % problem.msg)
+ # The problem data is expected to have those duplicate settings and the
+ # actual setting as a last element
+ target_feature = problem.problem_data[0]
+ target_config = target_feature.find_parent(type=api.Configuration)
+ for feature in problem.problem_data[1:]:
+ logging.getLogger('cone.validation').info("Move settings from Feature %s in %s to %s" % \
+ (feature.fqr, feature.get_configuration_path(), target_feature.get_configuration_path()))
+ for setting_ref in feature.list_features():
+ setting = feature.get_feature(setting_ref)
+ # Get the path from feature to the parent of this setting
+ # (pathto,ref) = utils.dottedref.psplit_ref(setting_ref)
+ if target_feature.has_ref(setting_ref):
+ target_feature.remove_feature(setting_ref)
+ target_feature.add_feature(setting)
+
+ config = feature.find_parent(type=api.Configuration)
+ logging.getLogger('cone.validation').info("Remove feature %s from %s" % (feature.fqr, config.get_full_path()))
+ config.remove_feature(feature.ref)
+
+
+#: List of all built-in ConfML validator classes
+VALIDATOR_CLASSES = [
+ MissingFeatureForDataValidator,
+ LengthConstraintValidator,
+ DuplicateSettingValidator,
+ DuplicateFeatureValidator,
+# MissingDescriptionValidator,
+]
+
+#: List of all built-in ConfML fixer classes
+FIXER_CLASSES = [
+ DuplicateFeatureFixer,
+]
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/implml.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/implml.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,52 @@
+#
+# 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:
+#
+
+from cone.public import api, plugin
+from cone.validation.implmlvalidation import GlobalValidatorBase
+
+class DuplicateTempFeatureRefValidator(GlobalValidatorBase):
+ """
+ Validator for checking for duplicate refs in temporary variable
+ definitions.
+ """
+ PROBLEM_TYPES = ['model.implml.container.duplicate_tempvar']
+
+ def validate(self):
+ # Collect a dictionary of all temporary variable locations,
+ # i.e. (file, lineno) tuples
+ tempvar_locations_by_ref = {}
+ for impl in self.context.all_impls:
+ if isinstance(impl, plugin.ImplContainer):
+ for td in impl._tempvar_defs:
+ lst = tempvar_locations_by_ref.get(td.ref, [])
+ lst.append((impl.ref, td.lineno))
+ tempvar_locations_by_ref[td.ref] = lst
+
+ # Check for duplicates
+ for ref, locations in tempvar_locations_by_ref.iteritems():
+ if len(locations) > 1:
+ for impl_file, lineno in locations:
+ prob = api.Problem(
+ msg = "Duplicate temporary variable ref '%s'" % ref,
+ type = self.PROBLEM_TYPES[0],
+ line = lineno,
+ file = impl_file)
+ self.context.problems.append(prob)
+
+#: List of all built-in ImplML validator classes
+VALIDATOR_CLASSES = [
+ DuplicateTempFeatureRefValidator,
+]
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+#
+# 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:
+#
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/tests/runtests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+#
+# 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:
+#
+
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/tests/unittest_confmlfixer.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/tests/unittest_confmlfixer.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,141 @@
+#
+# 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:
+#
+
+import unittest
+
+from cone.confml import model
+from cone.public import api
+from cone.validation.confmlvalidation import ValidationContext
+from cone.validation.builtinvalidators import confml
+
+class TestConfmlDuplicateSettingFix(unittest.TestCase):
+ def test_duplicate_setting_fix_with_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting1", desc="description two", name="setting new")
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = confml.DuplicateSettingValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1.setting1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+ fixer = confml.DuplicateSettingFixer()
+ fixer.fix(context)
+
+ # revalidation should now report no problems
+ context = ValidationContext(root)
+ valid = confml.DuplicateSettingValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),0, context.problems)
+
+
+class TestConfmlDuplicateFeatureFix(unittest.TestCase):
+ def test_duplicate_setting_fix_with_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting2", desc="description two", name="setting new")
+ fea.add_feature(set2)
+ self.assertEquals(conf1.list_all_features(),['fea1','fea1.setting1'])
+
+ context = ValidationContext(root)
+ valid = confml.DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+ fixer = confml.DuplicateFeatureFixer()
+ fixer.fix(context)
+
+ # revalidation should now report no problems
+ context = ValidationContext(root)
+ valid = confml.DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),0, context.problems)
+ self.assertEquals(conf1.list_all_features(),['fea1','fea1.setting1','fea1.setting2'])
+ self.assertEquals(conf2.list_all_features(),[])
+
+
+ def test_duplicate_setting_fix_with_duplicates_with_options(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ set1.add(api.Option('op1','val1'))
+ set1.add(api.Option('op2','val2'))
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting1", desc="description two", name="setting new")
+ set2.add(api.Option('op3','val3'))
+ set2.add(api.Option('op4','val4'))
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = confml.DuplicateFeatureValidator(context)
+ valid.validate()
+ fixer = confml.DuplicateFeatureFixer()
+ fixer.fix(context)
+
+ set1 = conf1.get_feature('fea1').get_feature('setting1')
+ options = set1.options
+ self.assertEquals(len(options),2,'After fix only options from new setting should be preserved')
+ self.assertEquals(options['val3'].name,'op3')
+ self.assertEquals(options['val4'].name,'op4')
+
+
+ def test_duplicate_feature_fixer_with_sequence_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlSequenceSetting("setting1", desc="description one", name="setting")
+ set1.add_feature(model.ConfmlSetting("sub_setting1", desc="description one", name="sub_setting one"))
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlSequenceSetting("setting1", desc="description one", name="setting")
+ set2.add_feature(model.ConfmlSetting("sub_setting1", desc="description two", name="sub_setting two"))
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = confml.DuplicateFeatureValidator(context)
+ valid.validate()
+
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+ fixer = confml.DuplicateFeatureFixer()
+ fixer.fix(context)
+
+ # revalidation should now report no problems
+ context = ValidationContext(root)
+ valid = confml.DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),0, context.problems)
+ self.assertEquals(conf1.list_all_features(),['fea1',
+ 'fea1.setting1',
+ 'fea1.setting1.sub_setting1'])
+ self.assertEquals(conf2.list_all_features(),[])
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/builtinvalidators/tests/unittest_confmlvalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/builtinvalidators/tests/unittest_confmlvalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,179 @@
+#
+# 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:
+#
+
+import os
+import unittest
+
+from cone.confml import model
+from cone.public import api
+from cone.validation.confmlvalidation import ValidationContext, get_validator_classes
+from cone.validation.builtinvalidators.confml import LengthConstraintValidator, DuplicateSettingValidator, DuplicateFeatureValidator
+
+class TestConfmlValidation(unittest.TestCase):
+ def test_validations_for_duplicate_setting(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting1", desc="description two", name="setting new")
+ fea.add_feature(set2)
+
+ validator_classes = get_validator_classes()
+
+ context = ValidationContext(root)
+ validators = [vc(context) for vc in validator_classes]
+ for validator in validators:
+ validator.validate()
+ self.assertEquals(len(context.problems),2, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1.setting1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+
+ def test_validations_for_lenght_and_duplicate_setting(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting", length="4")
+ fea.add_feature(set1)
+ set1.value = "abcdefg"
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting1", desc="description two", name="setting new")
+ fea.add_feature(set2)
+
+ validator_classes = get_validator_classes()
+
+ context = ValidationContext(root)
+ validators = [vc(context) for vc in validator_classes]
+ for validator in validators:
+ validator.validate()
+ self.assertEquals(len(context.problems),3, context.problems)
+ self.assertEquals(context.problems[0].msg,"Setting fea1.setting1: Exact number of characters must be 4 (value has 7)", context.problems)
+ self.assertEquals(context.problems[1].msg,"Feature fea1.setting1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+
+
+class TestConfmlLenghtValidation(unittest.TestCase):
+ def test_length_constraint_validator_with_empty_context(self):
+ context = ValidationContext(api.Configuration("foo"))
+ valid = LengthConstraintValidator(context)
+ valid.validate()
+ self.assertEquals(context.problems,[])
+
+ def test_length_constraint_validator_with_singe_feature(self):
+ conf = model.ConfmlConfiguration("foo")
+ fea = model.ConfmlStringSetting("test", length="4")
+ conf.add_feature(fea)
+ # Test lenght validation
+ fea.value= "test mee"
+ context = ValidationContext(conf)
+ valid = LengthConstraintValidator(context)
+ valid.validate()
+ self.assertEquals(context.problems[0].type,'model.confml.invalid_value.length')
+ # Test minLenght validation
+ context.problems = []
+ del fea.length
+ fea.minLength = 10
+ valid.validate()
+ self.assertEquals(context.problems[0].type,'model.confml.invalid_value.minlength', context.problems[0])
+ # Test maxLenght validation
+ context.problems = []
+ del fea.minLength
+ fea.maxLength = 4
+ valid.validate()
+ self.assertEquals(context.problems[0].type,'model.confml.invalid_value.maxlength', context.problems[0])
+
+
+class TestConfmlDuplicateSettingValidation(unittest.TestCase):
+ def test_duplicate_setting_validator_with_no_duplicates(self):
+ conf = model.ConfmlConfiguration("dummy_conf")
+ fea = conf.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ set2 = model.ConfmlStringSetting("setting2", desc="description two", name="setting")
+ fea.add_feature(set1)
+ fea.add_feature(set2)
+
+ context = ValidationContext(conf)
+ valid = DuplicateSettingValidator(context)
+ valid.validate()
+ self.assertEquals(context.problems,[])
+
+ def test_duplicate_setting_validator_with_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting1", desc="description two", name="setting new")
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = DuplicateSettingValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1.setting1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+
+class TestConfmlDuplicateFeatureValidation(unittest.TestCase):
+ def test_duplicate_feature_validator_with_no_duplicates(self):
+ conf = model.ConfmlConfiguration("dummy_conf")
+ fea = conf.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ set2 = model.ConfmlStringSetting("setting2", desc="description two", name="setting")
+ fea.add_feature(set1)
+ fea.add_feature(set2)
+
+ context = ValidationContext(conf)
+ valid = DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(context.problems,[])
+
+ def test_duplicate_feature_validator_with_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlStringSetting("setting1", desc="description one", name="setting")
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlStringSetting("setting2", desc="description two", name="setting new")
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
+
+ def test_duplicate_feature_validator_with_sequence_duplicates(self):
+ root = model.ConfmlConfiguration("dummy_conf")
+ conf1 = root.create_configuration("conf1.confml")
+ fea = conf1.create_feature("fea1")
+ set1 = model.ConfmlSequenceSetting("setting1", desc="description one", name="setting")
+ set1.add_feature(model.ConfmlSetting("sub_setting1", desc="description one", name="sub_setting one"))
+ fea.add_feature(set1)
+ conf2 = root.create_configuration("conf2.confml")
+ fea = conf2.create_feature("fea1")
+ set2 = model.ConfmlSequenceSetting("setting1", desc="description one", name="setting")
+ set2.add_feature(model.ConfmlSetting("sub_setting1", desc="description two", name="sub_setting two"))
+ fea.add_feature(set2)
+
+ context = ValidationContext(root)
+ valid = DuplicateFeatureValidator(context)
+ valid.validate()
+ self.assertEquals(len(context.problems),1, context.problems)
+ self.assertEquals(context.problems[0].msg,"Feature fea1 has '2' definitions in files ['conf1.confml', 'conf2.confml']", context.problems)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/common.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/common.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,84 @@
+#
+# 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:
+#
+
+import sys
+import logging
+import inspect
+
+def load_plugin_classes(entry_point_group, base_class):
+ """
+ Load plugin classes from plug-in entry points.
+
+ @param entry_point_group: Entry point group from which to load
+ classes. Each entry point is expected to be an iterable of
+ plugin class instances.
+ @param base_class: The base class that every loaded class must inherit.
+ @return: List of loaded plugin classes.
+ """
+ log = logging.getLogger('cone')
+ log.setLevel(logging.DEBUG)
+ validator_classes = []
+
+ import pkg_resources
+ working_set = pkg_resources.WorkingSet(sys.path)
+ for entry_point in working_set.iter_entry_points(entry_point_group):
+ class_list = entry_point.load()
+
+ # Make sure that the class list is a list
+ try:
+ class_list = [c for c in class_list]
+ except:
+ log.warn("Entry point %s:%s is not iterable (%r)" % (entry_point_group, entry_point.name, class_list))
+ continue
+
+ for i, cls in enumerate(class_list):
+ if not inspect.isclass(cls):
+ log.warn("Object %d from entry point %s:%s is not a class (%r)" % (i, entry_point_group, entry_point.name, cls))
+ elif not issubclass(cls, base_class):
+ log.warn("Object %d from entry point %s:%s is not a sub-class of %s.%s (%r)" \
+ % (i, entry_point, entry_point.name,
+ base_class.__module__,
+ base_class.__name__,
+ cls))
+ else:
+ msg = "Validator class %r loaded from egg entry point %s:%s, item %d" % (cls, entry_point_group, entry_point.name, i)
+ log.debug(msg)
+ #print msg
+ validator_classes.append(cls)
+
+ return validator_classes
+
+def filter_classes(classes, filter):
+ """
+ Filter the given list of validator by the given ProblemTypeFilter object.
+
+ @param classes: The class list for filter. Each
+ class is assumed to have a PROBLEM_TYPES attribute that defines
+ an iterable of the types of problems that the problem yields.
+ @param filter: The filter object to use. Can be None, in which case
+ the class list is simply returned back.
+ @return: The filtered list.
+ """
+ if filter == None:
+ return classes
+ else:
+ result = []
+ for klass in classes:
+ for problem_type in klass.PROBLEM_TYPES:
+ if filter.match(problem_type):
+ result.append(klass)
+ break
+ return result
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/XInclude.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/XInclude.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/XMLSchema.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/XMLSchema.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2358 @@
+
+
+
+
+
+ Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp
+ Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp
+
+
+
+
+
+ The schema corresponding to this document is normative,
+ with respect to the syntactic constraints it expresses in the
+ XML Schema language. The documentation (within <documentation> elements)
+ below, is not normative, but rather highlights important aspects of
+ the W3C Recommendation of which this is a part
+
+
+
+
+ The simpleType element and all of its members are defined
+ towards the end of this schema document
+
+
+
+
+
+ Get access to the xml: attribute groups for xml:lang
+ as declared on 'schema' and 'documentation' below
+
+
+
+
+
+
+
+ This type is extended by almost all schema types
+ to allow attributes from other namespaces to be
+ added to user schemas.
+
+
+
+
+
+
+
+
+
+
+
+
+ This type is extended by all types which allow annotation
+ other than <schema> itself
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This group is for the
+ elements which occur freely at the top level of schemas.
+ All of their types are based on the "annotated" type by extension.
+
+
+
+
+
+
+
+
+
+
+
+
+ This group is for the
+ elements which can self-redefine (see <redefine> below).
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+ #all or (possibly empty) subset of {extension, restriction}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+ #all or (possibly empty) subset of {extension, restriction, list, union}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for maxOccurs
+
+
+
+
+
+
+
+
+
+
+
+ for all particles
+
+
+
+
+
+
+ for element, group and attributeGroup,
+ which both define and reference
+
+
+
+
+
+
+
+ 'complexType' uses this
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This branch is short for
+ <complexContent>
+ <restriction base="xs:anyType">
+ ...
+ </restriction>
+ </complexContent>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Will be restricted to required or forbidden
+
+
+
+
+
+ Not allowed if simpleContent child is chosen.
+ May be overriden by setting on complexContent child.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This choice is added simply to
+ make this a valid restriction per the REC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Overrides any setting on complexType parent.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This choice is added simply to
+ make this a valid restriction per the REC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No typeDefParticle group reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+ #all or (possibly empty) subset of {substitution, extension,
+ restriction}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The element element can be used either
+ at the top level to define an element-type binding globally,
+ or within a content model to either reference a globally-defined
+ element or type or declare an element-type binding locally.
+ The ref form is not allowed at the top level.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ group type for explicit groups, named top-level groups and
+ group references
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ group type for the three kinds of group
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This choice with min/max is here to
+ avoid a pblm with the Elt:All/Choice/Seq
+ Particle derivation constraint
+
+
+
+
+
+
+
+
+
+ restricted max/min
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Only elements allowed inside
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ simple type for the value of the 'namespace' attr of
+ 'any' and 'anyAttribute'
+
+
+
+ Value is
+ ##any - - any non-conflicting WFXML/attribute at all
+
+ ##other - - any non-conflicting WFXML/attribute from
+ namespace other than targetNS
+
+ ##local - - any unqualified non-conflicting WFXML/attribute
+
+ one or - - any non-conflicting WFXML/attribute from
+ more URI the listed namespaces
+ references
+ (space separated)
+
+ ##targetNamespace or ##local may appear in the above list, to
+ refer to the targetNamespace of the enclosing
+ schema or an absent targetNamespace respectively
+
+
+
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A subset of XPath expressions for use
+in selectors
+ A utility type, not for public
+use
+
+
+
+ The following pattern is intended to allow XPath
+ expressions per the following EBNF:
+ Selector ::= Path ( '|' Path )*
+ Path ::= ('.//')? Step ( '/' Step )*
+ Step ::= '.' | NameTest
+ NameTest ::= QName | '*' | NCName ':' '*'
+ child:: is also allowed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A subset of XPath expressions for use
+in fields
+ A utility type, not for public
+use
+
+
+
+ The following pattern is intended to allow XPath
+ expressions per the same EBNF as for selector,
+ with the following change:
+ Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The three kinds of identity constraints, all with
+ type of or derived from 'keybase'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+ A public identifier, per ISO 8879
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notations for use within XML Schema schemas
+
+
+
+
+
+
+
+
+ Not the real urType, but as close an approximation as we can
+ get in the XML representation
+
+
+
+
+
+
+
+
+
+ First the built-in primitive datatypes. These definitions are for
+ information only, the real built-in definitions are magic.
+
+
+
+ For each built-in datatype in this schema (both primitive and
+ derived) can be uniquely addressed via a URI constructed
+ as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the datatype
+
+ For example, to address the int datatype, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#int
+
+ Additionally, each facet definition element can be uniquely
+ addressed via a URI constructed as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the facet
+
+ For example, to address the maxInclusive facet, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#maxInclusive
+
+ Additionally, each facet usage in a built-in datatype definition
+ can be uniquely addressed via a URI constructed as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the datatype, followed
+ by a period (".") followed by the name of the facet
+
+ For example, to address the usage of the maxInclusive facet in
+ the definition of int, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#int.maxInclusive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NOTATION cannot be used directly in a schema; rather a type
+ must be derived from it by specifying at least one enumeration
+ facet whose value is the name of a NOTATION declared in the
+ schema.
+
+
+
+
+
+
+
+
+
+ Now the derived primitive types
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pattern specifies the content of section 2.12 of XML 1.0e2
+ and RFC 3066 (Revised version of RFC 1766).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pattern matches production 7 from the XML spec
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pattern matches production 5 from the XML spec
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pattern matches production 4 from the Namespaces in XML spec
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #all or (possibly empty) subset of {restriction, union, list}
+
+
+ A utility type, not for public use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Can be restricted to required or forbidden
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Required at the top level
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Forbidden when nested
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ We should use a substitution group for facets, but
+ that's ruled out because it would allow users to
+ add their own, which we're not ready for yet.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ base attribute and simpleType child are mutually
+ exclusive, but one or other is required
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ itemType attribute and simpleType child are mutually
+ exclusive, but one or other is required
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ memberTypes attribute must be non-empty or there must be
+ at least one simpleType child
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/confml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/confml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,273 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/confml2.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/confml2.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/xlink.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/xlink.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,129 @@
+
+
+
+
+
+ Note this schema is NOT a normative schema - - It contains
+ attribute types derived from all the attribute definitions found in
+ the XLink Recommendation available at
+ http://www.w3.org/TR/2001/REC-xlink-20010627 Section 4.1
+ (http://www.w3.org/TR/2001/REC-xlink-20010627/#N1238) provides a
+ summary of the element types on which the global attributes are
+ allowed, with an indication of whether a value is required or
+ optional.
+
+
+
+ The XLink Element Type Attribute. Note: xml:lang is not
+ required if the value of the type attribute is "title", but provides
+ much of the motivation for title elements in addition to attributes.
+ A W3C XML Schema definition of the xml:lang attribute can be found
+ at: http://www.w3.org/2001/xml.xsd
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Locator Attribute.
+
+
+
+
+ The Arcrole Semantic Attribute.
+
+
+
+
+ The Role Semantic Attribute.
+
+
+
+
+ The Title Semantic Attribute.
+
+
+
+
+ The Show Behavior Attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Actuate Behavior Attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+ The Label Traversal Attribute.
+
+
+
+
+ The From Traversal Attribute.
+
+
+
+
+ The To Traversal Attribute.
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confml_xsd/xml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confml_xsd/xml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,145 @@
+
+
+
+
+
+ See http://www.w3.org/XML/1998/namespace.html and
+ http://www.w3.org/TR/REC-xml for information about this namespace.
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+
+ Note that local names in this namespace are intended to be defined
+ only by the World Wide Web Consortium or its subgroups. The
+ following names are currently defined in this namespace and should
+ not be used with conflicting semantics by any Working Group,
+ specification, or document instance:
+
+ base (as an attribute name): denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.
+
+ id (as an attribute name): denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.
+
+ lang (as an attribute name): denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.
+
+ space (as an attribute name): denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.
+
+ Father (in any context at all): denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+
+ In appreciation for his vision, leadership and dedication
+ the W3C XML Plenary on this 10th day of February, 2000
+ reserves for Jon Bosak in perpetuity the XML name
+ xml:Father
+
+
+
+
+ This schema defines attributes and an attribute group
+ suitable for use by
+ schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
+ attributes on elements they define.
+
+ To enable this, such a schema must import this schema
+ for the XML namespace, e.g. as follows:
+ <schema . . .>
+ . . .
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+ Subsequently, qualified reference to any of the attributes
+ or the group defined below will have the desired effect, e.g.
+
+ <type . . .>
+ . . .
+ <attributeGroup ref="xml:specialAttrs"/>
+
+ will define a type which will schema-validate an instance
+ element with any of those attributes
+
+
+
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ http://www.w3.org/2007/08/xml.xsd.
+ At the date of issue it can also be found at
+ http://www.w3.org/2001/xml.xsd.
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML Schema
+ itself, or with the XML namespace itself. In other words, if the XML
+ Schema or XML namespaces change, the version of this document at
+ http://www.w3.org/2001/xml.xsd will change
+ accordingly; the version at
+ http://www.w3.org/2007/08/xml.xsd will not change.
+
+
+
+
+
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility. See
+ RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
+ at http://www.iana.org/assignments/lang-tag-apps.htm for
+ further information.
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ See http://www.w3.org/TR/xmlbase/ for
+ information about this attribute.
+
+
+
+
+
+ See http://www.w3.org/TR/xml-id/ for
+ information about this attribute.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/confmlvalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/confmlvalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,190 @@
+#
+# 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:
+#
+
+import logging
+
+import cone.validation.common
+
+class ValidationContext(object):
+ def __init__(self, configuration):
+ #: The configuration being validated
+ self.configuration = configuration
+
+ self._dview = None
+ #: The list of validation problems
+ self.problems = []
+ #: The list of fixes executed in the context
+ self.fixes = []
+
+
+ @property
+ def dview(self):
+ """
+ The configuration's default view
+ """
+ if not self._dview:
+ self._dview = self.configuration.get_default_view()
+ return self._dview
+
+ @property
+ def feature_dict(self):
+ """
+ All the configuration's features as a ref -> feature dictionary.
+ """
+ if not hasattr(self, '_feature_dict'):
+ self._feature_dict = {}
+ for fea in self.dview.get_features('**'):
+ self._feature_dict[fea.fqr] = fea
+ return self._feature_dict
+
+class ValidatorBase(object):
+ #: Types of the problems this validator produces
+ PROBLEM_TYPES = None
+
+ def __init__(self, context):
+ self.context = context
+
+ def validate(self):
+ """
+ Method called to validate a configuration.
+ """
+ raise NotImplementedError()
+
+class FixerBase(object):
+ def fix(self, context):
+ """
+ The fix functions takes ValidationContext that is expected to contain a
+ list of Problem objects that it will traverse through and it will try to
+ fix any problem that matches its category.
+ @param context: The ValidationContext object from which problems should be fixed.
+ """
+ raise NotImplementedError()
+
+ def filter_problems(self, problems, problem_type):
+ """
+ A filtering function that returns a list of problems that match to the
+ given problem_type.
+ @param problems: a list of api.Problem objects
+ @param problem_type: a string that represents the problem name. e
+ .g. 'model.confml.duplicate.setting'.
+ """
+ return [problem for problem in problems if problem.type == problem_type]
+
+def get_validator_classes(problem_type_filter=None):
+ """
+ Return a list of all ConfML validator classes that match the given
+ problem type filter (i.e. all validator classes that yield problems
+ that will not be filtered out).
+
+ @param problem_type_filter: The filter, if None, all validator
+ classes will be returned.
+ """
+ classes = []
+
+ # Validators from plug-in entry points
+ classes.extend(cone.validation.common.load_plugin_classes(
+ 'cone.plugins.confmlvalidators',
+ ValidatorBase))
+
+ # Built-in validators
+ from cone.validation.builtinvalidators.confml import VALIDATOR_CLASSES
+ classes.extend(VALIDATOR_CLASSES)
+
+ return cone.validation.common.filter_classes(classes, problem_type_filter)
+
+def get_fixer_classes(problem_type_filter=None):
+ """
+ Return a list of all ConfML fixer classes that match the given
+ problem type filter (i.e. all fixer classes that yield problems
+ that will not be filtered out).
+
+ @param problem_type_filter: The filter, if None, all fixer
+ classes will be returned.
+ """
+ classes = []
+
+ # Validators from plug-in entry points
+ classes.extend(cone.validation.common.load_plugin_classes(
+ 'cone.plugins.confmlfixers',
+ FixerBase))
+
+ # Built-in validators
+ from cone.validation.builtinvalidators.confml import FIXER_CLASSES
+ classes.extend(FIXER_CLASSES)
+
+ return cone.validation.common.filter_classes(classes, problem_type_filter)
+
+def validate_configuration(configuration, validator_classes=None):
+ """
+ Validate the given configuration.
+ @param configuration: The configuration to validate.
+ @param validator_classes: The validator classes to use for the validation.
+ If None, all validator classes will be used.
+ @return: A ValidationContext objects, which contains a list of Problem objects in
+ member variable problems.
+ """
+
+ if validator_classes is None:
+ validator_classes = get_validator_classes()
+
+ context = ValidationContext(configuration)
+ validators = [vc(context) for vc in validator_classes]
+ for validator in validators:
+ try:
+ validator.validate()
+ except Exception, e:
+ from cone.public import utils
+ utils.log_exception(logging.getLogger('cone'),
+ "Error validating configuration: %s: %s" \
+ % (e.__class__.__name__, e))
+ return context
+
+def fix_configuration(configuration, context=None, fixer_classes=None):
+ """
+ Validate the given configuration.
+ @param configuration: The configuration to validate.
+ @param context: The ValidationContext if it has been alread created. With value None
+ The ValidationContext will be created and validated fisrt
+ @param fixer_classes: The fixer classes to use for the validation.
+ If None, all fixer classes will be used.
+ @return: A ValidationContext objects, which contains a list of messaages of fixes that
+ were executed.
+ """
+
+ try:
+ conf = configuration.get_configuration('duplicate_settings1.confml')
+ data1 = conf.data
+ except Exception:
+ pass
+ if context is None:
+ context = validate_configuration(configuration)
+ if fixer_classes is None:
+ fixer_classes = get_fixer_classes()
+
+ try:
+ conf = configuration.get_configuration('duplicate_settings1.confml')
+ data2 = conf.data
+ except Exception:
+ pass
+ for fixer in fixer_classes:
+ try:
+ fixer().fix(context)
+ except Exception, e:
+ from cone.public import utils
+ utils.log_exception(logging.getLogger('cone'),
+ "Error fixing configuration: %s: %s" \
+ % (e.__class__.__name__, e))
+ return context
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/implml_xsd/default-impl-schema-template.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/implml_xsd/default-impl-schema-template.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/implml_xsd/implml-template.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/implml_xsd/implml-template.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,271 @@
+
+
+
+ {% for entry in data -%}
+
+ {% endfor %}
+
+
+
+
+ Defines the root implementation container for a multi-implementation ImplML file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A container element can also contain other common elements affect all implementations defined
+ inside the container.
+ ]]>
+
+
+
+
+ {% for entry in data -%}
+
+ {% endfor -%}
+
+
+
+
+
+
+ The condition should be a simple ConfML setting reference enclosed with ${},
+ e.g. '${MyFeature.MySetting}'. If the value of the setting is equal to the
+ expected value (defined using the 'value' attribute), the implementation
+ container will be entered and the implementations inside executed. Note that
+ the condition is evaluated at the moment the decision to enter the container
+ or not is made.
+ ]]>
+
+
+
+
+
+
+ Defines the expected value for the 'condition' attribute, defaults to 'true'.
+
+
+
+
+
+
+
+
+
+
+
+
+ Overrides the execution phase of the implementations inside the container.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines an implementation tag for the implementations inside the container.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A temporary variable is an ordinary ConfML setting that can be used normally
+ in implementations. Only the most basic ConfML setting types are supported.
+ ]]>
+
+
+
+
+
+
+ The ConfML setting reference of the temporary variable, e.g. 'TempFeature.SomeSetting'.
+
+
+
+
+
+
+ The type of the temporary variable, defaults to 'string'.
+
+
+
+
+
+
+ The initial value of the temporary variable, defaults to an empty string.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines a global temporary variable sequence that can be used in all implementations.
+
+
+
+
+
+
+
+ Defines a sub-setting for the temporary variable sequence.
+
+
+
+
+
+
+
+
+
+
+
+
+ The ConfML setting reference of the temporary variable, e.g. 'SomeSubSetting'.
+
+
+
+
+
+
+ The type of the sub-setting, defaults to 'string'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The override can either be a list of setting refences, or it can specify that setting
+ references are irrelevant for implementation execution.
+ ]]>
+
+
+
+
+
+
+
+ Specifies a single setting reference in the setting reference list.
+
+
+
+
+
+
+
+ Specifies that setting references are irrelevant for the execution of the
+ implementation inside the container (i.e. they are never filtered out
+ based on setting references).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Overrides the output root directory of the implementations inside the container.
+ This can be used e.g. to always generate output under \epoc32\data\
+
+
+
+
+
+
+
+
+
+ Overrides the output sub-directory of the implementations inside the container.
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/implmlvalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/implmlvalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,176 @@
+#
+# 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:
+#
+
+import logging
+
+from cone.public import api, exceptions, plugin, utils, parsecontext
+from cone.validation.parsecontext import ValidationParseContext
+import cone.validation.common
+
+class ValidationContext(object):
+ def __init__(self, configuration):
+ self.configuration = configuration
+ self.problems = []
+
+ #: Flat list of all implementations, including containers
+ self.all_impls = []
+
+class ValidatorBase(object):
+ """
+ Base class for implementation validators.
+
+ NOTE THAT THIS CLASS SHOULD NOT BE DIRECTLY SUB-CLASSED.
+ Sub-class either ImplValidatorBase or GlobalValidatorBase
+ instead.
+ """
+ PROBLEM_TYPES = None
+
+ def __init__(self, context):
+ self.context = context
+
+class ImplValidatorBase(ValidatorBase):
+ """
+ Base class for validators that validate only a single implementation.
+ """
+ SUPPORTED_IMPL_CLASSES = []
+
+ def __init__(self, context, impl):
+ self.context = context
+ self.impl = impl
+
+ def validate(self):
+ """
+ Called to validate an implementation instance.
+ """
+ pass
+
+ def check_feature_reference(self, ref, line, problem_type):
+ """
+ Check that a feature with the given reference exists, and if
+ not, add a problem.
+
+ @param ref: The feature reference to check.
+ @param line: The line number to set to the created problem.
+ @param line: The problem type to set to the created problem.
+ """
+ dview = self.context.configuration.get_default_view()
+ try:
+ dview.get_feature(ref)
+ except exceptions.NotFound:
+ prob = api.Problem(
+ msg = u"Setting '%s' not found in configuration" % ref,
+ type = problem_type,
+ line = line,
+ file = self.impl.ref)
+ self.context.problems.append(prob)
+
+class GlobalValidatorBase(ValidatorBase):
+ """
+ Base class for validators that validate the entire implementation set at once.
+ """
+ def validate(self):
+ pass
+
+def get_validator_classes(problem_type_filter=None):
+ """
+ Return a list of all ImplML validator classes that match the given
+ problem type filter (i.e. all validator classes that yield problems
+ that will not be filtered out).
+
+ @param problem_type_filter: The filter, if None, all validator
+ classes will be returned.
+ """
+ classes = []
+
+ # Validators from plug-in entry points
+ classes.extend(cone.validation.common.load_plugin_classes(
+ 'cone.plugins.implvalidators',
+ ValidatorBase))
+
+ # Built-in validators
+ from cone.validation.builtinvalidators.implml import VALIDATOR_CLASSES
+ classes.extend(VALIDATOR_CLASSES)
+
+ return cone.validation.common.filter_classes(classes, problem_type_filter)
+
+def validate_impl_set(impl_set, configuration, validator_classes=None):
+ """
+ Validate the given implementation set.
+ @param impl_set: The implementations to validate.
+ @param configuration: The configuration used in the validation.
+ @param validator_classes: The validator classes to use for the validation.
+ If None, all validator classes will be used.
+ @return: A list of Problem objects.
+ """
+ context = ValidationContext(configuration)
+ context.all_impls = _get_flat_impl_list(impl_set)
+
+ if validator_classes is None:
+ validator_classes = get_validator_classes()
+
+ # Run global validation first
+ for vc in validator_classes:
+ if issubclass(vc, GlobalValidatorBase):
+ try:
+ validator = vc(context)
+ validator.validate()
+ except Exception, e:
+ utils.log_exception(logging.getLogger('cone'),
+ "Error while validating: %s: %s" \
+ % (e.__class__.__name__, e))
+
+ # Then run validation for individual implementations
+ for impl in context.all_impls:
+ for vc in validator_classes:
+ if issubclass(vc, ImplValidatorBase) and isinstance(impl, vc.SUPPORTED_IMPL_CLASSES):
+ try:
+ validator = vc(context, impl)
+ validator.validate()
+ except Exception, e:
+ utils.log_exception(logging.getLogger('cone'),
+ "Error validating '%s': %s: %s" \
+ % (impl, e.__class__.__name__, e))
+ return context.problems
+
+def _get_flat_impl_list(impl_set):
+ """
+ Return a flat list of all implementations in the given set.
+ """
+ result = []
+ def add_to_result(impl):
+ result.append(impl)
+ if isinstance(impl, plugin.ImplContainer):
+ for sub_impl in impl.impls:
+ add_to_result(sub_impl)
+ for impl in impl_set:
+ add_to_result(impl)
+ return result
+
+def validate_impls(configuration, filter='.*', validator_classes=None):
+ """
+ Validate all implementations in the given configuration.
+ @param filter: Regex for filtering the implementations to validate.
+ @param validator_classes: The validator classes to use for the validation.
+ If None, all validator classes will be used.
+ """
+ # Set up the parse context to collect problems from the parsing phase
+ context = ValidationParseContext()
+ parsecontext.set_implml_context(context)
+
+ impl_set = plugin.get_impl_set(configuration, filter=filter)
+ problems = validate_impl_set(impl_set, configuration, validator_classes)
+
+ return context.problems + problems
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/parsecontext.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/parsecontext.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,35 @@
+#
+# 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:
+#
+
+from cone.public import api, parsecontext
+
+class ValidationParseContext(parsecontext.ParseContext):
+ """
+ Parse context that collects all exceptions and problems that
+ occur during parsing into a problem list.
+ """
+ def __init__(self):
+ parsecontext.ParseContext.__init__(self)
+ self.problems = []
+
+ def _handle_exception(self, exception, file_path):
+ problem = api.Problem.from_exception(exception)
+ problem.file = file_path
+ self.problems.append(problem)
+
+ def _handle_problem(self, problem, file_path):
+ problem.file = file_path
+ self.problems.append(problem)
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/problem_type_filter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/problem_type_filter.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,88 @@
+#
+# 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:
+#
+
+class ProblemTypeFilter(object):
+ """
+ Class for filtering problem types.
+
+ An instance of this class can be constructed with includes
+ and excludes, and then it can be asked if a certain problem
+ type matches and should be included.
+ """
+ def __init__(self, includes, excludes):
+ self._includes = [Pattern(expr) for expr in includes]
+ self._excludes = [Pattern(expr) for expr in excludes]
+
+ def match(self, problem_type):
+ """
+ Check whether the given problem type matches the filter or not.
+ @return: True if matches (should be included), False if not.
+ """
+ # No filters: always match
+ if not self._includes and not self._excludes:
+ return True
+
+ # Filter out entries that don't match includes
+ if self._includes and not self._match(self._includes, problem_type):
+ return False
+
+ # Filter out entries that match excludes
+ if self._excludes and self._match(self._excludes, problem_type):
+ return False
+
+ return True
+
+ def filter(self, lst, key=lambda item: item.type):
+ result = []
+ for item in lst:
+ if self.match(key(item)):
+ result.append(item)
+ return result
+
+ def _match(self, patterns, problem_type):
+ for p in patterns:
+ if p.match(problem_type):
+ return True
+ return False
+
+class Pattern(object):
+ def __init__(self, pattern):
+ self.elements = pattern.split('.')
+
+ def match(self, problem_type):
+ type_elements = problem_type.split('.')
+ for i in xrange(max(len(type_elements), len(self.elements))):
+ if i < len(type_elements):
+ type_elem = type_elements[i]
+ else:
+ # The pattern is longer than the type, so it cannot
+ # possibly match.
+ # E.g. type = 'foo', pattern = 'foo.bar.baz'
+ return False
+
+ if i < len(self.elements):
+ pattern_elem = self.elements[i]
+ else:
+ # The pattern ends and we have matched so far, so the
+ # type is a sub-type of an included one.
+ # E.g. type = 'foo.bar.baz', pattern = 'foo.bar'
+ return True
+
+ if pattern_elem != '*' and type_elem != pattern_elem:
+ return False
+
+ return True
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/schemavalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/schemavalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,495 @@
+#
+# 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:
+#
+
+import sys, os
+import logging
+import StringIO
+import pkg_resources
+import jinja2
+from cone.public import api, utils, exceptions
+import cone.public.plugin
+
+log = logging.getLogger('cone.schemavalidation')
+
+ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+
+CONFML_SCHEMA_DIR = 'confml_xsd'
+
+SCHEMA_FILES_BY_NAMESPACE = {'http://www.s60.com/xml/confml/1': 'confml.xsd',
+ 'http://www.s60.com/xml/confml/2': 'confml2.xsd'}
+
+_schema_cache = {}
+
+# ============================================================================
+
+def validate_confml_file(config, ref):
+ """
+ Schema-validate the given ConfML file in a configuration.
+ @param config: The configuration.
+ @param ref: The resource reference of the file to validate.
+ @return: A list of api.Problem objects.
+ """
+ return _validate_file(config, ref, validate_confml_data)
+
+def validate_implml_file(config, ref):
+ """
+ Schema-validate the given ImplML file in a configuration.
+ @param config: The configuration.
+ @param ref: The resource reference of the file to validate.
+ @return: A list of api.Problem objects.
+ """
+ return _validate_file(config, ref, validate_implml_data)
+
+def validate_confml_data(data):
+ """
+ Schema-validate the given ConfML data.
+
+ @raise ParseError: Something is wrong with the data (invalid XML,
+ unsupported ConfML namespace or not conforming to the schema)
+ """
+ _validate_data(data, _get_confml_schema_for_namespace, 'xml.confml')
+
+def validate_implml_data(data):
+ """
+ Schema-validate the given ImplML data.
+
+ @raise ParseError: Something is wrong with the data (invalid XML,
+ unsupported ImplML namespace or not conforming to the schema)
+ """
+ _validate_data(data, _get_implml_schema_for_namespace, 'xml.implml')
+
+# ============================================================================
+
+def _validate_file(config, ref, data_validator_func):
+ res = config.get_resource(ref)
+ try: data = res.read()
+ finally: res.close()
+
+ problem = None
+ try:
+ data_validator_func(data)
+ except exceptions.ParseError, e:
+ problem = api.Problem.from_exception(e)
+
+ if problem:
+ problem.file = ref
+ return [problem]
+ else:
+ return []
+
+def _parse_schema(filename, file_data_dict):
+ """
+ Parse a schema using a filename-data dictionary as the source.
+ @param filename: Name of the schema file to parse.
+ @param file_data_dict: Dictionary mapping file names to file data.
+ @return: The parsed schema object.
+ """
+ if filename not in file_data_dict:
+ raise RuntimeError("Could not parse XML schema file '%s', no such file" % filename)
+
+ schema_data = file_data_dict[filename]
+
+ import lxml.etree
+
+ parser = lxml.etree.XMLParser()
+ class Resolver(lxml.etree.Resolver):
+ def resolve(self, url, id, context):
+ if url not in file_data_dict:
+ log.error("Could not resolve schema file '%s', no such file" % url)
+ raise RuntimeError("No file named '%s'" % url)
+ data = file_data_dict[url]
+ return self.resolve_string(data, context)
+ parser.resolvers.add(Resolver())
+
+ try:
+ schema_doc = lxml.etree.fromstring(schema_data, parser=parser)
+ schema = lxml.etree.XMLSchema(schema_doc)
+ except lxml.etree.LxmlError, e:
+ raise RuntimeError(
+ "Error parsing schema file '%s': %s: %s" \
+ % (filename, e.__class__.__name__, str(e)))
+ return schema
+
+def _validate_data(data, schema_resolver_func, xml_parse_problem_type):
+ """
+ Validate the given XML data.
+ @param data: The raw binary data to validate.
+ @param schema_resolver_func: The function used to resolve the
+ schema used for validation. The function is given the namespace
+ of the root element and is supposed to return the schema object
+ and problem type to use, or raise a ParseError.
+ @param xml_parse_problem_type: Problem type to use if XML parsing
+ fails of the data fails.
+
+ @raise ParseError: Something is wrong with the data (invalid XML
+ or not conforming to the schema)
+ """
+ # Find out the XML namespace in the root element
+ try:
+ namespace, _ = utils.xml.get_xml_root(StringIO.StringIO(data))
+ except exceptions.XmlParseError, e:
+ e.problem_type = xml_parse_problem_type
+ raise e
+
+ schema, problem_type = schema_resolver_func(namespace)
+
+ # Parse the XML document
+ import lxml.etree
+ try:
+ doc = lxml.etree.fromstring(data)
+ except lxml.etree.XMLSyntaxError, e:
+ raise exceptions.XmlParseError(
+ "XML parse error on line %d: %s" % (e.position[0], e),
+ problem_lineno = e.position[0],
+ problem_msg = str(e),
+ problem_type = xml_parse_problem_type)
+
+ # Validate the document against the schema
+ if not schema.validate(doc):
+ error = schema.error_log.last_error
+ raise exceptions.XmlSchemaValidationError(
+ "Line %d: %s" % (error.line, error.message),
+ problem_lineno = error.line,
+ problem_msg = error.message,
+ problem_type = problem_type)
+
+
+class UnsupportedNamespaceError(exceptions.ParseError):
+ pass
+
+_confml_schema_file_cache = None
+def get_confml_schema_files():
+ global _confml_schema_file_cache
+ if _confml_schema_file_cache is None:
+ _confml_schema_file_cache = _load_confml_schema_files()
+ return _confml_schema_file_cache
+
+def get_schema_file_data(file):
+ """
+ Return the data of the given XML schema file.
+
+ @raise ValueError: No such schema file exists.
+ """
+ resource_path = CONFML_SCHEMA_DIR + '/' + file
+ if pkg_resources.resource_exists('cone.validation', resource_path):
+ data = pkg_resources.resource_string('cone.validation', resource_path)
+ return data
+ else:
+ msg = "Could not get schema file '%s': Package resource '%s' does not exist" \
+ % (file, resource_path)
+ raise ValueError(msg)
+
+def get_schema_file_for_namespace(namespace):
+ """
+ Return the correct schema file name for the given namespace.
+
+ @param namespace: The namespace for which to get the schema file.
+ @return: The name of the schema file (suitable for calling
+ get_schema_file_data() with), or None if no schema is associated
+ with the namespace.
+ """
+ return SCHEMA_FILES_BY_NAMESPACE.get(namespace, None)
+
+
+def _get_confml_schema_for_namespace(namespace):
+ """
+ Return the correct XML schema and problem type ID for
+ the given ConfML namespace.
+ @return: Tuple (schema, problem_type).
+ """
+ PROBLEM_TYPE = 'schema.confml'
+
+ # Return a cached schema if possible
+ if namespace in _schema_cache:
+ return _schema_cache[namespace], PROBLEM_TYPE
+
+ # Get the schema file and its raw byte data
+ schema_file = get_schema_file_for_namespace(namespace)
+ if schema_file is None:
+ raise exceptions.ConfmlParseError(
+ "Unsupported ConfML namespace '%s'" % namespace)
+ schema_data = get_schema_file_data(schema_file)
+
+ # Parse the schema
+ import lxml.etree
+ parser = lxml.etree.XMLParser()
+ class PackageDataResolver(lxml.etree.Resolver):
+ def resolve(self, url, id, context):
+ data = get_schema_file_data(url)
+ return self.resolve_string(data, context)
+ parser.resolvers.add(PackageDataResolver())
+ schema_doc = lxml.etree.fromstring(schema_data, parser=parser)
+ schema = lxml.etree.XMLSchema(schema_doc)
+
+ _schema_cache[namespace] = schema
+ return schema, PROBLEM_TYPE
+
+def _load_confml_schema_files():
+ files = {}
+ for name in pkg_resources.resource_listdir('cone.validation', CONFML_SCHEMA_DIR):
+ path = CONFML_SCHEMA_DIR + '/' + name
+ if path.lower().endswith('.xsd'):
+ files[name] = pkg_resources.resource_string('cone.validation', path)
+ return files
+
+# ============================================================================
+#
+#
+# ============================================================================
+
+# Reader class list stored here so that it can be used to check if the reader
+# class list changes, and reload the schema files in that case
+_implml_reader_class_list = None
+
+_implml_schema_file_cache = None
+_implml_schema_cache = {}
+
+def _check_reader_class_list():
+ """
+ Check if the reader class list has changed, and clear all caches if so.
+ """
+ global _implml_reader_class_list
+ global _implml_schema_file_cache
+ global _implml_schema_cache
+
+ rc_list = cone.public.plugin.ImplFactory.get_reader_classes()
+ if _implml_reader_class_list is not rc_list:
+ _implml_reader_class_list = rc_list
+ _implml_schema_file_cache = None
+ _implml_schema_cache = {}
+
+def dump_schema_files(dump_dir):
+ CONFML_SCHEMA_DIR = os.path.join(dump_dir, 'confml')
+ IMPLML_SCHEMA_DIR = os.path.join(dump_dir, 'implml')
+ if not os.path.exists(CONFML_SCHEMA_DIR):
+ os.makedirs(CONFML_SCHEMA_DIR)
+ if not os.path.exists(IMPLML_SCHEMA_DIR):
+ os.makedirs(IMPLML_SCHEMA_DIR)
+
+ def dump_files(files, dir):
+ for name, data in files.iteritems():
+ path = os.path.join(dir, name)
+ f = open(path, 'wb')
+ try: f.write(data)
+ finally: f.close()
+
+ dump_files(get_confml_schema_files(), CONFML_SCHEMA_DIR)
+ dump_files(get_implml_schema_files(), IMPLML_SCHEMA_DIR)
+
+class _ImplmlReaderEntry(object):
+ def __init__(self, id, namespace, data, root_elem_name, schema_problem_sub_id):
+ self.id = id
+ self.filename = id + '.xsd'
+ self.namespace = namespace
+ self.data = data
+ self.root_elem_name = root_elem_name
+ self.schema_problem_sub_id = schema_problem_sub_id
+
+def get_implml_schema_files():
+ """
+ Return a dictionary of ImplML schema file data by file name.
+ """
+ global _implml_schema_file_cache
+
+ _check_reader_class_list()
+ if _implml_schema_file_cache is None:
+ _implml_schema_file_cache = _load_implml_schema_files()
+ return _implml_schema_file_cache
+
+def _load_implml_schema_files():
+ result = {}
+ result['implml.xsd'] = _generate_implml_schema_data()
+
+ result['XInclude.xsd'] = pkg_resources.resource_string(
+ 'cone.validation', CONFML_SCHEMA_DIR + '/XInclude.xsd')
+
+ for entry in _get_implml_reader_entries():
+ if entry.data is not None:
+ result[entry.filename] = entry.data
+ else:
+ result[entry.filename] = _generate_default_schema_data(entry)
+ return result
+
+def _get_implml_reader_entries():
+ entries = []
+ for rc in cone.public.plugin.ImplFactory.get_reader_classes():
+ # Skip ImplContainerReader
+ if rc is cone.public.plugin.ImplContainerReader:
+ continue
+
+ entry = _ImplmlReaderEntry(rc.NAMESPACE_ID,
+ rc.NAMESPACE,
+ rc.get_schema_data(),
+ rc.ROOT_ELEMENT_NAME,
+ rc.SCHEMA_PROBLEM_SUB_ID)
+ entries.append(entry)
+ return entries
+
+def _generate_implml_schema_data():
+ template_data = pkg_resources.resource_string('cone.validation', 'implml_xsd/implml-template.xsd')
+ template = jinja2.Template(template_data)
+ data = template.render(data=_get_implml_reader_entries()).encode('utf-8')
+ return data
+
+def _generate_default_schema_data(entry):
+ template_data = pkg_resources.resource_string('cone.validation', 'implml_xsd/default-impl-schema-template.xsd')
+ template = jinja2.Template(template_data)
+ data = template.render(entry=entry).encode('utf-8')
+ return data
+
+def _get_implml_schema_for_namespace(namespace):
+ """
+ Return the correct XML schema and problem type ID for
+ the given ImplML namespace.
+ @return: Tuple (schema, problem_type).
+ """
+ global _implml_schema_cache
+
+ problem_type_sub_id = None
+ filename = None
+ if namespace == 'http://www.symbianfoundation.org/xml/implml/1':
+ filename = 'implml.xsd'
+ problem_type_sub_id = 'implml'
+ else:
+ for entry in _get_implml_reader_entries():
+ if entry.namespace == namespace:
+ filename = entry.filename
+ problem_type_sub_id = entry.schema_problem_sub_id
+ break
+ if filename is None:
+ raise exceptions.ImplmlParseError(
+ "Unsupported ImplML namespace: %s" % namespace)
+
+ # Check reader classes before trying to use the schema cache
+ _check_reader_class_list()
+
+ # Get the schema from cache if possible
+ if filename in _implml_schema_cache:
+ return _implml_schema_cache[filename]
+
+ file_data_dict = get_implml_schema_files()
+ if filename not in file_data_dict:
+ raise exceptions.ImplmlParseError(
+ "ImplML schema file '%s' does not exist!" % filename)
+
+ schema = _parse_schema(filename, file_data_dict)
+ problem_type = 'schema.implml'
+ if problem_type_sub_id:
+ problem_type += '.' + problem_type_sub_id
+ return schema, problem_type
+
+# ============================================================================
+#
+#
+# ============================================================================
+
+class SchemaValidationTestMixin(object):
+ """
+ Mix-in class for providing assertion methods for unittest.TestCase sub-classes
+ testing schema validation.
+ """
+
+ def assert_schemavalidation_succeeds(self, type, dir, namespace=None):
+ """
+ Assert that schema validation succeeds for all the files in the given directory.
+ @param type: Type of the schema validation to perform, can be 'confml' or 'implml'.
+ @param dir: The directory containing the files to validate
+ @param namespace: If not None, specifies the namespace that the root element
+ in all the must have. If any of the files has a different namespace, the
+ assertion fails.
+ """
+ errors = []
+ for file in self._get_files(dir):
+ f = open(file, 'rb')
+ try: data = f.read()
+ finally: f.close()
+
+ if namespace is not None:
+ self._check_root_element_namespace(file, data, namespace)
+
+ validate_data = self._get_validator_function_for_type(type)
+ try:
+ validate_data(data)
+ except Exception, e:
+ errors.append(file)
+ errors.append("Raised: %r" % e)
+
+ if errors:
+ self.fail('\n'.join(errors))
+
+ def assert_schemavalidation_fails(self, type, dir, namespace=None, problem_type=None):
+ """
+ Assert that schema validation fails for all the files in the given directory.
+ @param type: Type of the schema validation to perform, can be 'confml' or 'implml'.
+ @param dir: The directory containing the files to validate
+ @param namespace: If not None, specifies the namespace that the root element
+ in all the must have. If any of the files has a different namespace, the
+ assertion fails.
+ @param: problem_type: If not None, specifies the problem type that the
+ SchemaValidationError raised from validation must contain.
+ """
+ errors = []
+ for file in self._get_files(dir):
+ f = open(file, 'rb')
+ try: data = f.read()
+ finally: f.close()
+
+ if namespace is not None:
+ self._check_root_element_namespace(file, data, namespace)
+
+ validate_data = self._get_validator_function_for_type(type)
+ try:
+ validate_data(data)
+ errors.append(file)
+ except exceptions.XmlSchemaValidationError, e:
+ if problem_type is not None:
+ if e.problem_type != problem_type:
+ errors.append(file)
+ errors.append("Problem type was '%s', expected '%s'" % (e.problem_type, problem_type))
+
+ if errors:
+ self.fail('The following files were reported as valid when they should not have been:\n%s' % '\n'.join(errors))
+
+
+ def _get_files(self, dir):
+ """
+ Return a list of all files in the given directory.
+ @param dir: The directory.
+ @return: List of all files in the dir. Each entry has the
+ also the directory joined to it.
+ """
+ files = []
+ for name in os.listdir(dir):
+ path = os.path.join(dir, name)
+ if os.path.isfile(path):
+ files.append(path)
+ return files
+
+ def _check_root_element_namespace(self, file_path, data, expected_namespace):
+ file_namespace, _ = utils.xml.get_xml_root(StringIO.StringIO(data))
+ if file_namespace != expected_namespace:
+ msg = "Error testing schema validation with file '%s': "\
+ "Root element namespace is not what was expected (expected '%s', got '%s')"\
+ % (file_path, expected_namespace, file_namespace)
+ self.fail(msg)
+
+ def _get_validator_function_for_type(self, type):
+ if type == 'implml':
+ return validate_implml_data
+ elif type == 'confml':
+ return validate_confml_data
+ else:
+ raise ValueError("Invalid schema validation type '%s', should be 'implml' or 'confml'" % type)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+#
+# 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:
+#
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/runtests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+#
+# 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:
+#
+
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_settings1.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_settings1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ Testing desc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fo
+ 1
+ 1
+
+
+
+
+
+ 123
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_settings2.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/fixed_expected/duplicate_settings2.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/data_without_feature.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/data_without_feature.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ foobar
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_settings1.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_settings1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fo
+ 1
+ 1
+
+
+ 123
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_settings2.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/duplicate_settings2.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ Testing desc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/min_max_length.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files/min_max_length.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fo
+ foobar
+ baz
+
+
+
+ foobar
+ ba
+ baztu
+ b
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/data_without_feature.confml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/data_without_feature.confml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+Problem(msg="Feature 'Foo.Bar' not found", type='model.confml.missing_feature_for_data', line=5, file='data_without_feature.confml', severity='error')
+Problem(msg="Feature 'Foo' not found", type='model.confml.missing_feature_for_data', line=4, file='data_without_feature.confml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/duplicate_root.confml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/duplicate_root.confml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+Problem(msg="Feature Feature has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.feature', line=3, file='duplicate_settings2.confml', severity='info')
+Problem(msg="Feature Feature.NoData has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=15, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.One has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=4, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.TestSequence has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=17, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.TestSequence.SeqThree has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=20, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.TestSequence.SeqTwo has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=18, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.Three has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=10, file='duplicate_settings2.confml', severity='warning')
+Problem(msg="Feature Feature.Two has '2' definitions in files ['duplicate_settings1.confml', 'duplicate_settings2.confml']", type='model.confml.duplicate.setting', line=7, file='duplicate_settings2.confml', severity='warning')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/min_max_length.confml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/confml/single_files_expected/min_max_length.confml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+Problem(msg='Setting MinMaxLengthNotOk.Exact1: Exact number of characters must be 3 (value has 5)', type='model.confml.invalid_value.length', line=43, file='min_max_length.confml', severity='error')
+Problem(msg='Setting MinMaxLengthNotOk.Exact2: Exact number of characters must be 3 (value has 1)', type='model.confml.invalid_value.length', line=44, file='min_max_length.confml', severity='error')
+Problem(msg='Setting MinMaxLengthNotOk.Max: Maximum number of characters is 3 (value has 6)', type='model.confml.invalid_value.maxlength', line=41, file='min_max_length.confml', severity='error')
+Problem(msg='Setting MinMaxLengthNotOk.Min: Minimum number of characters is 3 (value has 2)', type='model.confml.invalid_value.minlength', line=42, file='min_max_length.confml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/implml/expected/duplicate_tempvar_ref.implml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/implml/expected/duplicate_tempvar_ref.implml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+Problem(msg="Duplicate temporary variable ref 'Temp.Foo'", type='model.implml.container.duplicate_tempvar', line=4, file='Layer1/implml/duplicate_tempvar_ref.implml', severity='error')
+Problem(msg="Duplicate temporary variable ref 'Temp.Foo'", type='model.implml.container.duplicate_tempvar', line=8, file='Layer1/implml/duplicate_tempvar_ref.implml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/implml/project/Layer1/implml/duplicate_tempvar_ref.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/implml/project/Layer1/implml/duplicate_tempvar_ref.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/implml/project/Layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/model/implml/project/Layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/model/implml/project/root.confml
Binary file configurationengine/source/cone/validation/tests/testdata/model/implml/project/root.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml1/invalid/invalid_type.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml1/invalid/invalid_type.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ test
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/feature1.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/feature1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,112 @@
+
+
+
+ Feature with all supported setting types for ConfML v1.0
+
+ A real setting
+
+
+ An int setting
+
+
+ A string setting
+
+
+ A boolean setting
+
+
+ A selection setting
+
+
+
+
+
+
+
+
+ A multi-selection setting
+
+
+
+
+
+
+
+
+ A sequence setting
+
+ A real sub-setting
+
+
+ An int sub-setting
+
+
+ A string sub-setting
+
+
+ A boolean sub-setting
+
+
+ A selection sub-setting
+
+
+
+
+
+
+
+ A multi-selection sub-setting
+
+
+
+
+
+
+
+
+
+
+ 3.14
+ 10
+ default string
+ true
+ 1
+ "opt 0" "opt 2" "opt 4"
+
+ 1.0
+ 1
+ template
+ false
+ 0
+ "opt 0"
+
+
+ 1.25
+ 128
+ def1
+ false
+ 1
+ "opt 1"
+
+
+ 1.5
+ 256
+ def2
+ false
+ 1
+ "opt 2"
+
+
+
+
+
+
+ true
+ false
+ false
+ true
+ true
+ false
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/feature2.confml
Binary file configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/feature2.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/name_id_mapping_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml1/valid/name_id_mapping_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Entry 1
+ Entry 2
+ Entry 3
+
+
+
+
+
+ Entry 1e 1
+ Entry 2e 2
+ Entry 3e 3
+
+
+
+
+
+ Entry 1100
+ Entry 2120
+ Entry 3130
+
+
+
+
+
+
+ Entry 11.1
+ Entry 21.2
+ Entry 31.3
+
+
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/invalid/invalid_type.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/invalid/invalid_type.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ test
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/basic_setting_types_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/basic_setting_types_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,62 @@
+
+
+
+ Feature with basic setting types (ConfML v2.0)
+
+
+ A real setting
+
+
+
+ An int setting
+
+
+
+ A string setting
+
+
+
+ A boolean setting
+
+
+
+ A selection setting
+
+
+
+
+
+
+
+
+ A multi-selection setting
+
+
+
+
+
+
+
+
+
+
+ 3.14
+ 10
+ default string
+ true
+ 1
+ "opt 0" "opt 2" "opt 4"
+
+
+
+
+
+ true
+ false
+ false
+ true
+ true
+ true
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/file_folder_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/file_folder_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,28 @@
+
+
+
+ Feature with file and folder setting types
+
+ A folder setting
+
+
+
+
+ A file setting
+
+
+
+
+
+
+
+ default_folder
+ default_target_folder/
+
+
+ default_file.txt
+ default_target_folder/default_file_renamed.txt
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/name_id_mapping_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/name_id_mapping_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Entry 1
+ Entry 2
+ Entry 3
+
+
+
+
+
+ Entry 1e 1
+ Entry 2e 2
+ Entry 3e 3
+
+
+
+
+
+ Entry 1100
+ Entry 2120
+ Entry 3130
+
+
+
+
+
+
+ Entry 11.1
+ Entry 21.2
+ Entry 31.3
+
+
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+ none
+ none
+
+
+ 0
+ 0
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/product_root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/product_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/relevant_feature_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/relevant_feature_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,136 @@
+
+
+
+ Feature for testing attribute 'relevant' in a feature.
+
+
+ A real setting
+
+
+
+ An int setting
+
+
+
+ A string setting
+
+
+
+ A boolean setting
+
+
+
+ A selection setting
+
+
+
+
+
+
+
+
+ A multi-selection setting
+
+
+
+
+
+
+
+
+ A folder setting
+
+
+
+
+
+ A file setting
+
+
+
+
+
+ A sequence setting
+
+
+ A real sub-setting
+
+
+
+ An int sub-setting
+
+
+
+ A string sub-setting
+
+
+
+ A boolean sub-setting
+
+
+
+ A selection sub-setting
+
+
+
+
+
+
+
+
+ A multi-selection sub-setting
+
+
+
+
+
+
+
+
+ A folder sub-setting
+
+
+
+
+
+ A file sub-setting
+
+
+
+
+
+
+
+
+ 3.14
+ 10
+ default string
+ true
+ 1
+ "opt 0" "opt 2" "opt 4"
+
+
+ default_folder
+ default_target_folder/
+
+
+ default_file.txt
+ default_target_folder/default_file_renamed.txt
+
+
+
+ 1.25
+ 128
+ def1
+ false
+ 1
+ "opt 1"
+ seq/def1_folder
+ seq/def1_file.txt
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/sequence_setting_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/sequence_setting_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,117 @@
+
+
+
+ Feature with a sequence setting (ConfML v2.0)
+
+
+ A sequence setting
+
+
+ A folder sub-setting
+
+
+
+
+
+ A real sub-setting
+
+
+
+ A file sub-setting
+
+
+
+
+
+ An int sub-setting
+
+
+
+ A string sub-setting
+
+
+
+ A boolean sub-setting
+
+
+
+ A selection sub-setting
+
+
+
+
+
+
+
+
+ A multi-selection sub-setting
+
+
+
+
+
+
+
+
+ A date sub-setting
+
+
+ A time sub-setting
+
+
+ A date-time sub-setting
+
+
+ A duration sub-setting
+
+
+
+
+
+
+
+
+ seq/default_folder
+ 1.0
+ seq/default_file.txt
+ 1
+ template
+ false
+ 0
+ "opt 0"
+ 2009-02-02
+ 07:30:15
+ 2009-02-02-07:00:00
+ P5Y4M3DT12H25M15S
+
+
+ seq/def1_folder
+ 1.25
+ seq/def1_file.txt
+ 128
+ def1
+ false
+ 1
+ "opt 1"
+ 2009-02-02
+ 07:30:15
+ 2009-02-02-07:00:00
+ P5Y4M3DT12H25M15S
+
+
+ seq/def2_folder
+ 1.5
+ seq/def2_file.txt
+ 256
+ def2
+ false
+ 1
+ "opt 2"
+ 2009-02-02
+ 07:30:15
+ 2009-02-02-07:00:00
+ P5Y4M3DT12H25M15S
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/time_types_test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/time_types_test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,26 @@
+
+
+
+ Feature with date-time etc. setting types
+
+ A date setting
+
+
+ A time setting
+
+
+ A date-time setting
+
+
+ A duration setting
+
+
+
+
+ 2009-02-02
+ 07:30:15
+ 2009-02-02-07:00:00
+ P5Y4M3DT12H25M15S
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/view.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/confml2/valid/view.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,81 @@
+
+
+
+ Testing view located on layer 1.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Description from view
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/empty_temp_variable_sequence.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/empty_temp_variable_sequence.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/output_root_dir_without_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/output_root_dir_without_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/output_sub_dir_without_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/output_sub_dir_without_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/phase_without_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/phase_without_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/setting_refs_override_without_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/setting_refs_override_without_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/tag_without_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/tag_without_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/temp_variable_sequence_without_ref.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/temp_variable_sequence_without_ref.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/temp_variable_without_ref.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/invalid/temp_variable_without_ref.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/dummy.dummy1ml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/dummy.dummy1ml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ jee
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/dummy.dummy2ml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/dummy.dummy2ml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ jee
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_all_common_elements.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_all_common_elements.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_condition.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_condition.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_condition_and_value.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/empty_with_condition_and_value.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_1.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_1.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+ jee
+
+
+
+ jee
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_2.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_2.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+ jee
+
+
+
+ jee
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_3.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_3.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+ jee
+
+
+
+ jee2
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_4.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_4.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+ jee
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_5.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/multi_impl_5.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,14 @@
+
+
+
+ jee
+
+
+
+ jee
+
+
+
+ joojaa
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/nested_containers.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/testdata/schema/implml/valid/nested_containers.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+ jee
+
+
+
+ nested dummy 2
+
+
+
+
+
+
+
+ jee
+
+
+
+
+
+
+ still more nesting
+
+
+
+
+
+ jee
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/unittest_confmlfixing.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/unittest_confmlfixing.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,79 @@
+#
+# 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:
+#
+
+import os
+import unittest
+import logging
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata')
+TEMP_DIR = os.path.join(ROOT_PATH, 'temp')
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+import cone.validation.confmlvalidation
+
+class TestConfmlFixing(unittest.TestCase):
+ def test_confml_fixer_filter_problems(self):
+ fixer = cone.validation.confmlvalidation.FixerBase()
+ prbs = [api.Problem("msg1", type="test.foo.bar"),
+ api.Problem("msg2", type="test.foo.bar"),
+ api.Problem("msg3", type="test.foo.faa"),
+ api.Problem("msg4", type="test.foo.bar")]
+ self.assertEquals(len(fixer.filter_problems(prbs,'test.foo.bar')),3)
+
+ def test_get_fixer_classes(self):
+ fixers = cone.validation.confmlvalidation.get_fixer_classes()
+ self.assertEquals(len(fixers),1)
+
+class TestConfmlFixModel(BaseTestCase):
+ def test_fix_duplicates(self):
+ prj_dir = os.path.join(TESTDATA_DIR, 'model/confml/single_files')
+ prj = api.Project(api.Storage.open(prj_dir))
+ conf = prj.get_configuration("duplicate_root.confml")
+ vc = cone.validation.confmlvalidation.fix_configuration(conf)
+ self.assertEqual(len(vc.fixes), 1)
+ self.assertEquals(conf.list_configurations(),['duplicate_settings1.confml',
+ 'duplicate_settings2.confml'])
+ subconf1 = conf.get_configuration('duplicate_settings1.confml')
+ subconf2 = conf.get_configuration('duplicate_settings2.confml')
+ self.assertEquals(subconf2.list_all_features(),[])
+ self.assertEquals(subconf1.list_all_features(),['Feature',
+ 'Feature.One',
+ 'Feature.Two',
+ 'Feature.Three',
+ 'Feature.NoData',
+ 'Feature.TestSequence',
+ 'Feature.TestSequence.SeqTwo',
+ 'Feature.TestSequence.SeqThree'])
+
+class TestConfmlFixingFiles(BaseTestCase):
+
+ def test_export_fixed_configuration_test(self):
+ # Open the file as a configuration
+ prj_dir = os.path.join(TESTDATA_DIR, 'model/confml/single_files')
+ prj = api.Project(api.Storage.open(prj_dir))
+ conf = prj.get_configuration('duplicate_root.confml')
+ vc = cone.validation.confmlvalidation.fix_configuration(conf)
+ self.recreate_dir(os.path.join(TEMP_DIR,'fixed'))
+ rstorage = api.Storage.open(os.path.join(TEMP_DIR,'fixed'), "w")
+ prj.export_configuration(conf, rstorage)
+ rstorage.save()
+ rstorage.close()
+ self.assert_dir_contents_equal(os.path.join(TEMP_DIR,'fixed'),
+ os.path.join(TESTDATA_DIR, 'model/confml/fixed_expected'),
+ ignore=[".metadata", '.svn'])
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/unittest_confmlvalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/unittest_confmlvalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,51 @@
+#
+# 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:
+#
+
+import os
+import unittest
+import logging
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata')
+TEMP_DIR = os.path.join(ROOT_PATH, 'temp')
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+import cone.validation.confmlvalidation
+
+
+class TestConfmlValidation(BaseTestCase):
+
+ def _run_single_file_test(self, filename):
+ # Open the file as a configuration
+ prj_dir = os.path.join(TESTDATA_DIR, 'model/confml/single_files')
+ prj = api.Project(api.Storage.open(prj_dir))
+ conf = prj.get_configuration(filename)
+
+ self.assert_problem_list_equals_expected(
+ actual = cone.validation.confmlvalidation.validate_configuration(conf).problems,
+ expected_file = os.path.join(TESTDATA_DIR, 'model/confml/single_files_expected', filename + '.txt'),
+ outdir = os.path.join(TEMP_DIR, 'confml_model_single_files', filename))
+
+ def test_validate_min_max_length(self):
+ self._run_single_file_test('min_max_length.confml')
+
+ def test_validate_data_without_feature(self):
+ self._run_single_file_test('data_without_feature.confml')
+
+ def test_validate_duplicates(self):
+ self._run_single_file_test('duplicate_root.confml')
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/unittest_implmlvalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/unittest_implmlvalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,46 @@
+#
+# 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:
+#
+
+import os
+import __init__
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata')
+TEMP_DIR = os.path.join(ROOT_PATH, 'temp')
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+import cone.validation.implmlvalidation
+
+class TestImplmlValidation(BaseTestCase):
+
+ def _run_test(self, filename):
+ filepath = 'Layer1/implml/' + filename
+ project_dir = os.path.join(ROOT_PATH, 'testdata/model/implml/project')
+ config = 'root.confml'
+
+ prj = api.Project(api.Storage.open(project_dir))
+ config = prj.get_configuration(config)
+ problems = cone.validation.implmlvalidation.validate_impls(config, filter=filepath + '$')
+
+ self.assert_problem_list_equals_expected(
+ actual = problems,
+ expected_file = os.path.join(ROOT_PATH, 'testdata/model/implml/expected', filename + '.txt'),
+ outdir = os.path.join(ROOT_PATH, 'temp/implml_model', filename))
+
+ def test_validate_duplicate_tempvar_refs(self):
+ self._run_test('duplicate_tempvar_ref.implml')
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/unittest_problem_type_filter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/unittest_problem_type_filter.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,135 @@
+#
+# 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:
+#
+
+import unittest
+
+from cone.public import api
+from cone.validation.problem_type_filter import ProblemTypeFilter
+
+class TestProblemTypeFilter(unittest.TestCase):
+ def test_empty_matches_everything(self):
+ filter = ProblemTypeFilter([], [])
+ self.assertTrue(filter.match(''))
+ self.assertTrue(filter.match('foo'))
+ self.assertTrue(filter.match('foo.bar'))
+ self.assertTrue(filter.match('foo.bar.baz'))
+
+ def test_single_include(self):
+ filter = ProblemTypeFilter(['foo.bar'], [])
+ self.assertFalse(filter.match(''))
+ self.assertFalse(filter.match('foo'))
+ self.assertTrue(filter.match('foo.bar'))
+ self.assertTrue(filter.match('foo.bar.baz'))
+ self.assertFalse(filter.match('bar'))
+
+ def test_single_exclude(self):
+ filter = ProblemTypeFilter([], ['foo.bar'])
+ self.assertTrue(filter.match(''))
+ self.assertTrue(filter.match('foo'))
+ self.assertTrue(filter.match('bar'))
+ self.assertFalse(filter.match('foo.bar'))
+ self.assertFalse(filter.match('foo.bar.baz'))
+
+ def test_include_and_exclude(self):
+ filter = ProblemTypeFilter(['foo'], ['foo.bar.baz'])
+ self.assertFalse(filter.match(''))
+ self.assertTrue(filter.match('foo'))
+ self.assertFalse(filter.match('bar'))
+ self.assertTrue(filter.match('foo.bar'))
+ self.assertFalse(filter.match('foo.bar.baz'))
+ self.assertFalse(filter.match('foo.bar.baz.x'))
+
+ def test_multiple_includes_and_excludes(self):
+ filter = ProblemTypeFilter(['foo', 'boo'], ['foo.bar.baz', 'boo.bar.baz'])
+
+ self.assertFalse(filter.match(''))
+ self.assertFalse(filter.match('bar'))
+
+ self.assertTrue(filter.match('foo'))
+ self.assertTrue(filter.match('foo.bar'))
+ self.assertFalse(filter.match('foo.bar.baz'))
+ self.assertFalse(filter.match('foo.bar.baz.x'))
+
+ self.assertTrue(filter.match('boo'))
+ self.assertTrue(filter.match('boo.bar'))
+ self.assertFalse(filter.match('boo.bar.baz'))
+ self.assertFalse(filter.match('boo.bar.baz.x'))
+
+ def test_wildcard_in_include(self):
+ filter = ProblemTypeFilter(['*.bar'], [])
+
+ self.assertFalse(filter.match('foo'))
+ self.assertFalse(filter.match('boo'))
+ self.assertFalse(filter.match('foo.baz.bar'))
+
+ self.assertTrue(filter.match('foo.bar'))
+ self.assertTrue(filter.match('foo.bar.baz'))
+ self.assertTrue(filter.match('boo.bar'))
+ self.assertTrue(filter.match('boo.bar.baz'))
+
+
+ filter = ProblemTypeFilter(['*.*.baz'], [])
+ self.assertTrue(filter.match('foo.bar.baz'))
+ self.assertTrue(filter.match('boo.bar.baz'))
+
+ self.assertFalse(filter.match('baz'))
+ self.assertFalse(filter.match('foo.baz'))
+
+ def test_wildcard_in_exclude(self):
+ filter = ProblemTypeFilter([], ['*.bar'])
+
+ self.assertTrue(filter.match('foo'))
+ self.assertTrue(filter.match('boo'))
+ self.assertTrue(filter.match('foo.baz.bar'))
+
+ self.assertFalse(filter.match('foo.bar'))
+ self.assertFalse(filter.match('foo.bar.baz'))
+ self.assertFalse(filter.match('boo.bar'))
+ self.assertFalse(filter.match('boo.bar.baz'))
+
+
+ filter = ProblemTypeFilter([], ['*.*.baz'])
+ self.assertFalse(filter.match('foo.bar.baz'))
+ self.assertFalse(filter.match('boo.bar.baz'))
+
+ self.assertTrue(filter.match('baz'))
+ self.assertTrue(filter.match('foo.baz'))
+
+ def test_filter_problems(self):
+ filter = ProblemTypeFilter(['foo'], ['foo.bar.baz'])
+ problems = [api.Problem('', type=''),
+ api.Problem('', type='foo'),
+ api.Problem('', type='bar'),
+ api.Problem('', type='foo.bar'),
+ api.Problem('', type='foo.bar.baz'),
+ api.Problem('', type='foo.bar.baz.x')]
+
+ filtered_problems = filter.filter(problems)
+ self.assertEquals(filtered_problems,
+ [api.Problem('', type='foo'),
+ api.Problem('', type='foo.bar')])
+
+ def test_filter_strings(self):
+ filter = ProblemTypeFilter(['foo'], ['foo.bar.baz'])
+ problems = ['',
+ 'foo',
+ 'bar',
+ 'foo.bar',
+ 'foo.bar.baz',
+ 'foo.bar.baz.x']
+
+ filtered_problems = filter.filter(problems, key=lambda item: item)
+ self.assertEquals(filtered_problems, ['foo', 'foo.bar'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/validation/tests/unittest_schemavalidation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/cone/validation/tests/unittest_schemavalidation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,192 @@
+#
+# 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:
+#
+
+import unittest
+import os
+import StringIO
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api, plugin, utils, exceptions
+from cone.validation import schemavalidation
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+CONFML1_NAMESPACE = 'http://www.s60.com/xml/confml/1'
+CONFML2_NAMESPACE = 'http://www.s60.com/xml/confml/2'
+
+class DummyResource(object):
+ def __init__(self, data):
+ self.data = data
+ def read(self):
+ return self.data
+ def close(self):
+ pass
+
+class DummyConfiguration(object):
+ def __init__(self, resources):
+ self.resources = resources
+
+ def get_resource(self, ref):
+ if ref in self.resources:
+ return DummyResource(self.resources[ref])
+ else:
+ raise exceptions.NotFound("No such resource '%s'!" % ref)
+
+class TestConfmlSchemaValidation(BaseTestCase, schemavalidation.SchemaValidationTestMixin):
+
+ def test_valid_confml2_files(self):
+ self.assert_schemavalidation_succeeds(
+ type = 'confml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/confml2/valid'),
+ namespace = CONFML2_NAMESPACE)
+
+ def test_invalid_confml2_files(self):
+ self.assert_schemavalidation_fails(
+ type = 'confml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/confml2/invalid'),
+ namespace = CONFML2_NAMESPACE)
+
+ def test_valid_confml1_files(self):
+ self.assert_schemavalidation_succeeds(
+ type = 'confml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/confml1/valid'),
+ namespace = CONFML1_NAMESPACE)
+
+ def test_invalid_confml1_files(self):
+ self.assert_schemavalidation_fails(
+ type = 'confml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/confml1/invalid'),
+ namespace = CONFML1_NAMESPACE)
+
+ def test_validate_confml_invalid_xml_data(self):
+ config = DummyConfiguration({'foo.confml': 'foo'})
+ problems = schemavalidation.validate_confml_file(config, 'foo.confml')
+ self.assertEquals(len(problems), 1)
+ prob = problems[0]
+ #self.assertEquals(prob.type, api.Problem.TYPE_XML_PROBLEM)
+ self.assertEquals(prob.severity, api.Problem.SEVERITY_ERROR)
+ self.assertEquals(prob.line, 1)
+
+ def test_validate_confml_invalid_xml_data_but_valid_root(self):
+ REF = 'test.confml'
+ DATA = """
+
+
+ """.encode('utf-8')
+ config = DummyConfiguration({REF: DATA})
+ problems = schemavalidation.validate_confml_file(config, REF)
+ self.assertEquals(len(problems), 1)
+ prob = problems[0]
+ #self.assertEquals(prob.type, api.Problem.TYPE_XML_PROBLEM)
+ self.assertEquals(prob.severity, api.Problem.SEVERITY_ERROR)
+ self.assertEquals(prob.line, 3)
+
+ def test_validate_confml_unsupported_namespace(self):
+ DATA = """
+
+
+ """.encode('utf-8')
+ self.assertRaises(exceptions.ConfmlParseError, schemavalidation.validate_confml_data, DATA)
+
+
+
+
+class TestImplmlSchemaValidation(BaseTestCase, schemavalidation.SchemaValidationTestMixin):
+
+ DUMMY1_XSD_DATA = """
+
+
+
+
+
+
+
+
+
+ """
+
+ DUMMY2_XSD_DATA = """
+
+
+
+
+
+
+
+
+
+ """
+
+ def setUp(self):
+ class MockReader1(plugin.ReaderBase):
+ NAMESPACE = "http://www.dummy.com/dummy1"
+ NAMESPACE_ID = "dummy1ml"
+ FILE_EXTENSIONS = ['dummy1ml']
+ ROOT_ELEMENT_NAME = 'dummy1'
+ @classmethod
+ def get_schema_data(cls):
+ return self.DUMMY1_XSD_DATA
+ class MockReader2(plugin.ReaderBase):
+ NAMESPACE = "http://www.dummy.com/dummy2"
+ NAMESPACE_ID = "dummy2ml"
+ FILE_EXTENSIONS = ['dummy2ml']
+ ROOT_ELEMENT_NAME = 'dummy2'
+ @classmethod
+ def get_schema_data(cls):
+ return self.DUMMY2_XSD_DATA
+ class MockReader3(plugin.ReaderBase):
+ NAMESPACE = "http://www.dummy.com/dummy3"
+ NAMESPACE_ID = "dummy3ml"
+ FILE_EXTENSIONS = ['dummy3ml']
+ ROOT_ELEMENT_NAME = 'dummy3'
+ plugin.ImplFactory.set_reader_classes_override([MockReader1, MockReader2, MockReader3])
+
+ def tearDown(self):
+ plugin.ImplFactory.set_reader_classes_override(None)
+
+ def test_valid_implml_files(self):
+ self.assert_schemavalidation_succeeds(
+ type = 'implml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/implml/valid'))
+
+ def test_invalid_implml_files(self):
+ self.assert_schemavalidation_fails(
+ type = 'implml',
+ dir = os.path.join(ROOT_PATH, 'testdata/schema/implml/invalid'))
+
+ def test_validate_implml_invalid_xml_data(self):
+ self.assertRaises(exceptions.XmlParseError, schemavalidation.validate_implml_data, "foo")
+
+ def test_validate_implml_invalid_xml_data_but_valid_root(self):
+ DATA = """
+
+
+ """.encode('utf-8')
+ self.assertRaises(exceptions.ImplmlParseError, schemavalidation.validate_implml_data, DATA)
+
+ def test_validate_implml_unsupported_namespace(self):
+ DATA = """
+
+
+ """.encode('utf-8')
+ self.assertRaises(exceptions.ImplmlParseError, schemavalidation.validate_implml_data, DATA)
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/dev-tools/depfea.cmd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/dev-tools/depfea.cmd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,94 @@
+@rem
+@rem Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description:
+@rem
+
+:: ============================================================================
+:: Name : depfea.cmd
+:: Part of : depfea
+:: Description : depfea tool wrapper for Windows
+:: Version : %version: 1 %
+::
+:: ============================================================================
+
+
+
+@echo off
+setlocal
+
+set CONE_CMDARG=%*
+set BASEDIR=%~dp0
+set CONE_BASEDIR=%BASEDIR%configurationengine\win\
+set PYTHONCASEOK=1
+
+if not exist "%CONE_BASEDIR%" (
+echo Cannot run ConE, the ConE base directory does not exist:
+echo %CONE_BASEDIR%
+exit /b 1
+)
+
+@rem Check that Python is available
+call python -c None >nul 2>&1
+if %errorlevel% neq 0 (
+echo Python is required to run ConE!
+exit /b 1
+)
+
+@REM Find out Python version
+FOR /F "tokens=*" %%i in ('PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"') do SET VER1=%%i
+
+@REM Set the used base directory based on the version
+if %VER1%==2.5 (
+set CONE_BASEDIR=%CONE_BASEDIR%2.5\
+goto EndVersionCheck
+)
+if %VER1%==2.6 (
+set CONE_BASEDIR=%CONE_BASEDIR%2.6\
+goto EndVersionCheck
+)
+echo You are using an unsupported Python version (%VER1%)
+echo ConE requires Python 2.5 or 2.6
+exit /b 1
+)
+:EndVersionCheck
+
+@rem Check that this ConE installation supports the Python version
+if not exist "%CONE_BASEDIR%" (
+echo Python version %VER1% is not supported by this ConE installation
+exit /b 1
+)
+
+@rem Set the egg cache dir to be unique to avoid egg extraction clashes
+@rem when running multiple parallel ConE instances
+FOR /F "tokens=*" %%i in ('PYTHON -c "import tempfile; d = tempfile.mkdtemp(); print d"') do SET EGG_CACHE_DIR=%%i
+@rem echo Egg cache dir: %EGG_CACHE_DIR%
+set PYTHON_EGG_CACHE=%EGG_CACHE_DIR%
+
+@rem Set environment variables and run deprfea.py
+set CONE_LIBDIR=%CONE_BASEDIR%\lib
+set CONE_SCRIPTDIR=%CONE_BASEDIR%\scripts
+set PATH=%CONE_SCRIPTDIR%;%PATH%
+set PYTHONPATH=%CONE_LIBDIR%;%PYTHONPATH%
+REM The cone_tool will parse the arguments from the environment variable
+call python "%BASEDIR%deprfea.py" %*
+set CONE_ERROR_CODE=%ERRORLEVEL%
+
+@rem Delete the egg cache dir
+call rd /S /Q "%EGG_CACHE_DIR%"
+
+if 0%CONE_EXITSHELL% equ 0 exit /b %CONE_ERROR_CODE%
+exit %CONE_ERROR_CODE%
+endlocal
+
+:: END OF depfea.cmd
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/dev-tools/deprfea.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/dev-tools/deprfea.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,230 @@
+#
+# 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:
+#
+
+import os
+import sys
+import re
+import shutil
+from optparse import OptionParser
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(os.path.join(ROOT_PATH, '..'))
+if sys.version_info[0] == 2 and (sys.version_info[1] == 5 or sys.version_info[1] == 6):
+ cone_basedir = os.path.join(ROOT_PATH, 'configurationengine',
+ 'win', '%s.%s' % (sys.version_info[0], sys.version_info[1]))
+ cone_scriptdir = os.path.join(cone_basedir, 'scripts')
+ cone_libdir = os.path.join(cone_basedir, 'lib')
+ sys.path.append(cone_basedir)
+ sys.path.append(cone_scriptdir)
+ sys.path.append(cone_libdir)
+else:
+ print 'You are using an unsupported Python version: %s.%s' % (sys.version_info[0], sys.version_info[1])
+ sys.exit(1)
+
+print sys.path
+print os.getenv('PATH')
+
+try:
+ import scripts.cone_common
+except:
+ import cone_common
+from cone.public import api, plugin, utils, exceptions
+from cone.storage.filestorage import FileStorage
+
+CARBON_PROJECT_URL = 'http://carbon.nokia.com/extapi'
+
+CONFIGS_FILE = os.path.join(ROOT_PATH, 'configs.txt')
+ALL_FEATURES_FILE = os.path.join(ROOT_PATH, 'all_features_and_values.txt')
+REPORT_FILE = os.path.join(ROOT_PATH, 'deprecated_features.txt')
+EXPORT_STORAGE = os.path.join(ROOT_PATH, 'exported')
+
+
+def get_list_of_configurations_from_carbon(carbon_prj):
+ config_list = carbon_prj.list_configurations()
+ config_list.sort()
+ return config_list
+
+def filter_configurations_from_file(cfilter=""):
+ config_list = []
+ fh = open(CONFIGS_FILE, 'r')
+ config_list = fh.readlines()
+ fh.close()
+ if cfilter:
+ return [elem.strip() for elem in config_list if match_filter(cfilter, elem)]
+ else:
+ return config_list
+
+def check_deprecated_features(config, depr_features):
+ default_view = config.get_default_view()
+ f = open(ALL_FEATURES_FILE, 'a')
+ f.write('\n\n### %s ###\n\n' % config.get_name())
+ for fea_ref in default_view.list_all_features():
+ feature = default_view.get_feature(fea_ref)
+ # If feature has subfeatures, skip it
+ if len(feature.list_features()) > 0:
+ f.write('%-15s # %s\n' % ('Has subs', fea_ref))
+ continue
+ fea_value = default_view.get_feature(fea_ref).get_value()
+ f.write('%-15s # %s\n' % (fea_value, fea_ref))
+ # If the value is None and it is not on the list yet, append it to deprecated features
+ if fea_value == None and depr_features.count(fea_ref) == 0:
+ depr_features.append(fea_ref)
+ # If the value is something else and the feature is on the list, remove it
+ elif fea_value != None and depr_features.count(fea_ref) != 0:
+ depr_features.remove(fea_ref)
+ f.close()
+ return depr_features
+
+def save_report(depr_features):
+ fh = open(REPORT_FILE, 'w')
+ try: [fh.write(df + '\n') for df in depr_features]
+ finally: fh.close()
+
+
+def match_filter(cfilter, element):
+ filters = cfilter.split(';')
+ for f in filters:
+ if f.strip().lower() == element.strip().lower():
+ return True
+ if re.match('.*' + f.strip().lower() + '.*', element.strip().lower()):
+ return True
+ return False
+
+def create_options():
+ #parser = OptionParser(usage="Sumthin")
+ parser = OptionParser()
+ parser.add_option("-f", "--filter",
+ action="store",
+ dest="filter",
+ help="Filter configurations. Multiple filters can be given, separated by \';\'. E.g. -f \"\(Vasco 01\);\(Vasco 06\)\"",
+ metavar="REGEX",
+ default="")
+ parser.add_option("-l", "--list-configurations",
+ action="store_true",
+ dest="list_configs",
+ help="Only list available configurations in Carbon. When used with the -f option, preview the configurations which would be fetched from Carbon.",
+ default=False)
+ parser.add_option("--force-carbon",
+ action="store_true",
+ dest="force_carbon",
+ help="Get configurations from Carbon even if they have already been fetched.",
+ default=False)
+ return parser
+
+def main():
+ parser = create_options()
+ (options, args) = parser.parse_args()
+ configs = []
+ carbon_prj = None
+ local_prj = None
+
+ if options.filter == "":
+ selection = raw_input('No filter given! ALL the configs in Carbon will be fetched and it will take a loooong time. Are you ABSOLUTELY sure you want to continue (y/n)? ')
+ if selection.lower() != 'y':
+ print '\nGood choice :)'
+ return 0
+ else:
+ print '\nOk...\n'
+
+ try:
+ os.remove(ALL_FEATURES_FILE)
+ except Exception, e:
+ pass
+
+ print '\nOpening project in Carbon (%s)...' % CARBON_PROJECT_URL
+ try:
+ carbon_prj = api.Project(api.Storage.open(CARBON_PROJECT_URL,"r"))
+ except Exception, e:
+ print 'Unable to open Carbon project. %s' % e
+ return 1
+
+ if os.path.exists(EXPORT_STORAGE):
+ print '\nOpening project on local disk (%s)...' % EXPORT_STORAGE
+ try:
+ local_prj = api.Project(api.Storage.open(EXPORT_STORAGE, 'r'))
+ except Exception, e:
+ print 'Unable to open local project. %s' % e
+ return 1
+
+ # Force script to get everything from Carbon again
+ if options.force_carbon:
+ try:
+ os.remove(CONFIGS_FILE)
+ shutil.rmtree(EXPORT_STORAGE, ignore_errors=True)
+ except:
+ pass
+
+ # Only get available configs and exit
+ if options.list_configs:
+ print 'Getting available configurations from Carbon (%s)' % CARBON_PROJECT_URL
+ configs = get_list_of_configurations_from_carbon(carbon_prj)
+ print 'Saving configs to %s...' % CONFIGS_FILE
+ fh = open(CONFIGS_FILE, 'w')
+ try: [fh.write('%s\n' % c) for c in configs]
+ finally: fh.close()
+ print 'Filtered configs: '
+ configs = filter_configurations_from_file(options.filter)
+ for elem in configs: print elem.strip()
+ return 0
+
+
+ if not os.path.exists(CONFIGS_FILE):
+ print 'Configurations file not found. Getting list of configurations in project...'
+ configs = get_list_of_configurations_from_carbon(carbon_prj)
+ print 'Saving configs to %s...' % CONFIGS_FILE
+ fh = open(CONFIGS_FILE, 'w')
+ try: [fh.write('%s\n' % c) for c in configs]
+ finally: fh.close()
+
+ print '\nFilter wanted configurations from file: '
+ configs = filter_configurations_from_file(options.filter)
+ for elem in configs: print elem.strip()
+
+ depr_features = []
+
+ for c in configs:
+ config_name = c.strip()
+ # Configuration has not been exported yet
+ if not os.path.exists(os.path.join(EXPORT_STORAGE, config_name)):
+ print '\nExport configuration %s from Carbon' % config_name
+ if not carbon_prj:
+ carbon_prj = api.Project(api.Storage.open(CARBON_PROJECT_URL,"r"))
+ try:
+ config = carbon_prj.get_configuration(config_name)
+ carbon_prj.export_configuration(config, FileStorage(EXPORT_STORAGE, 'w'))
+ except:
+ print 'Unable to export %s' % config_name
+ continue
+ print '\nOpen configuration %s in project %s' % (config_name, EXPORT_STORAGE)
+ if not local_prj:
+ try:
+ local_prj = api.Project(api.Storage.open(EXPORT_STORAGE, 'r'))
+ except Exception, e:
+ print 'Unable to open local project. %s' % e
+ if carbon_prj: carbon_prj.close()
+ return 1
+ config = local_prj.get_configuration(c.strip())
+ depr_features = check_deprecated_features(config, depr_features)
+
+ if local_prj: local_prj.close()
+ if carbon_prj: carbon_prj.close()
+
+ save_report(depr_features)
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/build_egg_info.py
--- a/configurationengine/source/plugins/build_egg_info.py Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-#
-# 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:
-#
-
-# Script for generating the egg-info directories for all needed plug-ins.
-#
-# This is needed, because running some of the tests from Eclipse or
-# command line requires the egg-info dirs to be present for the plug-ins
-# to be found.
-
-import sys, os, subprocess, shutil
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-DEBUG = False
-
-def generate_egg_info(path):
- """Generate egg-info for the given plug-in path if possible and necessary."""
- if not os.path.isdir(path) or "setup.py" not in os.listdir(path):
- return
-
- # Check if egg-info has already been generated
- for name in os.listdir(path):
- egg_info_path = os.path.join(path, name)
- if os.path.isdir(egg_info_path) and name.endswith('.egg-info'):
- # xxx.egg-info is present in the directory, check if it is old
- setup_py_path = os.path.join(path, 'setup.py')
- if os.stat(setup_py_path).st_mtime < os.stat(egg_info_path).st_mtime:
- if DEBUG: print "No need to generate egg-info for '%s'" % path
- return
- else:
- if DEBUG: print "egg-info for '%s' is out of date, removing old and generating new" % path
- shutil.rmtree(egg_info_path)
-
- # Run the egg-info generation command
- orig_workdir = os.getcwd()
- try:
- if DEBUG: print "Generating egg-info for '%s'..." % path
- os.chdir(path)
- p = subprocess.Popen("python setup.py egg_info", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = p.communicate()
- if p.returncode != 0:
- print >>sys.stderr, "Could not generate egg-info for '%s'!" % path
- print >>sys.stderr, "Command stdout output:"
- print >>sys.stderr, out
- print >>sys.stderr, "Command stderr output:"
- print >>sys.stderr, err
- else:
- if DEBUG:
- print "Done"
- print "Command output:"
- print out
- finally:
- os.chdir(orig_workdir)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/commandml.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/commandml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/commandml.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,14 +22,27 @@
import re
import os
-import sys
import logging
import types
+import pkg_resources
import subprocess
-import __init__
+
+from cone.public import plugin,utils
-from cone.public import exceptions,plugin,utils,api, settings
+def get_folder_set(folder):
+ """
+ Get a set object containing all files of given folder
+ @param folder: the folder to create set for
+ @return: a python set
+ """
+ fileset = set()
+ for (root, _, filenames) in os.walk(folder):
+ for filename in filenames:
+ fname = utils.relpath(os.path.join(root,filename), folder)
+ fileset.add(fname)
+
+ return fileset
class CommandImpl(plugin.ImplBase):
"""
@@ -47,13 +60,16 @@
self.desc = ""
self.logger = logging.getLogger('cone.commandml(%s)' % self.ref)
self.reader = reader
+ for element in self.reader.elements:
+ element.set_logger(self.logger)
def generate(self, context=None):
"""
Generate the given implementation.
"""
- self.create_output()
+
+ self.create_output(context)
return
def generate_layers(self,layers):
@@ -64,17 +80,26 @@
self.create_output(layers)
return
- def create_output(self, layers=None):
+ def create_output(self, context, layers=None):
"""
Function to generate output files.
"""
-
+ self.context = context
tmpDict = self.__create_helper_variables()
-
+ # Get the contents of output folder before the generation
+ outset_before = get_folder_set(context.output)
for element in self.reader.elements:
#Element can be either command or condition.
element.set_logger(self.logger)
- element.execute(tmpDict)
+ element.execute(context, tmpDict)
+
+ # Get the contents of output folder after the generation
+ # and get the new files created by the set difference.
+ # NOTE! this does not recognize files outside output folder!
+ outset_after = get_folder_set(context.output)
+ outset = outset_after - outset_before
+ for outfile in outset:
+ context.add_file(outfile, implementation=self)
return
def __create_helper_variables(self):
@@ -82,8 +107,8 @@
Internal function to create dictionary containing most often used ConE "environment" variables.
"""
tmp = {}
- tmp["%CONE_OUT%"] = self.output
- tmp["%CONE_OUT_ABSOLUTE%"] = os.path.abspath(self.output)
+ tmp["%CONE_OUT%"] = os.path.join(self.context.output, self.output).rstrip('\\')
+ tmp["%CONE_OUT_ABSOLUTE%"] = os.path.abspath(os.path.join(self.context.output, self.output)).rstrip('\\')
return tmp
def has_ref(self, refs):
@@ -100,6 +125,8 @@
Parses a single commandml file
"""
NAMESPACE = 'http://www.s60.com/xml/commandml/1'
+ NAMESPACE_ID = 'commandml'
+ ROOT_ELEMENT_NAME = 'commandml'
FILE_EXTENSIONS = ['commandml']
def __init__(self):
@@ -122,7 +149,11 @@
if reader.tags:
impl.set_tags(reader.tags)
return impl
-
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('commandplugin', 'xsd/commandml.xsd')
+
def set_default_view(self, dview):
"""
Function to set default view that is needed when solving out ConfML reference information
@@ -260,17 +291,17 @@
cmd.set_logger(logger)
def add_command(self, command):
- self.command.append(command)
+ self.commands.append(command)
- def execute(self, replaceDict=None):
- if self.__solve_condition(self.condition):
+ def execute(self, context, replaceDict=None):
+ if self._solve_condition(self.condition, context):
#Condition is true -> running command
for command in self.commands:
- command.execute(replaceDict)
+ command.execute(context, replaceDict)
else:
self.logger.info("Ignoring %s because it is evaluated as False." % self.condition)
- def __solve_condition(self, condition_str):
+ def _solve_condition(self, condition_str, context):
"""
Internal function to handle condition
"""
@@ -278,7 +309,7 @@
#Expanding ConfML information
modstr = utils.expand_delimited_tokens(
condition_str,
- lambda ref, index: repr(self.dview.get_feature(ref).get_value()))
+ lambda ref, index: repr(context.configuration.get_default_view().get_feature(ref).get_value()))
return eval(modstr)
else:
#Empty condition is true always.
@@ -323,8 +354,7 @@
self.cwd = cwd
def set_all_envs(self, envs):
- if envs:
- self.envs = eval(envs)
+ self.envs = envs
def set_default_view(self, dview):
self.dview = dview
@@ -401,9 +431,17 @@
for filter in self.filters:
filter.report(self.logger)
- def execute(self, replaceDict=None):
+ def execute(self, context, replaceDict=None):
+ self.dview = context.configuration.get_default_view()
+
self.solve_refs()
+ try:
+ if self.envs: env_dict = eval(self.envs)
+ else: env_dict = None
+ except Exception, e:
+ raise RuntimeError("Failed to evaluate env dictionary: %s: %s" % (e.__class__.__name__, e))
+
exit_code = 0
try:
try:
@@ -415,8 +453,8 @@
self.logger.info("Running command: \"%s\"" % command_str)
self.logger.info("with args: shell=%s envs=%s cwd=%s bufsize=%s stdin=%s stdout=%s stderr=%s" \
% (self.shell, self.envs, cwd, self.bufsize, \
- self.get_pipe("stdin", 'r'),self.get_pipe("stdout"), self.get_pipe("stderr")))
- pid = subprocess.Popen(command_str, shell=self.shell, env=self.envs, cwd=cwd,\
+ self.get_pipe("stdin", 'r'),self.get_pipe("stdout"), self.get_pipe("stderr")))
+ pid = subprocess.Popen(command_str, shell=self.shell, env=env_dict, cwd=cwd,\
bufsize=self.bufsize, stdin = self.get_pipe("stdin", 'r'),\
stdout = self.get_pipe("stdout"), stderr = self.get_pipe("stderr"))
#Waiting for process to complete
@@ -452,6 +490,7 @@
self.shell = self.__solve_ref(self.shell)
self.bufsize = self.__solve_ref(self.bufsize)
self.cwd = self.__solve_ref(self.cwd)
+ self.envs = self.__solve_ref(self.envs)
for argument in self.arguments:
self.arguments[self.arguments.index(argument)] = self.__solve_ref(argument)
for pipe in self.pipes.keys():
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/__init__.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,19 +18,5 @@
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/assets/s60/implml/file2.commandml
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/assets/s60/implml/file2.commandml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/assets/s60/implml/file2.commandml Tue Aug 10 14:29:28 2010 +0300
@@ -5,7 +5,7 @@
-
+
@@ -40,4 +40,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/assets/s60/implml/file3.commandml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/assets/s60/implml/file3.commandml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/tools/helloworld.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/tools/helloworld.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+#
+# 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:
+#
+import os, sys
+
+output = sys.argv[1]
+outputfile = os.path.join(output, "helloworld.txt")
+
+f = open(outputfile, "w")
+f.write("Hello World!!!")
+f.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/tools/print_hello.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/tools/print_hello.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/project/tools/print_hello.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,5 +16,4 @@
import os, sys
print "Hello"
-print "Cmd line args: %r" % sys.argv[1:]
-print "Env: %r" % os.environ
\ No newline at end of file
+print "Cmd line args: %r" % sys.argv[1:]
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/runtests.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_commandml_plugin.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_commandml_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_commandml_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,12 +16,10 @@
import unittest, os, shutil
-import __init__
-from cone.public import exceptions,plugin,api
+# import __init__
+from cone.public import plugin, api, utils
from cone.storage import filestorage
-from cone.confml import implml
from testautomation.base_testcase import BaseTestCase
-from commandplugin import commandml
# Hardcoded value of testdata folder that must be under the current working dir
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -41,27 +39,35 @@
try:
OUTPUT_DIR = os.path.join(ROOT_PATH, 'output')
self.remove_if_exists(OUTPUT_DIR)
+ self.remove_if_exists(['hello.log', 'exec_in_output_test.log',])
fs = filestorage.FileStorage(testdata)
p = api.Project(fs)
config = p.get_configuration('product.confml')
+ context = plugin.GenerationContext(configuration=config,
+ output=OUTPUT_DIR)
impls = plugin.get_impl_set(config,'file2\.commandml$')
- impls.output = OUTPUT_DIR
- impls.generate()
+ #impls.output = OUTPUT_DIR
+ impls.generate(context)
self.assert_file_content_equals('hello.log',
- "Hello\r\n" +
- "Cmd line args: ['-c', 'some_config.txt', '-d', 'some_dir', '-x']\r\n" +
- "Env: {'MYVAR': '123'}\r\n")
+ "Hello" + os.linesep +
+ "Cmd line args: ['-c', 'some_config.txt', '-d', 'some_dir', '-x']" + os.linesep)
self.assert_file_content_equals('exec_in_output_test.log',
- os.path.normpath(OUTPUT_DIR) + '\r\n')
+ os.path.normpath(OUTPUT_DIR) + os.linesep)
# Check that the log file of the command that should not be
# executed does not exist
self.assertFalse(os.path.exists("should_not_be_created.log"))
+ self.assertTrue(os.path.exists(os.path.join(OUTPUT_DIR,"helloworld.txt")))
+
+ self.assertEquals(len(context.generation_output), 1)
+ self.assertEquals(utils.relpath(context.generation_output[0].name, OUTPUT_DIR), 'helloworld.txt')
+ self.assertEquals(context.generation_output[0].implementation.ref, 'assets/s60/implml/file2.commandml')
finally:
os.chdir(orig_workdir)
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_commandml_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_commandml_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,57 @@
+#
+# 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:
+#
+
+import unittest, os, shutil
+
+from commandplugin import commandml
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TMP_PATH = os.path.join(ROOT_PATH, 'temp')
+TMP_FILE1 = os.path.join(TMP_PATH, 'sub/one.txt')
+TMP_FILE2 = os.path.join(TMP_PATH, 'foobar/two.txt')
+TMP_FILE3 = os.path.join(TMP_PATH, 'three.txt')
+
+def norm(path):
+ return os.path.normpath(path)
+
+def create_file(path):
+ if not os.path.exists(os.path.dirname(path)):
+ os.makedirs(os.path.dirname(path))
+ f = open(path, "w")
+ f.write('something...')
+ f.close()
+
+class TestCommandUtil(unittest.TestCase):
+ def test_get_folder_set(self):
+ if os.path.exists(TMP_PATH):
+ shutil.rmtree(TMP_PATH)
+ os.mkdir(TMP_PATH)
+ create_file(TMP_FILE1)
+ fset1 = commandml.get_folder_set(TMP_PATH)
+
+ self.assertEquals(len(fset1), 1)
+ self.assertEquals(fset1, set([norm('sub/one.txt')]))
+
+ create_file(TMP_FILE2)
+ create_file(TMP_FILE3)
+ fset2 = commandml.get_folder_set(TMP_PATH)
+ nset = fset2 - fset1
+ self.assertEquals(nset, set([norm('foobar/two.txt'),
+ norm('three.txt')]))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_parse_commandml.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_parse_commandml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_parse_commandml.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,7 +16,7 @@
import unittest, os, re, subprocess
-import __init__
+# import __init__
from cone.public import api, plugin
from cone.storage import filestorage
from testautomation.base_testcase import BaseTestCase
@@ -44,7 +44,7 @@
self.assertEquals(cmd.shell, False)
self.assertEquals(cmd.bufsize, 0)
self.assertEquals(cmd.cwd, r'c:\program1')
- self.assertEquals(cmd.envs, {'MYVAR': '123'})
+ self.assertEquals(cmd.envs, "{'MYVAR':'123'}")
self.assertEquals(cmd.arguments, ['-c some_config.txt',
'-d some_dir',
'-x'])
@@ -67,7 +67,7 @@
def test_parse_file2(self):
impl = self._get_impl('file2.commandml')
- self.assertEquals(len(impl.reader.elements), 4)
+ self.assertEquals(len(impl.reader.elements), 5)
self.assertTrue(isinstance(impl.reader.elements[0], Condition))
self.assertTrue(isinstance(impl.reader.elements[1], Condition))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_read_temp_variable.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/tests/unittest_read_temp_variable.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,57 @@
+#
+# 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:
+#
+
+import unittest, os, re, subprocess
+
+# import __init__
+from cone.public import api, plugin
+from cone.storage import filestorage
+from testautomation.base_testcase import BaseTestCase
+from commandplugin.commandml import Command, Condition
+from cone.public.api import Configuration
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+testdata = os.path.join(ROOT_PATH,'project')
+
+class TestParseCommandMl(BaseTestCase):
+ def _get_impl_and_set(self, ref):
+ fs = filestorage.FileStorage(testdata)
+ p = api.Project(fs)
+ config = p.get_configuration('product.confml')
+ impl_set = plugin.get_impl_set(config, re.escape(ref) + '$')
+ self.assertEquals(len(impl_set), 1)
+ return iter(impl_set).next(), impl_set
+
+ def test_parse_file3(self):
+ impl, impl_set = self._get_impl_and_set('file3.commandml')
+ self.assertEquals(len(impl[0].reader.elements), 2)
+
+ cond1 = impl.impls[0].reader.elements[0]
+ cond2 = impl.impls[0].reader.elements[1]
+
+ # Create temporary variables
+ impl_set.create_temp_features(impl_set.generation_context.configuration)
+
+ self.assertTrue(isinstance(cond1, Condition))
+ self.assertTrue(isinstance(cond2, Condition))
+
+
+ self.assertEquals(True, cond1._solve_condition(cond1.condition, impl_set.generation_context))
+ self.assertEquals(False, cond2._solve_condition(cond2.condition, impl_set.generation_context))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/xsd/commandml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/xsd/commandml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeCommandPlugin/setup.py
--- a/configurationengine/source/plugins/common/ConeCommandPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeCommandPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conecommandplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'commandplugin': ['xsd/*.xsd']},
test_suite = "commandplugin.tests.collect_suite",
# metadata for upload to PyPI
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentml.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentml.py Tue Aug 10 14:29:28 2010 +0300
@@ -23,6 +23,7 @@
import sys
import logging
import shutil
+import pkg_resources
import __init__
@@ -46,6 +47,8 @@
self.desc = ""
self.logger = logging.getLogger('cone.content(%s)' % self.ref)
self.errors = False
+ self.context = plugin.GenerationContext(configuration=configuration)
+
def list_output_files(self):
"""
@@ -76,7 +79,7 @@
self.logger.info('Content copy items from %s to %s' % (input.dir,os.path.join(self.output,output.dir)))
if input.__class__.__name__ == "ContentInput":
- copylist = self.create_copy_list(content=self.configuration.layered_content(),
+ copylist = self.create_copy_list(content=self.configuration.layered_content(empty_folders=True),
input=input.dir,
output=os.path.join(self.output,output.dir),
include_pattern=input.get_include_pattern(),
@@ -91,13 +94,20 @@
else:
fulldir = self.configuration.get_project().get_storage().get_path()
- data = container.DataContainer()
+ data = container.DataContainer()
for root, dirs, files in os.walk(fulldir):
- for f in files:
+ for f in files:
filepath = utils.resourceref.norm(os.path.join(root, f))
key = utils.resourceref.replace_dir(filepath,fulldir,"")
data.add_value(key,filepath)
- #data.add_value(filepath,filepath)
+
+ # If the root contains no directories and no files, it is
+ # an empty directory and needs to be added
+ if not dirs and not files:
+ filepath = utils.resourceref.norm(root)
+ key = utils.resourceref.replace_dir(filepath,fulldir,"")
+ data.add_value(key,filepath)
+
copylist = self.create_copy_list(content=data,
input=input.dir,
output=os.path.join(self.output,output.dir),
@@ -111,13 +121,18 @@
logging.getLogger('cone.content').warning("Unknown input %s" % (input.__class__.__name__))
fullcopylist += copylist
-
+
+ # Sort to make automated testing easier (list always in same order)
+ fullcopylist.sort()
+
return fullcopylist
def generate(self, context=None):
"""
Generate the given implementation.
"""
+ #assert context, "No Context given for generation!"
+ self.context = context
self.logger.info('Generating')
self.create_output()
return
@@ -127,31 +142,47 @@
Create the output directory from the content folder files
"""
if not self.errors:
- datacontainer = self.configuration.layered_content(layers)
- #root = self.configuration.get_root()
copylist = self.get_full_copy_list(True)
for copy_item in copylist:
- sourceref = copy_item[0]
- targetfile = copy_item[1]
- external = copy_item[2]
+ source_path = copy_item[0]
+ target_path = copy_item[1]
+ external = copy_item[2]
+
+ self.logger.info('Copy from %s to %s' % (source_path,target_path))
- self.logger.info('Copy from %s to %s' % (sourceref,targetfile))
- if not os.path.exists(os.path.dirname(targetfile)):
- os.makedirs(os.path.dirname(targetfile))
- if not external:
- outfile = open(targetfile,"wb")
- res = self.configuration.get_storage().open_resource(sourceref,"rb")
- outfile.write(res.read())
+ # Open file resource if the source is a file
+ file_res = None
+ if not external and not self.configuration.get_storage().is_folder(source_path):
+ file_res = self.configuration.get_storage().open_resource(source_path, "rb")
+ elif external and os.path.isfile(source_path):
+ file_res = open(source_path, 'rb')
+
+ # Copy file or create empty directory
+ if file_res:
+ try: self._copy_file(file_res, target_path)
+ finally: file_res.close()
else:
- shutil.copyfile(sourceref,targetfile)
+ path = os.path.join(self.context.output, target_path)
+ if not os.path.exists(path): os.makedirs(path)
return
else:
- self.logger.error('Plugin had errors! Bailing out!')
-
+ self.logger.error('Plugin had errors! Bailing out!')
+
+ def _copy_file(self, source_file, target_file_path):
+ outfile = self.context.create_file(target_file_path, implementation=self)
+ try:
+ # Copy data in chunks of max 2 MB to avoid
+ # memory errors with very large files
+ while True:
+ data = source_file.read(2 * 1024 * 1024)
+ if data: outfile.write(data)
+ else: break
+ finally:
+ outfile.close()
def create_copy_list(self, **kwargs):
"""
- Return a list copy list where each element is a (from,to) tuple
+ Return a list copy list where each element is a (from, to, is_external) tuple
"""
datacontainer = kwargs.get('content',None)
input_dir = kwargs.get('input','')
@@ -169,7 +200,7 @@
Then apply the possible filters.
"""
if input_dir == None:
- self.logger.warning("Input dir is none!")
+ self.logger.warning("Input dir is none!")
if files != []:
@@ -199,7 +230,11 @@
sourcefile = ""
targetfile = ""
- if input_dir != None and outfile.startswith(input_dir):
+ # For the startswith() check, make sure that input dir has a trailing slash
+ if input_dir and input_dir[-1] != '/': input_dir_check = input_dir + '/'
+ else: input_dir_check = input_dir
+
+ if input_dir != None and (input_dir == outfile or outfile.startswith(input_dir_check)):
sourcefile = datacontainer.get_value(outfile)
if flatten:
targetfile = utils.resourceref.join_refs([output_dir, os.path.basename(outfile)])
@@ -220,11 +255,35 @@
if output_file:
#Renaming output if defined
targetfile = targetfile.replace(os.path.basename(targetfile), output_file)
-
- if sourcefile and targetfile:
- copylist.append((sourcefile,targetfile, external))
+
+ if sourcefile and targetfile:
+ copylist.append((sourcefile,targetfile,external))
return copylist
-
+
+ def uses_layer(self, layer):
+ layered_content = layer.layered_content().list_keys()
+ for f in self.get_full_copy_list():
+ for file in layered_content:
+ if utils.resourceref.norm(os.path.join(utils.resourceref.get_path(layer.get_path()), 'content', file)) == f[0]:
+ return True
+ return False
+
+ def uses_layers(self, layers, context):
+ # Use the base implementation to check with refs first
+ if super(ContentImpl, self).uses_layers(layers, context):
+ return True
+
+ # Then check if any of the files in the copy list come from the layers
+ copy_list = self.get_full_copy_list()
+ for layer in layers:
+ layered_content = layer.layered_content().list_keys()
+ for f in copy_list:
+ for file in layered_content:
+ if utils.resourceref.norm(os.path.join(utils.resourceref.get_path(layer.get_path()), 'content', file)) == f[0]:
+ return True
+ return False
+
+
class ContentImplReaderBase(object):
FILE_EXTENSIONS = ['content', 'contentml']
@@ -251,8 +310,20 @@
class ContentImplReader1(ContentImplReaderBase, plugin.ReaderBase):
NAMESPACE = 'http://www.s60.com/xml/content/1'
+ NAMESPACE_ID = 'contentml1'
+ ROOT_ELEMENT_NAME = 'content'
parser_class = contentmlparser.Content1Parser
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('contentplugin', 'xsd/contentml.xsd')
class ContentImplReader2(ContentImplReaderBase, plugin.ReaderBase):
NAMESPACE = 'http://www.s60.com/xml/content/2'
+ NAMESPACE_ID = 'contentml2'
+ ROOT_ELEMENT_NAME = 'content'
parser_class = contentmlparser.Content2Parser
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('contentplugin', 'xsd/contentml2.xsd')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentmlparser.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentmlparser.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentmlparser.py Tue Aug 10 14:29:28 2010 +0300
@@ -60,8 +60,10 @@
self.configuration = configuration
def path_convert(self, path):
- (drive, tail) = os.path.splitdrive(path)
- return tail.lstrip('\\/')
+ match = re.match('([a-zA-Z]:)(.*)', path)
+ if match:
+ path = match.group(2)
+ return path.lstrip('\\/')
def get_dir(self):
if self.configuration and ConfmlRefs.is_confml_ref(self._dir):
@@ -151,7 +153,9 @@
# change None value to empty string
cvalue = dview.get_feature(cref).value or ''
if utils.is_list(cvalue):
- cvalue = ", ".join(cvalue)
+ # Allow only strings (mainly filter out Nones)
+ cvalue = filter(lambda x: isinstance(x, basestring), cvalue)
+ cvalue = ", ".join([v or '' for v in cvalue])
key_list[index] = cvalue
except exceptions.NotFound:
logging.getLogger('cone.content').error("Feature ref '%s' in include key '%s' not found." % (cref,key))
@@ -448,5 +452,5 @@
if not ref in ret:
ret.append(matchref.group(1))
else:
- ret.append(p)
+ ret.append(p)
return ret
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/__init__.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,11 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/confml/content.confml
Binary file configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/confml/content.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/implml/empty_input_file_from_sequence.content
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/implml/empty_input_file_from_sequence.content Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/implml/test_external_input.content
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/implml/test_external_input.content Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/assets/s60/implml/test_external_input.content Tue Aug 10 14:29:28 2010 +0300
@@ -1,7 +1,7 @@
Copy only prod
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/family/product/content/test/test_CAP_letters.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/contentproject/family/product/content/test/test_CAP_letters.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+S60 product layer
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/runtests.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/testdata/emptydircopy/external_content.zip
Binary file configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/testdata/emptydircopy/external_content.zip has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/testdata/emptydircopy/project.zip
Binary file configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/testdata/emptydircopy/project.zip has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_confmlrefs.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_confmlrefs.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_confmlrefs.py Tue Aug 10 14:29:28 2010 +0300
@@ -29,11 +29,6 @@
except ImportError:
from xml.etree import ElementTree
-try:
- pkg_resources.require('ConeContentPlugin')
-except pkg_resources.DistributionNotFound:
- import __init__
-
from contentplugin import contentmlparser
class TestConfmlRefs(unittest.TestCase):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_copy.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_copy.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_copy.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,11 +16,7 @@
import unittest, os
import pkg_resources
-try:
- pkg_resources.require('ConeContentPlugin')
-except pkg_resources.DistributionNotFound:
- import __init__
-
+
from cone.public.exceptions import NotSupportedException
from contentplugin import contentml
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_copy_empty_dirs.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_copy_empty_dirs.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,175 @@
+#
+# 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:
+#
+
+import os, shutil
+import unittest
+
+from cone.public import plugin, api
+from testautomation.base_testcase import BaseTestCase
+from testautomation.unzip_file import unzip_file
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata')
+TEMP_DIR = os.path.join(ROOT_PATH, 'temp/emptydircopy')
+
+class TestContentCopyEmptyDirs(BaseTestCase):
+
+ def _get_project_and_config(self, workdir, storage_type):
+ # Create the working directory for the test
+ self.remove_if_exists(workdir)
+ os.makedirs(workdir)
+
+ # Unpack or copy the project into the working directory
+ project_source_zip = os.path.join(TESTDATA_DIR, 'emptydircopy/project.zip')
+ if storage_type == 'fs':
+ project_location = os.path.join(workdir, 'project')
+ unzip_file(project_source_zip, project_location)
+ elif storage_type == 'zs':
+ project_location = os.path.join(workdir, 'project.zip')
+ shutil.copy(project_source_zip, project_location)
+ else:
+ raise ValueError('Invalid storage type %r' % storage_type)
+
+ # Copy the external content directory
+ unzip_file(os.path.join(TESTDATA_DIR, 'emptydircopy/external_content.zip'),
+ os.path.join(workdir, 'external_content'))
+
+ project = api.Project(api.Storage.open(project_location, 'r'))
+ config = project.get_configuration('root.confml')
+ return project, config
+
+ def test_get_copy_list(self):
+ workdir = os.path.join(TEMP_DIR, 'get_copy_list')
+ proj, conf = self._get_project_and_config(workdir, 'fs')
+ proj.close()
+ impls = plugin.get_impl_set(conf)
+
+ orig_dir = os.getcwd()
+ os.chdir(workdir)
+ try:
+ self.assertEquals(1, len(impls))
+ impl = iter(impls).next()
+ self.assertEquals(8, len(impl.impls))
+
+ # Normal inputs
+ # -------------
+ def check(impl_index, expected):
+ self.assertEquals(sorted(impl.impls[impl_index].get_full_copy_list()),
+ sorted(expected))
+ check(0, [
+ ('layer2/content/foobar/layer2_emptydir', 'foobar_out/layer2_emptydir', False),
+ ('layer1/content/foobar/layer1_emptydir', 'foobar_out/layer1_emptydir', False),
+ ('layer1/content/foobar/layer1_emptydir2/foo', 'foobar_out/layer1_emptydir2/foo', False),
+ ('layer2/content/foobar/layer2.txt', 'foobar_out/layer2.txt', False),
+ ('layer1/content/foobar/layer1.txt', 'foobar_out/layer1.txt', False)
+ ])
+ check(1, [
+ #('layer2/content/foobar_filtered/layer2_filtered_emptydir', 'foobar_out/layer2_filtered_emptydir', False),
+ #('layer1/content/foobar_filtered/layer1_filtered_emptydir', 'foobar_out/layer1_filtered_emptydir', False),
+ ('layer1/content/foobar_filtered/bar.txt', 'foobar_out_filtered/bar.txt', False),
+ ])
+ check(2, [('layer1/content/empty', 'empty_out', False)])
+ check(3, [])
+
+
+ # External inputs
+ # ---------------
+ def check(impl_index, expected):
+ expected = [(os.path.abspath(src).replace('\\', '/'), tgt, ext) for src, tgt, ext in expected]
+ self.assertEquals(sorted(impl.impls[impl_index].get_full_copy_list()),
+ sorted(expected))
+ check(4, [
+ ('external_content/foobar/emptydir', 'ext_out/foobar_out/emptydir', True),
+ ('external_content/foobar/emptydir2/foo', 'ext_out/foobar_out/emptydir2/foo', True),
+ ('external_content/foobar/x.txt', 'ext_out/foobar_out/x.txt', True)
+ ])
+ check(5, [
+ #('external_content/foobar_filtered/layer1_filtered_emptydir', 'ext_out/foobar_out/layer1_filtered_emptydir', False),
+ ('external_content/foobar_filtered/bar.txt', 'ext_out/foobar_out_filtered/bar.txt', True),
+ ])
+ check(6, [('external_content/empty', 'ext_out/empty_out', True)])
+ check(7, [])
+ finally:
+ os.chdir(orig_dir)
+ self.remove_if_exists(workdir)
+
+ def test_copy_empty_dirs_filestorage(self):
+ workdir = os.path.join(TEMP_DIR, 'filestorage')
+ proj, conf = self._get_project_and_config(workdir, 'fs')
+
+ orig_dir = os.getcwd()
+ os.chdir(workdir)
+ try:
+ self._run_test_copy_empty_dirs(workdir, conf)
+ finally:
+ os.chdir(orig_dir)
+ proj.close()
+ self.remove_if_exists(workdir)
+
+ def test_copy_empty_dirs_zipstorage(self):
+ workdir = os.path.join(TEMP_DIR, 'zipstorage')
+ proj, conf = self._get_project_and_config(workdir, 'zs')
+
+ orig_dir = os.getcwd()
+ os.chdir(workdir)
+ try:
+ self._run_test_copy_empty_dirs(workdir, conf)
+ finally:
+ os.chdir(orig_dir)
+ proj.close()
+ self.remove_if_exists(workdir)
+
+ def _run_test_copy_empty_dirs(self, workdir, config):
+ output_dir = os.path.join(workdir, 'output')
+ context = plugin.GenerationContext(configuration=config, output=output_dir)
+ impl_set = plugin.get_impl_set(config)
+ impl_set.generate(context)
+
+ created_dirs = []
+ created_files = []
+ def strip(path):
+ return path[len(output_dir):].replace('\\', '/').strip('/')
+ for root, dirs, files in os.walk(output_dir):
+ for d in dirs: created_dirs.append(strip(os.path.join(root, d)))
+ for f in files: created_files.append(strip(os.path.join(root, f)))
+
+ self.assertEquals(sorted(created_dirs), sorted(
+ ['empty_out',
+ 'ext_out',
+ 'ext_out/empty_out',
+ 'ext_out/foobar_out',
+ 'ext_out/foobar_out/emptydir',
+ 'ext_out/foobar_out/emptydir2',
+ 'ext_out/foobar_out/emptydir2/foo',
+ 'ext_out/foobar_out_filtered',
+ 'foobar_out',
+ 'foobar_out/layer1_emptydir',
+ 'foobar_out/layer1_emptydir2',
+ 'foobar_out/layer1_emptydir2/foo',
+ 'foobar_out/layer2_emptydir',
+ 'foobar_out_filtered'
+ #'foobar_out_filtered/layer1_emptydir',
+ #'foobar_out_filtered/layer2_emptydir',
+ ]))
+ self.assertEquals(sorted(created_files), sorted(
+ ['ext_out/foobar_out/x.txt',
+ 'ext_out/foobar_out_filtered/bar.txt',
+ 'foobar_out/layer1.txt',
+ 'foobar_out/layer2.txt',
+ 'foobar_out_filtered/bar.txt']))
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_parseimpl.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_parseimpl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_parseimpl.py Tue Aug 10 14:29:28 2010 +0300
@@ -29,11 +29,6 @@
except ImportError:
from xml.etree import ElementTree
-try:
- pkg_resources.require('ConeContentPlugin')
-except pkg_resources.DistributionNotFound:
- import __init__
-
from contentplugin import contentmlparser
@@ -319,6 +314,8 @@
conout = contentmlparser.ContentOutput()
self.assertEquals(conout.path_convert('z:\\test\\foo\\bar.txt'), 'test\\foo\\bar.txt')
self.assertEquals(conout.path_convert('z:/test/foo/bar.txt'), 'test/foo/bar.txt')
+ self.assertEquals(conout.path_convert('/test/foo/bar.txt'), 'test/foo/bar.txt')
+ self.assertEquals(conout.path_convert('foo/bar.txt'), 'foo/bar.txt')
class TestContentInput(unittest.TestCase):
def test_content_input_dir(self):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_plugin.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/tests/unittest_content_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,8 +18,7 @@
import os, shutil
import sys
import logging
-import __init__
-
+
from cone.public import exceptions,plugin,api,container
from cone.storage import filestorage
from contentplugin import contentml
@@ -103,7 +102,6 @@
impls = plugin.ImplFactory.get_impls_from_file(resource_ref, configuration)
self.assertEquals(len(impls), 1)
impl = impls[0]
- impl.set_output_root(self.output)
return impl
def test_configuration_parse_resource(self):
@@ -142,24 +140,25 @@
def test_configuration_content_get_full_copy_list(self):
impl = self.load_impl('assets/s60/implml/copy_files.content')
files = impl.get_full_copy_list()
- self.assertEquals(files[0],('family/content/test/override.txt', 'output/content/test/override.txt', False))
+ self.assertEquals(files,
+ [('assets/s60/content/test/s60.txt', 'content/test/s60.txt', False),
+ ('family/content/test/override.txt', 'content/test/override.txt', False)])
def test_configuration_content_list_output_files(self):
config = self.load_config()
impls = plugin.get_impl_set(config,'\.content$')
- impls.output = self.output
files = impls.list_output_files()
- self.assertTrue('output/content/test/override.txt' in files)
+ self.assertTrue('content/test/override.txt' in files)
def test_configuration_content_list_output_files_with_refs_filter(self):
impl = self.load_impl('assets/s60/implml/test_content_with_sequence_refs.content')
files = impl.list_output_files()
- self.assertEquals(files[0],'output/content/override.txt')
+ self.assertEquals(files[0],'content/override.txt')
def test_configuration_content_list_output_files_with_exclude_filter(self):
impl = self.load_impl('assets/s60/implml/test_filter_both.content')
files = impl.list_output_files()
- self.assertEquals(files[0],'output/content/prodX/jee/ProdX_specific.txt')
+ self.assertEquals(files[0],'content/prodX/jee/ProdX_specific.txt')
#
def test_configuration_get_input_with_ref(self):
impl = self.load_impl('assets/s60/implml/test_content_with_refs.content')
@@ -169,69 +168,71 @@
def test_configuration_get_include_with_refs(self):
impl = self.load_impl('assets/s60/implml/test_content_with_sequence_refs.content')
self.assertEquals(impl.outputs[0].inputs[0].include['files'], ['test/override.txt'])
- self.assertEquals(impl.list_output_files(), ['output/content/override.txt'])
+ self.assertEquals(impl.list_output_files(), ['content/override.txt'])
- def test_configuration_get_include_with_refs(self):
+ def test_configuration_get_include_with_refs2(self):
impl = self.load_impl('assets/s60/implml/copy.content')
- expected = ['output/content/prodX/jee/ProdX_specific.txt',
- 'output/content/test/shout.txt',
- 'output/content/test/override.txt',
- 'output/content/test/s60.txt',
- 'output/content/test/test_CAP_letters.txt']
+ expected = ['content/prodX/jee/ProdX_specific.txt',
+ 'content/test/shout.txt',
+ 'content/test/override.txt',
+ 'content/test/s60.txt',
+ 'content/test/test_CAP_letters.txt']
actual = impl.list_output_files()
self.assertEquals(sorted(actual), sorted(expected))
def test_configuration_content_create_output(self):
impl = self.load_impl('assets/s60/implml/copy.content')
- impl.set_output_root(self.output)
impl.logger.setLevel(logging.DEBUG)
impl.create_output()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'content/prodX/jee/ProdX_specific.txt')))
+ self.assertTrue(os.path.exists(os.path.join(self.output,'content/prodX/jee/ProdX_specific.txt')))
def test_configuration_content_generate(self):
config = self.load_config()
impls = plugin.get_impl_set(config,'\.content$')
- impls.output = self.output
- results = impls.generate()
+ context = plugin.GenerationContext(output=self.output)
+ results = impls.generate(context)
self.assertTrue(os.path.exists(impls.output))
- self.assertTrue(os.path.exists(os.path.join(impls.output,'content/prodX/jee/ProdX_specific.txt')))
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content/prodX/jee/ProdX_specific.txt')))
def test_configuration_content_generate_with_include_refs(self):
impl = self.load_impl('assets/s60/implml/test_content_with_sequence_refs.content')
- impl.set_output_root(self.output)
- results = impl.generate()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'content/override.txt')))
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content/override.txt')))
+
+ def test_configuration_content_generate_with_external_input(self):
+ impl = self.load_impl('assets/s60/implml/test_external_input.content')
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content_external/abc.txt')))
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content_external/folder1/data.txt')))
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content_external2/folder2/setting.txt')))
def test_configuration_content_generate_with_multi_output(self):
impl = self.load_impl('assets/s60/implml/content2_with_multi_outputs.content')
- impl.set_output_root(self.output)
- results = impl.generate()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'content/test/override.txt')))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'include/s60.txt')))
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content/test/override.txt')))
+ self.assertTrue(os.path.exists(os.path.join(context.output,'include/s60.txt')))
def test_configuration_content_generate_with_refs(self):
impl = self.load_impl('assets/s60/implml/test_content_with_refs2.content')
- impl.set_output_root(self.output)
- results = impl.generate()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'content2p1/content2p2/override.txt')))
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content2p1/content2p2/override.txt')))
def test_configuration_content_generate_with_refs2(self):
impl = self.load_impl('assets/s60/implml/test_content_with_refs3.content')
- impl.set_output_root(self.output)
- results = impl.generate()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'example/content2p2/override.txt')))
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(os.path.join(self.output,'example/content2p2/override.txt')))
def test_configuration_content_generate_capital_letters(self):
impl = self.load_impl('assets/s60/implml/test_content_capital_file_input.content')
- impl.set_output_root(self.output)
- results = impl.generate()
- self.assertTrue(os.path.exists(impl.output))
- self.assertTrue(os.path.exists(os.path.join(impl.output,'content/test_CAP_letters.txt')))
+ context = plugin.GenerationContext(output=self.output)
+ results = impl.generate(context)
+ self.assertTrue(os.path.exists(context.output))
+ self.assertTrue(os.path.exists(os.path.join(context.output,'content/test_CAP_letters.txt')))
def test_get_refs(self):
def check(filename, expected_refs):
@@ -257,5 +258,20 @@
check('test_external_with_ref.content', ['CTD_Special.InputPath'])
check('test_filter_both.content', None)
+ def test_uses_layer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'contentproject')))
+ root_config = project.get_configuration('product.confml')
+
+ impl = self.load_impl('assets/s60/implml/test_content_capital_file_input.content')
+ self.assertFalse(impl.uses_layer(root_config.get_configuration_by_index(0)))
+ self.assertFalse(impl.uses_layer(root_config.get_configuration_by_index(1)))
+ self.assertTrue(impl.uses_layer(root_config.get_configuration_by_index(2)))
+
+ def test_get_copy_list_with_empty_file_input_from_sequence(self):
+ impl = self.load_impl('assets/s60/implml/empty_input_file_from_sequence.content')
+ copylist = impl.get_full_copy_list()
+ # There should be nothing in the copy list
+ self.assertEquals(copylist, [])
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/xsd/contentml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/xsd/contentml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/xsd/contentml2.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/xsd/contentml2.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeContentPlugin/setup.py
--- a/configurationengine/source/plugins/common/ConeContentPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeContentPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conecontentplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'contentplugin': ['xsd/*.xsd']},
test_suite = "contentplugin.tests.collect_suite",
# metadata for upload to PyPI
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+#
+# 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:
+#
+
+__version__ = 0.1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+#
+# 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:
+#
+
+__version__ = 0.1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/accesspoint_id_counter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/accesspoint_id_counter.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,365 @@
+#
+# 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:
+#
+'''
+Ruleml eval extension to count accesspoint id's
+'''
+
+import logging
+
+logger = logging.getLogger('cone.ruleplugin.evals.accesspoint_id_counter')
+
+def get_apindex_by_apname(aps, dns, apname):
+ """
+ Returns AccessPoint index by given AccessPoint name
+ """
+ cnt = _get_ApDnContainer_(aps, dns)
+ return cnt.get_apindex_by_apname(apname)
+
+def get_apid_by_apname(aps, dns, apname, wlan_support=True):
+ """
+ Returns AccessPoint id by given AccessPoint name
+ """
+ cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ return cnt.get_apid_by_apname(apname)
+
+def get_dnid_by_dnname(aps, dns, dnname, wlan_support=True):
+ """
+ Return DestinationNetwork id by given DestinationNetworks name
+ """
+ cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ return cnt.get_dnid_by_dnname(dnname)
+
+def get_apid_by_dnname_and_apname(aps, dns, dnname, apname, wlan_support=True):
+ """
+ Returns AccessPoint id by given DestinationNetwork name and AccessPoint name.
+ """
+ cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ return cnt.get_apid_by_dnname_and_apname(dnname, apname)
+
+def get_all_in_array(aps, dns, wlan_support=True):
+ """
+ Returns array containing all data:
+ [DN name],[DN id], [IAPS names], [IAPS ids], [IAPS indexes]
+ """
+ cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ return cnt.get_all_in_array()
+
+def _get_ApDnContainer_(aps, dns, wlan_support=True):
+ """
+ Returns populated ApDnContainer
+ """
+ cnt = ApDnContainer()
+
+ _read_dns_(dns, cnt)
+ _read_aps_(aps, cnt)
+
+ cnt._calc_dn_ids_()
+
+ if wlan_support:
+ cnt._calc_ap_ids_(2)
+ else:
+ cnt._calc_ap_ids_(1)
+
+ cnt._calc_ap_indexes_(1)
+
+ return cnt
+
+def _read_dns_(dns, cnt):
+ """
+ Reads DNs to internal objects to ApDnContainer.
+ """
+
+ dn_names = None
+ dn_ids = None
+ dn_iaps = [None]*10
+
+ for dn in dns.DN:
+ if dn.ref == 'Name':
+ dn_names = dn.value
+ if dn.ref == 'DNId':
+ dn_ids = dn.value
+ if dn.ref == 'IAP':
+ dn_iaps[0] = dn.value
+ if dn.ref == 'IAP2':
+ dn_iaps[1] = dn.value
+ if dn.ref == 'IAP3':
+ dn_iaps[2] = dn.value
+ if dn.ref == 'IAP4':
+ dn_iaps[3] = dn.value
+ if dn.ref == 'IAP5':
+ dn_iaps[4] = dn.value
+ if dn.ref == 'IAP6':
+ dn_iaps[5] = dn.value
+ if dn.ref == 'IAP7':
+ dn_iaps[6] = dn.value
+ if dn.ref == 'IAP8':
+ dn_iaps[7] = dn.value
+ if dn.ref == 'IAP9':
+ dn_iaps[8] = dn.value
+ if dn.ref == 'IAP10':
+ dn_iaps[9] = dn.value
+
+ logger.info('Parsed DN names: %s' % dn_names)
+ logger.info('Parsed DN ids: %s' % dn_ids)
+ logger.info('Parsed DN iaps: %s' % dn_iaps)
+
+ for i in range(len(dn_names)):
+ mydn = Dn()
+ mydn.set_id(dn_ids[i])
+ mydn.set_name(dn_names[i])
+ myiaps = [None]*10
+ for j in range(10):
+ myiaps[j] = dn_iaps[j][i]
+ mydn.set_iaps(myiaps)
+ cnt.add_dn(mydn)
+ return cnt
+
+def _read_aps_(aps, cnt):
+ """
+ Reads APs to internal objects to ApDnContainer.
+ """
+ ap_names = None
+ ap_ids1 = None
+
+ for ap in aps.AP:
+ if ap.ref == 'ConnectionName':
+ ap_names = ap.value
+ if ap.ref == 'ConnectionId':
+ ap_ids1 = ap.value
+
+ ap_ids2 = [None]*len(ap_names)
+ if ap_ids1 == None:
+ ap_ids1 = []
+
+
+ for i in range(len(ap_ids1)):
+ ap_ids2[i] = ap_ids1[i]
+
+
+ logger.info('Parsed AP names: %s' % ap_names)
+ logger.info('Parsed AP ids: %s' % ap_ids2)
+
+ for i in range(len(ap_names)):
+ myap = Ap()
+ myap.set_id(ap_ids2[i])
+ myap.set_name(ap_names[i])
+ cnt.add_ap(myap)
+ return cnt
+
+def _get_next_free_id_(bases, start_index=1):
+ """
+ Returns next id as a string that is not in use.
+ """
+
+ biggest_id = int(start_index)
+
+ for base in bases:
+ current_id = base.get_id()
+ if current_id != None or current_id != '':
+ if current_id > biggest_id:
+ biggest_id = current_id
+
+ return str(int(biggest_id) + 1)
+
+
+class ApDnContainer(object):
+ """
+ Container for AccessPoints and DestinationNetworks, that provides various access and search methods to them.
+ """
+
+ def __init__(self):
+ self.dns = []
+ self.aps = []
+
+ def __str__(self):
+ return "ApDnContainer(dns: " + str(self.dns) + ", aps:" + str(self.aps) + ")"
+
+ def add_dn(self, dn):
+ self.dns.append(dn)
+
+ def add_ap(self, ap):
+ self.aps.append(ap)
+
+ def get_all_dns(self):
+ return self.dns
+
+ def get_all_aps(self):
+ return self.aps
+
+ def _calc_dn_ids_(self):
+ for dn in self.dns:
+ if dn.get_id() == None or dn.get_id() == '':
+ dn.set_id(_get_next_free_id_(self.dns, 1))
+
+ def _calc_ap_indexes_(self, ind=1):
+ index = ind
+
+ for dn in self.dns:
+ for iap in dn.get_iaps():
+ if iap != None:
+ for ap in self.aps:
+ if ap.get_name() == iap and ap.get_index() == '':
+ ap.set_index(str(index))
+ index += 1
+
+ def _calc_ap_ids_(self, start_index=1):
+ """
+ Calculates unique index for every AccessPoint, if Easy_WLAN is given it always have index 1.
+ """
+
+ for ap in self.aps:
+ if ap.name == 'Easy WLAN':
+ ap.set_id('1')
+ logger.info('Easy_WLAN AP found. Setting 1 to AP id.')
+
+ for ap in self.aps:
+ if ap.get_id() == None or ap.get_id() == '':
+ ap.set_id(_get_next_free_id_(self.aps, int(start_index)))
+
+ def get_apid_by_apname(self, apname):
+ """
+ Returns Accesspoint id by given AccessPoint name
+ """
+
+ for ap in self.aps:
+ if ap.name == apname:
+ return ap.get_id()
+ return None
+
+ def get_apindex_by_apname(self, apname):
+ """
+ Returns Accesspoint index by given AccessPoint name
+ """
+
+ for ap in self.aps:
+ if ap.get_name() == apname:
+ return ap.get_index()
+ return None
+
+
+ def get_dnid_by_dnname(self, dnname):
+ """
+ Return DestinationNetwork id by given DestinationNetworks name
+ """
+ for dn in self.dns:
+ if dn.name == dnname:
+ return dn.id
+ return None
+
+ def get_apid_by_dnname_and_apname(self, dnname, apname):
+ """
+ Returns AccessPoint id by given DestinationNetwork name and AccessPoint name.
+ """
+ for dn in self.dns:
+ if dn.name == dnname:
+ iaps = dn.get_iaps()
+ for iap in range(len(iaps)):
+ if iaps[iap] != None and iaps[iap] == apname:
+ return self.get_apid_by_apname(apname)
+ return None
+
+ def get_all_in_array(self):
+ """
+ Returns array containing all data:
+ [DN name],[DN id], [IAPS names], [IAPS ids] [IAPS index]
+ """
+ ret = [None]*len(self.dns)
+
+ for i in range(len(self.dns)):
+ line = [None]*5
+ line[0] = self.dns[i].get_name()
+ line[1] = self.dns[i].get_id()
+ line[2] = self.dns[i].get_iaps()
+
+ ap_ids = [None]*10
+
+ for j in range(10):
+ ap_ids[j] = self.get_apid_by_apname(self.dns[i].get_iaps()[j])
+
+ line[3] = ap_ids
+
+ ap_indexes = [None]*10
+
+ for j in range(10):
+ ap_indexes[j] = self.get_apindex_by_apname(self.dns[i].get_iaps()[j])
+
+ line[4] = ap_indexes
+
+ ret[i] = line
+
+ return ret
+
+class Base(object):
+ """
+ Base data classes for AP and DN classes.
+ """
+ def __init__(self):
+ self.name = ''
+ self.id = ''
+
+ def set_name(self, name):
+ self.name = name
+
+ def get_name(self):
+ return self.name
+
+ def set_id(self, id):
+ self.id = id
+
+ def get_id(self):
+ return self.id
+
+class Dn(Base):
+ """
+ Destination network
+ """
+
+ def __init__(self):
+ self.name = None
+ self.id = None
+ self.iaps = [None]*10
+
+ def __str__(self):
+ return "Dn(name: " + self.name + ", id:" + self.id + ", iaps:" + str(self.iaps) + ")"
+
+ def set_iaps(self, iaps):
+ self.iaps = iaps
+
+ def set_iap(self, index, value):
+ self.iaps[index] = value
+
+ def get_iap(self, index):
+ return self.iaps[index]
+
+ def get_iaps(self):
+ return self.iaps
+
+class Ap(Base):
+
+ def __init__(self):
+ self.name = ''
+ self.id = ''
+ self.index = ''
+
+ def __str__(self):
+ return "Ap(name: " + self.name + ", id:" + self.id + ")"
+
+ def set_index(self, index):
+ self.index = index
+
+ def get_index(self):
+ return self.index
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/layer_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/layer_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,119 @@
+# 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:
+#
+
+'''
+Ruleml eval extension to check is passed ref changed on given layer(range).
+'''
+
+from cone.public import api
+
+import logging
+
+logger = logging.getLogger('cone.ruleplugin.evals.layer_utils')
+
+def give_changed_layers(feat):
+ """
+ Returns a list of booleans where True means that feature is changed in that layer. Index is
+ same than in configuration root's get_configuration_by_index().
+ """
+
+ logger.debug('Checking feature: %s' % feat.fqr)
+
+ root_conf = feat.get_root_configuration()
+ nro_of_layers = len(root_conf.list_configurations())
+ result = [False] * nro_of_layers
+
+ for i in range(0, nro_of_layers):
+ conf = root_conf.get_configuration_by_index(i)
+ logger.debug("Traversing data from configuration: %s" % conf.get_path())
+ datas = conf._traverse(type=api.Data, filters=[lambda d: d.fqr==feat.fqr])
+ for data in datas:
+ try:
+ if data.get_value() != None:
+ logger.debug("Feature '%s' is changed in layer %s with data '%s'" % (feat.fqr, i, data.get_value()))
+ result[i] = True
+ except Exception, e:
+ logger.debug("Failed to check Feature '%s' data in layer %s:", (e,i))
+ if result[i] == False:
+ logger.debug("Feature '%s' is not changed in layer: %s" % (feat.fqr, i))
+ logger.debug("Feature '%s' is changed in layers: %s" % (feat.fqr, result))
+ return result
+
+def changed_on_last_layer(feat):
+ """
+ Returns True if feature is changed in the last layer.
+ """
+
+ root_conf = feat.get_root_configuration()
+ conf = root_conf.get_configuration_by_index(-2)#autoconfig layer is ignored
+
+ def check(node):
+ if isinstance(node, api.Data) and node.fqr == feat.fqr:
+ return True
+ for obj in node._objects():
+ if check(obj):
+ return True
+
+ if check(conf):
+ return True
+ else:
+ return False
+
+def changed_on_autoconfig_layer(feat):
+ """
+ Returns True if feature is changed in the autoconfig layer.
+ """
+
+ root_conf = feat.get_root_configuration()
+ conf = root_conf.get_configuration_by_index(-1)
+
+ def check(node):
+ if isinstance(node, api.Data) and node.fqr == feat.fqr:
+ return True
+ for obj in node._objects():
+ if check(obj):
+ return True
+
+ if check(conf):
+ return True
+ else:
+ return False
+
+def changed_on_layer(feat, layer):
+ """
+ Returns True if feature is changed in the given layer.
+ """
+ try:
+ return give_changed_layers(feat)[layer]
+ except IndexError, e:
+ logger.warning("Given layer is not found: %s" % (layer))
+ return False
+
+def changed_on_layers(feat, findex, tindex):
+ """
+ Returns True if feature is changed in layer of given range.
+ """
+ layers = give_changed_layers(feat)
+
+ if findex == tindex:
+ return changed_on_layer(feat, findex)
+
+ for i in range(findex, tindex):
+ if i > len(layers):
+ continue
+ if layers != None and layers[i] != None and layers[i]:
+ return True
+ return False
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/shortcuts_conversion.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/shortcuts_conversion.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,95 @@
+#
+# 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:
+#
+
+import os
+
+def get_fixed_target_path(feature, setting):
+ type_ref = setting + '_type'
+ type = feature.get_feature(type_ref)
+ type_value = type.get_value()
+ ret = ""
+ if type_value == '1':
+ None
+ elif type_value == '2':
+ icon = feature.get_feature(setting + '_icon')
+ if icon != None:
+ ret = get_fixed_icon_target(icon)
+ else:
+ None
+
+ return ret
+
+def get_fixed_icon_target(icon):
+ targetPath = icon.get_feature('targetPath').get_value()
+ localPath = icon.get_feature('localPath').get_value()
+ target = get_target_without_extension(targetPath)
+ extension = get_correct_extension(localPath)
+ fixed = ""
+ if extension != None:
+ if len(target) > 0 and len(extension) > 0:
+ fixed = target + extension
+ return fixed
+
+def get_target_without_extension(targetPath):
+ (target,_) = os.path.splitext(targetPath)
+ return target
+
+def get_correct_extension(localPath):
+
+ if localPath != None:
+ (_,extension) = os.path.splitext(localPath)
+ if extension == '.bmp':
+ return '.mbm'
+ elif extension == '.svg':
+ return '.mif'
+ else:
+ return extension
+ else:
+ return None
+
+def get_shortcut_string(feature, setting):
+ type_ref = setting + '_type'
+ type_value = feature.get_feature(type_ref).get_value()
+ ret = ""
+ if type_value == '1':
+ app_ref = setting + '_app'
+ application = feature.get_feature(app_ref).get_value()
+ ret = application
+ elif type_value == '2':
+ url = feature.get_feature(setting+'_URL').get_value()
+ title = feature.get_feature(setting+'_title').get_value()
+
+ if title == None:
+ title = ""
+ else:
+ title = 'customtitle=' + title
+
+ icon = feature.get_feature(setting + '_icon')
+ image_path = icon.get_feature('targetPath').get_value()
+
+ icon_str = ""
+
+ if image_path != None and image_path != "":
+ icon_str = 'iconmifpath='
+ if image_path.endswith('.mif'): index = '16384'
+ else: index = '0'
+ icon_str = icon_str + image_path + ';' + index + '&'
+
+ ret = url + '?custom?' + icon_str + title
+ return ret
+
+#print get_shortcut_string('1', '2', '3')
+#http://www.nokia2.com?custom?iconmifpath=Z:\\resource\\apps\\icon2.mbm;1&customtitle=Nokia2
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+#
+# 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:
+#
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+ String 1
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/implml/test1.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/implml/test1.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+ {% changed_on_layer( @{StringFeatureTest.Value1}, -1) %} configures result1 = True
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer2/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer2/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ String 2
+ String 2
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer2/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer2/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer3/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer3/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ String 3
+ String 3
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer3/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer3/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer4/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer4/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ String 4
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer4/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer4/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer5/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer5/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ String 5
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer5/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/layer5/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/layerproject/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/ctd/confml/CTD_commsdat.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/ctd/confml/CTD_commsdat.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,460 @@
+
+
+
+
+
+
+ Selection for A-GPS access point
+
+
+
+
+
+
+
+ Selection for MMS access point
+
+
+
+
+
+
+ Selection for Browser access point
+
+
+
+
+
+
+ Setting for the default Destination Network
+
+
+
+
+
+
+
+ Selection for web feeds autoupdate access point
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+ Selection for Email access point
+
+
+
+
+
+
+ GPRS connection method (CM) definitions
+
+
+ The access point name that is visible to the user.
+
+
+ The access point name for this GPRS connection
+
+
+ Define the destination network that the access point will be added to. Can be left empty.
+
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Addressing that the network uses.
+
+
+
+
+ User name
+
+
+ Prompt password at connection time.
+
+
+
+
+ Password.
+
+
+ Password authentication method.
+
+
+
+
+ Access point homepage in URL format.
+
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+
+
+
+
+ WLAN connection method (CM) definitions
+
+
+ The access point name that is visible to the user.
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Service set identifier (SSID) of the primary WLAN network.
+
+
+ Define the destination network that the access point will be added to. Can be left empty.
+
+
+
+
+
+ Access point homepage in URL format.
+
+
+ Determines the network infrastructure.
+ If there is a WLAN access point in the network then this should be Infrastructure.
+
+
+
+
+
+ Defines whether the SSID should be actively scanned.
+ This is needed if the SSID is hidden (not broadcasted by the AP)
+
+
+
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+
+ 802.11 Channel ID (1-14). Used only when connecting/setting up adhoc network.
+
+
+
+ Security mode of the WLAN network.
+
+
+
+
+
+
+
+ Index of default WEP key. Used only when security mode is WEP.
+
+
+
+
+
+
+ WEP authentication mode. Only used when security mode is WEP.
+
+
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+
+ Specifies that when the security mode is WPA or WPA2 if the PSK mode is enabled.
+ If this is off then EAP mode is used and the list of EAPs needs to be defined.
+
+
+
+
+ The length of the specified pre-shared key (in WPA pre-shared key field)
+
+
+ WPA/WPA2 pre-shared key in plain text. ASCII character set values between 32-126 must be used. Minimum length is 8 characters and maximum 63.
+ You need to also define the WPA pre-shared key length field accordingly
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eap Key 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ConfirmFirst
+ IPv4
+ No
+ Normal
+
+
+
+
+
+
+ ConfirmFirst
+ Infrastructure
+ Open
+ 0
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/ctd/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/ctd/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/.metadata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/ap.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/ap.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+ Default
+
+
+ Full 1
+
+
+ Full 2
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/commsdatcreator.confml
Binary file configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/commsdatcreator.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/testdata.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/confml/testdata.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+ image_conf_imakerapi.mk
+
+
+ 0
+ V .50.2009.04.0113 RND
+ myProduct
+ myProduct
+
+
+
+ 5
+ 25
+ 7
+ 5
+ 10
+ 2
+ 5
+ 10
+ 8
+
+
+ String 1
+ String 2
+ x
+ x
+ x
+ x
+ x
+ x
+
+
+ <ударениÑ>
+ <ελληνικά>カタカナελληνικά>
+ ударениÑ>
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/implml/accesspoint_id_counter.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/implml/accesspoint_id_counter.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+ True configures APIDCTest.FullSequence.StringSubSetting = {% apid( @{APs}, @{DNs} ) %}
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/.metadata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/confml/data.confml
Binary file configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/confml/data.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/layer2/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/ruleproject/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/runtests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+#
+# 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:
+#
+
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/unittest_accesspoint_id_counter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/unittest_accesspoint_id_counter.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,123 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import pkg_resources
+import re
+
+from legacyruleplugin import ruleml, relations
+from cone.public import api, exceptions
+from legacyruleplugin.evals import accesspoint_id_counter
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class TestAPIDC(unittest.TestCase):
+ def test_get_ApDnContainer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals('Internet', container.get_all_dns()[0].get_name())
+ self.assertEquals('1', container.get_all_dns()[0].get_id())
+ self.assertEquals(['IAP11', 'IAP12', 'IAP13', None, None, None, None, None, None, None], container.get_all_dns()[0].get_iaps())
+
+ self.assertEquals('MMS', container.get_all_dns()[1].get_name())
+ self.assertEquals('2', container.get_all_dns()[1].get_id())
+ self.assertEquals(['IAP21', 'IAP22', 'IAP23', 'IAP13', None, None, None, None, None, None], container.get_all_dns()[1].get_iaps())
+
+ self.assertEquals('Operator', container.get_all_dns()[2].get_name())
+ self.assertEquals('3', container.get_all_dns()[2].get_id())
+ self.assertEquals(['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None], container.get_all_dns()[2].get_iaps())
+
+ self.assertEquals('IAP11', container.get_all_aps()[0].get_name())
+ self.assertEquals('1', container.get_all_aps()[0].get_id())
+
+ def test_get_apid_by_apname(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals('1', container.get_apid_by_apname('IAP11'))
+ self.assertEquals('2', container.get_apid_by_apname('IAP12'))
+ self.assertEquals('7', container.get_apid_by_apname('IAP13'))
+
+ def test_get_dnid_by_dnname(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals('1', container.get_dnid_by_dnname('Internet'))
+ self.assertEquals('2', container.get_dnid_by_dnname('MMS'))
+ self.assertEquals('3', container.get_dnid_by_dnname('Operator'))
+
+
+ def test_get_apid_by_dnname_and_apname(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals('2', container.get_apid_by_dnname_and_apname('Internet', 'IAP12'))
+
+ def test_calc_ap_ids(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals('9', container.get_all_aps()[6].get_id())
+
+ def test_all_in_array(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals(container.get_all_in_array(), [['Internet', '1', ['IAP11', 'IAP12', 'IAP13', None, None, None, None, None, None, None], ['1', '2', '7', None, None, None, None, None, None, None], ['1', '2', '3', None, None, None, None, None, None, None]], ['MMS', '2', ['IAP21', 'IAP22', 'IAP23', 'IAP13', None, None, None, None, None, None], ['4', '8', '6', '7', None, None, None, None, None, None], ['4', '5', '6', '3', None, None, None, None, None, None]], ['Operator', '3', ['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None], [None, None, '9', None, None, None, None, None, None, None], [None, None, '7', None, None, None, None, None, None, None]]])
+
+ def test_get_next_free_id(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals("4", accesspoint_id_counter._get_next_free_id_(container.get_all_dns()))
+ self.assertEquals("10", accesspoint_id_counter._get_next_free_id_(container.get_all_aps()))
+
+ def test_get_apindex_by_apname(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+
+ self.assertEquals("4", container.get_apindex_by_apname("IAP21"))
+ self.assertEquals("1", container.get_apindex_by_apname("IAP11"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/unittest_layer_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/evals/tests/unittest_layer_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,90 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import pkg_resources
+import re
+import logging
+
+from legacyruleplugin import ruleml, relations
+from cone.public import api, exceptions
+from legacyruleplugin.evals import layer_utils
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+#logger = logging.getLogger("cone.ruleplugin.evals.layer_utils")
+#logger.setLevel(logging.DEBUG)
+#ch = logging.StreamHandler()
+#ch.setLevel(logging.DEBUG)
+#logger.addHandler(ch)
+
+class TestLayerUtils(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_give_changed_layers(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layerproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ self.assertEquals(layer_utils.give_changed_layers(dview.get_feature("StringFeatureTest.Value1")), [True, True, True, True, True])
+ self.assertEquals(layer_utils.give_changed_layers(dview.get_feature("StringFeatureTest.Value2")), [False, True, True, False, False])
+
+ def test_changed_on_last_layer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layerproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ self.assertTrue(layer_utils.changed_on_last_layer(dview.get_feature("StringFeatureTest.Value1")))
+ self.assertFalse(layer_utils.changed_on_last_layer(dview.get_feature("StringFeatureTest.Value2")))
+
+ def test_changed_on_layer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layerproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),-1))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),0))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),1))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),2))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),3))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),4))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value1"),5))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),-1))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),0))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),1))
+ self.assertTrue(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),2))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),3))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),4))
+ self.assertFalse(layer_utils.changed_on_layer(dview.get_feature("StringFeatureTest.Value2"),5))
+
+ def test_changed_on_layers(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layerproject')))
+ config = project.get_configuration('root.confml')
+ dview = config.get_default_view()
+
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),0,4))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),2,3))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),2,2))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),1,7))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),8,9))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),0,1))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),1,5))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/relations.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/relations.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,391 @@
+#
+# 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:
+#
+
+'''
+implementation for ruleml relations.
+'''
+import os
+import StringIO
+import logging
+import operator as ops
+import re
+import sys, traceback
+
+log = logging.getLogger('cone.ruleplugin.relations')
+
+from legacyruleplugin import rules
+from cone.public import api, utils, exceptions, plugin
+
+class RelationFactory(api.FactoryBase):
+ @ classmethod
+ def get_relation_by_name(cls, relation_name):
+ """
+ Get the class name by file extension.
+ """
+ try:
+ return rules.RELATIONS.get(relation_name)
+ except KeyError:
+ raise exceptions.NotSupportedException("No Relation class found for name %s" % relation_name)
+
+ @ classmethod
+ def get_relations(cls, configuration, relation):
+ try:
+ relations = []
+ (left_expression,relation_name,right_expression) = parse_rule(relation)
+ relation = cls.get_relation_by_name(relation_name)(configuration, left_expression, right_expression)
+ relations.append(relation)
+ propagated_relations = cls.get_relations(configuration, right_expression)
+ if propagated_relations:
+ for relation in propagated_relations:
+ relations.append(relation)
+ return relations
+ except exceptions.ParseError:
+ return None
+
+
+class ConfigurationContext(rules.DefaultContext):
+
+ def __init__(self, data):
+ rules.DefaultContext.__init__(self, data)
+
+ # Callback called with the setting reference when a setting is dereferenced
+ # as a terminal expression
+ self.ref_terminal_callback = None
+
+ # Callback called with the setting reference when a setting is dereferenced
+ # inside an EvalExpression
+ self.ref_eval_callback = None
+
+ # Callback called with the setting reference when the value of a setting
+ # is set inside a SetExpression
+ self.ref_set_callback = None
+
+ def handle_terminal(self, expression):
+ try:
+ value = self.data.get_default_view().get_feature(expression).get_value()
+
+ # Got a valid ref, call the callback
+ if self.ref_terminal_callback:
+ self.ref_terminal_callback(expression)
+
+ return value
+ except exceptions.NotFound,e:
+ """ return the expression itself if it is not a fearef """
+ #print "handle_terminal constant %s" % (expression)
+ try:
+ return eval(expression)
+ except (NameError,SyntaxError), e:
+ return expression
+
+ def eval(self, ast, expression, value):
+ #print "expression %s = %s" % (expression,value)
+ pass
+
+class ConfigurationBaseRelation(rules.BaseRelation):
+ def __init__(self, data, left, right):
+ self.context = ConfigurationContext(data)
+ super(ConfigurationBaseRelation, self).__init__(data, left, right)
+
+class RequireRelation(ConfigurationBaseRelation):
+ KEY = 'requires'
+ def __init__(self, data, left, right):
+ super(RequireRelation, self).__init__(data, left, right)
+ self.context = ConfigurationContext(data)
+
+class ConfigureRelation(ConfigurationBaseRelation):
+ KEY = 'configures'
+ def __init__(self, data, left, right):
+ self.context = ConfigurationContext(data)
+ super(ConfigureRelation, self).__init__(data, left, right)
+
+ # A plugin.RelationExecutionResult object is stored here
+ self._execution_result = None
+
+
+ def execute(self, context=None):
+ self._execution_result = None
+ exec_results = []
+
+ result = rules.BaseRelation.execute(self, context)
+
+ if len(exec_results) > 0:
+ # There should be only one ConfigureExpression inside a ConfigureRelation
+ if len(exec_results) > 1:
+ log.warning("Execution of ConfigureRelation returned more than one result, ignoring all except the first")
+ self._execution_result = exec_results[0]
+
+ return result
+
+ def get_execution_result(self):
+ """
+ Return the execution result from the most recent call to execute().
+ """
+ return self._execution_result
+
+def handle_configure(self, left, right):
+ if left and right:
+ return True
+ elif not left:
+ return True
+ return False
+
+def handle_set(self, left, right):
+ left.set_value(right)
+
+def handle_filenamejoin(self, left, right):
+ def extract_dirname(path):
+ """Extract directory name (will always contain a trailing slash or backslash)"""
+ pos = max(path.rfind('/'), path.rfind('\\'))
+ if pos == -1: return path + '/'
+ else: return path[:pos + 1]
+
+ def extract_filename(path):
+ pos = max(path.rfind('/'), path.rfind('\\'))
+ if pos == -1: return path
+ else: return path[pos + 1:]
+
+ return extract_dirname(left) + extract_filename(right)
+
+def handle_plus(self, left, right):
+ return left + right
+
+def handle_minus(self, left, right):
+ return left - right
+
+def handle_multiply(self, left, right):
+ return left * right
+
+def handle_divide(self, left, right):
+ return left / right
+
+class ConfigureExpression(rules.TwoOperatorExpression):
+ PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS']
+ KEY = 'configures'
+ OP = handle_configure
+
+ def eval(self, context, **kwargs):
+ input_refs = []
+ affected_refs = []
+
+ # Evaluate the left-hand side expression, catching refs for the result
+ try:
+ context.ref_terminal_callback = lambda ref: input_refs.append(ref)
+ context.ref_eval_callback = lambda ref: input_refs.append(ref)
+ evaluated_left = self.left.eval(context, **kwargs)
+ finally:
+ context.ref_terminal_callback = None
+ context.ref_eval_callback = None
+
+ if evaluated_left:
+ # If left evaluated to True, evaluate the right-hand side and
+ # catch refs from SetExpression evaluations
+ try:
+ context.ref_set_callback = lambda ref: affected_refs.append(ref)
+ self.value = self.right.eval(context, **kwargs)
+ finally:
+ context.ref_set_callback = None
+ else:
+ self.value = True
+
+ if not self.value:
+ left_keys = []
+ for ref in self.ast.extract_refs(str(self.left)):
+ for key in context.get_keys(ref):
+ left_keys.append(key)
+
+ for key in left_keys:
+ self.ast.add_error(key, { 'error_string' : 'CONFIGURES right side value is "False"',
+ 'left_key' : key,
+ 'rule' : self.ast.expression
+ })
+
+ return self.value
+
+class MultiplyExpression(rules.TwoOperatorExpression):
+ expression = "multiply_operation"
+ PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
+ KEY= '*'
+ OP = handle_multiply
+
+class DivideExpression(rules.TwoOperatorExpression):
+ expression = "divide_operation"
+ PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
+ KEY= '/'
+ OP = handle_divide
+
+class PlusExpression(rules.TwoOperatorExpression):
+ expression = "plus_operation"
+ PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
+ KEY= '+'
+ OP = handle_plus
+
+class MinusExpression(rules.TwoOperatorExpression):
+ expression = "minus_operation"
+ PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
+ KEY= '-'
+ OP = handle_minus
+
+class EvalExpression(rules.OneParamExpression):
+ expression = "__eval__"
+ PRECEDENCE = rules.PRECEDENCES['PREFIX_OPERATORS']
+ KEY = '__eval__'
+
+ def __init__(self, ast, expression):
+ super(EvalExpression, self).__init__(ast, expression)
+ self.expression = expression
+ self._str_to_eval = eval(expression.expression)
+ #self.default_view = default_view
+
+ def extract_refs(self):
+ result = []
+ result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('${', '}')))
+ result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('@{', '}')))
+ return result
+
+ def eval(self, context, **kwargs):
+ # Using the configuration to pass the eval globals dictionary to here,
+ # since there isn't any easy way to do this more elegantly
+ globals_and_locals = {}
+ if hasattr(context, '_eval_expression_globals_dict'):
+ globals_and_locals = context._eval_expression_globals_dict
+
+ str_to_eval = self._str_to_eval
+
+ def expand_feature_ref(ref, index):
+ var_name = "__fea_%05d" % index
+ globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref)
+ if context.ref_eval_callback:
+ context.ref_eval_callback(ref)
+ return var_name
+ def expand_value_ref(ref, index):
+ var_name = "__feaval_%05d" % index
+ globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref).get_value()
+ if context.ref_eval_callback:
+ context.ref_eval_callback(ref)
+ return var_name
+
+ str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_feature_ref, delimiters=('@{', '}'))
+ str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_value_ref, delimiters=('${', '}'))
+
+ # Strip leading and trailing whitespace to avoid indentation problems
+ str_to_eval = str_to_eval.strip()
+
+ ret = None
+
+ try:
+ ret = eval(str_to_eval, globals_and_locals)
+ return ret
+ except SyntaxError, e:
+ logging.getLogger('cone.ruleml').warning("Invalid syntax in eval: %s" % (str_to_eval) )
+ self.ast.add_error(self.expression, { 'error_string' : 'Invalid syntax in eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
+ except Exception, e:
+ logging.getLogger('cone.ruleml').warning("Execution failed for eval: %s %s: %s" % (str_to_eval, type(e), e) )
+ self.ast.add_error(self.expression, { 'error_string' : 'Execution failed for eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
+
+rules.OPERATORS[EvalExpression.KEY] = EvalExpression
+
+class FilenamejoinExpression(rules.TwoOperatorExpression):
+ expression = "filenamejoin"
+ PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
+ KEY = 'filenamejoin'
+ OP = handle_filenamejoin
+
+rules.OPERATORS[FilenamejoinExpression.KEY] = FilenamejoinExpression
+
+class SetExpression(rules.TwoOperatorExpression):
+ PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS']
+ KEY= '='
+ OP = handle_set
+
+# def eval(self, context):
+# try:
+# variable = context.configuration.get_default_view().get_feature(self.left.expression)
+# value = self.right.eval(context)
+# variable.set_value(value)
+# logging.getLogger('cone.ruleml').info("Set %r = %r from %r" % (self.left.expression, value, self.right.expression) )
+# if context.ref_set_callback:
+# context.ref_set_callback(self.left.expression)
+# return True
+# except exceptions.NotFound,e:
+# self.ast.add_error(self.left.expression, { 'error_string' : 'Setting value failed, because of %s' % e,
+# 'left_key' : self.left.expression,
+# 'rule' : self.ast.expression})
+# return False
+
+ def eval(self, context, **kwargs):
+
+ value = self.right.eval(context, **kwargs)
+ ref = self.left.get_ref()
+ context.set(ref, value, **kwargs)
+ return True
+
+_relations_and_operators_backup = None
+
+def register():
+ """
+ Register the relations and operators to ConE rules.
+ """
+ global _relations_and_operators_backup
+ if _relations_and_operators_backup is None:
+ # Create the backup copies of the dictionaries
+ rels_backup = rules.RELATIONS.copy()
+ ops_backup = rules.OPERATORS.copy()
+ assert rels_backup is not rules.RELATIONS
+ assert ops_backup is not rules.OPERATORS
+ _relations_and_operators_backup = (rels_backup, ops_backup)
+
+ # Register relations and operators to rules
+ rules.RELATIONS[RequireRelation.KEY] = RequireRelation
+ rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
+ rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
+ rules.OPERATORS[PlusExpression.KEY] = PlusExpression
+ rules.OPERATORS[SetExpression.KEY] = SetExpression
+ rules.OPERATORS[MinusExpression.KEY] = MinusExpression
+ rules.OPERATORS[MultiplyExpression.KEY] = MultiplyExpression
+ rules.OPERATORS[DivideExpression.KEY] = DivideExpression
+
+def unregister():
+ """
+ Undo the changes made by a call to register().
+ """
+ global _relations_and_operators_backup
+ if _relations_and_operators_backup is not None:
+ rules.RELATIONS = _relations_and_operators_backup[0]
+ rules.OPERATORS = _relations_and_operators_backup[1]
+ _relations_and_operators_backup = None
+
+def parse_rule(rulestring):
+ """
+ Divide the given rule string into (left side, relation, right side) components.
+ @return: Triple (left side, relation, right side)
+ """
+ left_expression = ''
+ relation_name = None
+ right_expression = ''
+ for token in rules.get_tokens(rulestring):
+ if relation_name == None:
+ if token in rules.RELATIONS.keys():
+ relation_name = token
+ else:
+ left_expression += ' ' + token
+ else:
+ right_expression += ' ' + token
+
+ if relation_name == None:
+ raise exceptions.ParseError('invalid rule definition %s' % rulestring)
+
+ return (left_expression,relation_name,right_expression)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/ruleml.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/ruleml.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,303 @@
+#
+# 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:
+#
+'''
+Legacy RuleML plug-in to support RuleML 1 and 2 after rule engine changes
+in cone.public.rules. The new RuleML version is 3, and it uses the setting
+reference format ${MyFeature.MySetting} in the rules.
+
+The rule engine (rules.py) before the change is contained in this plug-in.
+
+NOTE THAT THIS PLUG-IN WILL NOT BE MAINTAINED, ALL NEW DEVELOPMENT SHOULD
+HAPPEN IN THE NEW RULE PLUG-IN. IF NEW FUNCTIONALITY IS REQUIRED IN AN
+EXISTING RULEML FILE, THE CHANGES SHOULD BE MADE TO THE NEW RULE PLUG-IN
+AND THE EXISTING RULEML FILE CONVERTED TO RULEML 3.
+'''
+
+
+import os
+import sys
+import logging
+import shutil
+import pkg_resources
+
+import __init__
+import re
+
+from legacyruleplugin import relations, rules
+from cone.public import exceptions,plugin,utils,api
+
+class RuleImpl(plugin.ImplBase):
+ """
+ MakeImpl plugin finds feature references that are configured in a .ruleml file
+ and generate a rule from them
+ """
+ IMPL_TYPE_ID = 'ruleml'
+ DEFAULT_INVOCATION_PHASE = 'pre'
+
+ def __init__(self, ref, configuration, relation_container):
+ """
+ Overloading the default constructor
+ """
+ plugin.ImplBase.__init__(self,ref,configuration)
+ self.relation_container = relation_container
+
+ def list_output_files(self):
+ """
+ Return a list of output files as an array.
+ """
+ return []
+
+ def generate(self, context=None):
+ relation_container = self.get_relation_container()
+ relation_container.context = context
+ return relation_container.execute(context)
+
+ def has_tag(self, tags, policy=None):
+ # RuleML should always be executed, regardless of the tags
+ return True
+
+ def get_relation_container(self):
+ return self.relation_container
+
+ def get_refs(self):
+ """
+ Return a list of all ConfML setting references that affect this
+ implementation. May also return None if references are not relevant
+ for the implementation.
+ """
+ refs = []
+ relations = self.get_relations()
+ for relation in relations:
+ # get refs from relation return a tuple (left side refs, right side refs)
+ # only the left side refs are the "input" refs
+ refs += relation.get_refs()
+ # If the rules do not have any references return None to disable filter by refs
+ if refs == []:
+ refs = None
+ return refs
+
+ def get_relations(self):
+ return self.relation_container.get_relations()
+
+class RuleBuiltinsModule(object):
+ pass
+
+class RulemlRelationContainer(plugin.RelationContainer):
+ """
+ Relation container for RuleML rules.
+
+ Basically this is a wrapper for rules.RelationContainer that adapts
+ it to the interface of plugin.RelationContainer.
+ """
+ def __init__(self, configuration, source, rule_list, eval_globals):
+ plugin.RelationContainer.__init__(self, configuration, source=source)
+ self.configuration = configuration
+ self.relation_container = rules.RelationContainerImpl()
+ self.eval_globals = eval_globals
+ self.context = None
+ for rule in rule_list:
+ self.relation_container.add_relation(rule)
+
+ def execute(self, context=None):
+ results = []
+
+ # Create the autoconfig if not done already
+ autoconfig = plugin.get_autoconfig(self.configuration)
+
+ # Register relations etc. to the rule engine.
+ # Due to unit test issues the relations are not registered
+ # in the relations module, but only for the duration of
+ # rule parsing and execution
+ relations.register()
+ try:
+ # Using the configuration to pass the eval globals dict to the
+ # eval expression. The configuration only contains the globals
+ # dict for the duration of the rule execution, so hopefully this
+ # shouldn't mess anything up
+ self._set_builtin_eval_globals()
+ context._eval_expression_globals_dict = self.eval_globals
+ for i, rel in enumerate(self.relation_container):
+ index = i + 1
+
+ # Execute
+ self._execute_relation_and_log_error(rel, self.source, index, context)
+
+ # Collect execution result if supported
+ if hasattr(rel, 'get_execution_result'):
+ result = rel.get_execution_result()
+ if isinstance(result, plugin.RelationExecutionResult):
+ result.source = self.source
+ result.index = index
+ results.append(result)
+
+ del context._eval_expression_globals_dict
+
+ if self.relation_container.has_errors():
+ for error in self.relation_container.get_errors():
+ logging.getLogger('cone.ruleml_relation_container(%s)' % self.source).error(error)
+
+ if self.context:
+ self.context.results += results
+ self.context.add_changed_refs(autoconfig.list_leaf_datas())
+ return results
+ finally:
+ relations.unregister()
+
+ def get_relation_count(self):
+ return len(self.relation_container)
+
+ def get_relations(self):
+ return list(self.relation_container)
+
+ def _set_builtin_eval_globals(self):
+ """
+ Add built-in attributes into the eval globals dictionary.
+ """
+
+ builtins = RuleBuiltinsModule()
+ builtins.configuration = self.configuration
+
+ self.eval_globals['ruleml'] = builtins
+
+class RuleImplReaderBase(plugin.ReaderBase):
+ NAMESPACE = None # Used as a base class, so should have no namespace
+ FILE_EXTENSIONS = ['ruleml']
+
+ def __init__(self, resource_ref, configuration):
+ self.resource_ref = resource_ref
+ self.configuration = configuration
+
+ @classmethod
+ def read_impl(cls, resource_ref, configuration, etree):
+ reader = cls(resource_ref, configuration)
+
+ # Register relations etc. to the rule engine.
+ # Due to unit test issues the relations are not registered
+ # in the relations module, but only for the duration of
+ # rule parsing and execution
+ relations.register()
+ try:
+ rules = reader.parse_rules(resource_ref, etree)
+ eval_globals = reader.parse_eval_globals(etree)
+ lineno = utils.etree.get_lineno(etree)
+
+ # Create an ImplContainer to hold each rule as its own
+ # RuleML implementation
+ main_impl = plugin.ImplContainer(resource_ref, configuration)
+ main_impl.lineno = lineno
+
+ for rule in rules:
+ relation_container = RulemlRelationContainer(
+ configuration = configuration,
+ source = "%s:%d" % (resource_ref, rule.lineno),
+ rule_list = [rule],
+ eval_globals = eval_globals)
+
+ impl = RuleImpl(resource_ref, configuration, relation_container)
+ impl.lineno = rule.lineno
+ rule.implml = impl
+
+ main_impl.append(impl)
+ finally:
+ relations.unregister()
+
+ return main_impl
+
+class RuleImplReader1(RuleImplReaderBase):
+ NAMESPACE = 'http://www.s60.com/xml/ruleml/1'
+ NAMESPACE_ID = 'ruleml1'
+ ROOT_ELEMENT_NAME = 'ruleml'
+
+ def __init__(self, resource_ref, configuration):
+ RuleImplReaderBase.__init__(self, resource_ref, configuration)
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('legacyruleplugin', 'xsd/ruleml.xsd')
+
+ def parse_rules(self, ref, etree):
+ rules = []
+ for elem in etree.getiterator("{%s}rule" % self.NAMESPACE):
+ lineno = utils.etree.get_lineno(elem)
+ for rule in relations.RelationFactory.get_relations(self.configuration, elem.text):
+ rule.ref = ref
+ rule.lineno = lineno
+ rules.append(rule)
+ return rules
+
+ def parse_eval_globals(self, etree):
+ return {}
+
+class RuleImplReader2(RuleImplReaderBase):
+ NAMESPACE = 'http://www.s60.com/xml/ruleml/2'
+ NAMESPACE_ID = 'ruleml2'
+ ROOT_ELEMENT_NAME = 'ruleml'
+
+ def __init__(self, resource_ref, configuration):
+ RuleImplReaderBase.__init__(self, resource_ref, configuration)
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('legacyruleplugin', 'xsd/ruleml2.xsd')
+
+ def parse_rules(self, ref, etree):
+ rules = []
+ for elem in etree.getiterator("{%s}rule" % self.NAMESPACE):
+ lineno = utils.etree.get_lineno(elem)
+ for rule in relations.RelationFactory.get_relations(self.configuration, self._replace_eval_blocks(elem.text)):
+ rule.ref = ref
+ rule.lineno = lineno
+ rules.append(rule)
+ return rules
+
+ def parse_eval_globals(self, etree):
+ eval_globals = {}
+ for elem in etree.getiterator("{%s}eval_globals" % self.NAMESPACE):
+ text = ""
+ if elem.get('file') != None:
+ self._read_eval_globals_from_file(elem.get('file'), eval_globals)
+ else:
+ try:
+ # Strip surrounding whitespace, otherwise there might be Python
+ # indentation errors
+ text = elem.text.strip()
+ exec(text, eval_globals)
+ except Exception, e:
+ logging.getLogger('cone.ruleml(%s)' % self.resource_ref).warning('Failed to evaluate eval_globals block, exception: %s' % (e))
+ return eval_globals
+
+ def _read_eval_globals_from_file(self, relative_path, eval_globals):
+ # Get the actual path (relative to the current implementation file)
+ base_path = os.path.dirname(self.resource_ref)
+ pyfile_path = os.path.normpath(os.path.join(base_path, relative_path)).replace('\\', '/')
+ # Read the data and execute
+ try:
+ resource = None
+ resource = self.configuration.get_resource(pyfile_path)
+ text = resource.read()
+ exec(text.replace('\r', ''), eval_globals)
+ except Exception, e:
+ logging.getLogger('cone.ruleml(%s)' % self.resource_ref).warning('Cannot import eval file: %s. Exception: %s' % (pyfile_path, e))
+ finally:
+ if resource is not None: resource.close()
+
+
+ @classmethod
+ def _replace_eval_blocks(cls, code):
+ return utils.expand_delimited_tokens(
+ string = code,
+ expander_func = lambda ref, index: '__eval__ %r' % ref,
+ delimiters =('{%', '%}'))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/rules.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/rules.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,801 @@
+#
+# 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:
+#
+
+import operator as ops
+import logging
+import tokenize
+from token import ENDMARKER, NAME, ERRORTOKEN
+import StringIO
+
+from cone.public import container
+
+RELATIONS = {}
+
+def abstract():
+ import inspect
+ caller = inspect.getouterframes(inspect.currentframe())[1][3]
+ raise NotImplementedError(caller + ' needs to be implemented')
+
+def get_tokens(tokenstr):
+ result = []
+ tokens = []
+ tokenstr = tokenstr.replace('\r', '')
+ name_buffer = [] # Temp buffer for reading name tokens
+ last_epos = None
+ for toknum, tokval, spos, epos, _ in tokenize.generate_tokens(StringIO.StringIO(unicode(tokenstr)).readline):
+ #print "toknum: %r, tokval: %r, spos: %r, epos: %r" % (toknum, tokval, spos, epos)
+ val = tokval.strip('\r\n\t ')
+
+ if toknum == ENDMARKER and name_buffer:
+ tokens.append(''.join(name_buffer))
+
+ # Ignore whitespace (this ignores also the end marker,
+ # since its value is empty)
+ if val == '': continue
+
+ # Put NAME, and ERRORTOKEN tokens through the temp
+ # buffer
+ if toknum in (NAME, ERRORTOKEN):
+ # If this and the previous token in the temp buffer are not adjacent,
+ # they belong to separate tokens
+ if name_buffer and spos[1] != last_epos[1]:
+ tokens.append(''.join(name_buffer))
+ name_buffer = []
+
+ name_buffer.append(val)
+ last_epos = epos
+ # Other tokens can just go directly to the token list
+ else:
+ if name_buffer:
+ tokens.append(''.join(name_buffer))
+ name_buffer = []
+ tokens.append(val)
+
+ while len(tokens) > 0:
+ val = tokens.pop(0)
+ # Join the refs with dot in between them to make them dotted refs
+ if val == '.':
+ newval = ".".join([result.pop(),tokens.pop(0)])
+ result.append( newval )
+ else:
+ result.append( val )
+
+ return result
+
+class RelationException(Exception):
+ pass
+
+#### The containers are here ####
+
+
+class RelationBase(object):
+ """
+ RelationBase defines a base class for all named relations that can be applied between objects.
+ e.g. Relation depends, that can be applied in Rule
+ """
+ relation_name = "RelationBase"
+ def __init__(self, data, left, right):
+ self.description = ""
+ self.data = data or container.DataContainer()
+ self.left = left
+ self.right = right
+
+ def __str__(self):
+ """
+ @return: A string presentation of the relation object
+ """
+ return "%s %s %s" % (self.left,self.relation_name,self.right)
+
+ def __repr__(self):
+ return "%s(ref=%r, lineno=%r)" % (self.__class__.__name__,
+ getattr(self, 'ref', None),
+ getattr(self, 'lineno', None))
+
+ def get_name(self):
+ """
+ @return: The relation name.
+ """
+ return self.relation_name
+
+ def get_description(self):
+ """
+ @return: a possible description of the relation.
+ """
+ return self.description
+
+ def execute(self):
+ """
+ Execute the relation object.
+ """
+ pass
+
+
+class RelationContainer(RelationBase, list):
+ """
+ This class provides the RelationContainer interface for collecting
+ relation sets into one place which can be executed through the container.
+ """
+ def __init__(self, data=None):
+ super(RelationContainer, self).__init__(data, 'LContainer', 'RContainer')
+ self.value_list = list()
+
+ def append(self, value):
+ self.value_list.append(value)
+
+ def __iter__(self):
+ return self.value_list.__iter__()
+
+ def __len__(self):
+ return len(self.value_list)
+
+ def __or__(self, other):
+ """
+ This function adds two RelationContainers to each other and removes
+ duplicates from the result.
+ The modification is inplace and the returned value is called object.
+ """
+ self.value_list = set(self.value_list) | set(other.value_list)
+ return self
+
+ def __unicode__(self):
+ if self:
+ ret = ''
+ for value in self:
+ ret += unicode(value)
+ else:
+ ret = 'No relations'
+ return ret
+
+ def find_relations(self, refs): abstract()
+ def add_relation(self, relation): abstract()
+ def has_errors(self): abstract()
+
+class RelationContainerImpl(RelationContainer):
+ """ Base implementation for RelationContainer to use in ConE rules
+ """
+ def execute(self):
+ ret = True
+ i = 0
+ for relation in self:
+ i += 1
+ r = relation.execute()
+ ret = ret and r
+ return ret
+
+ def find_relations(self, refs):
+ relations = []
+ for ref in refs:
+ for relation in self:
+ if relation.has_ref(ref):
+ relations.append(relation)
+ return relations
+
+ def add_relation(self, relation):
+ self.append(relation)
+
+ def has_ref(self, refs):
+ for ref in refs:
+ for relation in self:
+ if relation.has_ref(ref):
+ return True
+ return False
+
+ def has_errors(self):
+ for relation in self:
+ if relation.has_errors():
+ return True
+ return False
+
+ def get_errors(self):
+ errors = []
+ for relation in self:
+ errors += relation.get_errors()
+ return errors
+
+#### The relations are here ####
+
+class BaseRelation(RelationBase):
+ """ BaseRelation implements the basic evaluation logic for relations
+ This class abstract and should be extended for concrete implementation of
+ relation type.
+
+ Subclasses need to set their own context in their constructor before this
+ class's constructor is called if custom context is needed. If context not
+ set then DefaultContext is used.
+ """
+ KEY = 'base_relation'
+
+ def __init__(self, data, left, right):
+ # Context needs to be overridden for special purposes
+ try:
+ self.__getattribute__('context')
+ except AttributeError:
+ self.context = DefaultContext(data)
+
+ left = self.expand_rule_elements(left)
+ right = self.expand_rule_elements(right)
+ super(BaseRelation, self).__init__(data, left, right)
+ self.interpreter = ASTInterpreter(context=self.context)
+
+ def execute(self, context=None):
+ """
+ @return Returns error dictionary
+
+ In the client code proper way to check if the rule applies:
+ info = relation.execute()
+ if not info.has_errors():
+ else: HANDLE ERRORS
+ """
+ # logger.debug("Interpreter context %s" % self.interpreter.context)
+ self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
+ ret = self.interpreter.eval(context, relation=self)
+ return ret
+
+ def get_keys(self):
+ """ Returns the references from this relation.
+ """
+ refs = ASTInterpreter.extract_refs(self.left)
+ refs += ASTInterpreter.extract_refs(self.right)
+ return refs
+
+ def has_ref(self, ref):
+ """ Returns if the 'ref' is included in this relation
+ """
+ return ref in self.get_keys()
+
+ def has_errors(self):
+ return bool(self.interpreter.errors)
+
+ def get_refs(self):
+ extracted_refs = ASTInterpreter.extract_refs(self.left)
+
+ # Handle eval expressions (a somewhat ugly hack,
+ # but this is a legacy plug-in so...)
+ interpreter = ASTInterpreter(self.left)
+ for expression in interpreter.parse_tree:
+ if hasattr(expression, 'extract_refs'):
+ extracted_refs.extend(expression.extract_refs())
+
+ # Filter out entries that evaluate successfully as Python code
+ # e.g. True or 123
+ result = []
+ for item in extracted_refs:
+ try: eval(item)
+ except: result.append(item)
+ else: pass
+ return result
+
+ def _eval_rside_value(self, value): abstract()
+ def _compare_value(self, value): abstract()
+
+ def extract_erroneus_features_with_values(self):
+ """
+ Extract references who have errors.
+
+ Returns dictionary { 'reference' : 'value' }
+ """
+ data_dict = {}
+ for ref in ASTInterpreter.extract_refs(self.right):
+ value = self.data.get_feature(ref)
+ if self._compare_value(value):
+ data_dict[ref] = value
+ elif value == None:
+ data_dict[ref] = None
+ return data_dict
+
+ def get_errors(self):
+ return self.interpreter.errors
+
+ def expand_rule_elements(self, rule):
+ """ Expans rule elements base on the reference.
+ Context is used for fetching the child elements for parent references
+ which uses asterisk identifier for selecting all child features:
+ 'parent_feature.*' -> 'child_fea_1 and child_fea_2'.
+ """
+ tokens = get_tokens(rule) # [token for token in rule.split()]
+
+ expanded_rule = ""
+ for token in tokens:
+ if token.endswith('.*'):
+ index = token.index('.*')
+ parent_ref = token[:index]
+ children = self.context.get_children_for_reference(parent_ref)
+ expanded_element = ' and '.join([child.reference for child in children])
+ if expanded_rule:
+ expanded_rule = '%s and %s' % (expanded_rule, expanded_element.rstrip())
+ else:
+ expanded_rule = expanded_element.rstrip()
+ elif token.lower() in OPERATORS:
+ expanded_rule += ' %s ' % token
+ else:
+ if expanded_rule:
+ expanded_rule += '%s'% token
+ else:
+ expanded_rule = token
+ return expanded_rule.strip()
+
+class RequireRelation(BaseRelation):
+ KEY = 'requires'
+RELATIONS[RequireRelation.KEY] = RequireRelation
+
+class ExcludesRelation(BaseRelation):
+ KEY = 'excludes'
+
+RELATIONS['excludes'] = ExcludesRelation
+
+################################
+# Abstract syntax tree builder #
+################################
+
+def nor(expression, a, b):
+ return not ops.or_(a, b)
+
+def nand(expression, a, b):
+ return not ops.and_(a, b)
+
+def truth_and(expression, a, b):
+ return ops.truth(a) and ops.truth(b)
+
+class DefaultContext(object):
+ """ DefaultContext implements ConE specific context for handling rules
+ """
+ def __init__(self, data):
+ self.data = data
+
+ def eval(self, ast, expression, value):
+ pass
+
+ def get_keys(self, refs):
+ return ASTInterpreter.extract_refs(refs)
+
+ def get_children_for_reference(self, reference):
+ # implement ConE specific children expansion
+ pass
+
+ def handle_terminal(self, expression):
+ try:
+ return int(expression)
+ except:
+ return expression
+
+PRECEDENCES = {
+ 'PREFIX_OPERATORS' : 10,
+ 'MULDIV_OPERATORS' : 8,
+ 'ADDSUB_OPERATORS' : 7,
+ 'SHIFT_OPERATORS' : 6,
+ 'BITWISE_OPERATORS' : 5,
+ 'COMPARISON_OPERATORS' : 4,
+ 'SET_OPERATORS' : 3,
+ 'BOOLEAN_OPERATORS' : 2,
+ 'RELATION_OPERATORS' : 1,
+ 'NOT_DEFINED' : 0
+}
+
+class Expression(object):
+ PRECEDENCE = PRECEDENCES['NOT_DEFINED']
+ KEY = 'base_expression'
+
+ def __init__(self, ast):
+ self.ast = ast
+ self.value = None
+
+ def get_title(self):
+ return self.KEY
+
+ def eval(self, context, **kwargs): pass
+
+class OneParamExpression(Expression):
+ PARAM_COUNT = 1
+ def __init__(self, ast, expression):
+ super(OneParamExpression, self).__init__(ast)
+ self.expression = expression
+
+ def __unicode__(self):
+ return u'%s %s' % (self.KEY, self.expression)
+
+ def eval(self, context, **kwargs):
+ self.value = self.OP(self.expression.eval(context, **kwargs))
+ context.eval(self.ast, self, self.value)
+ return self.value
+
+class TwoOperatorExpression(Expression):
+ PARAM_COUNT = 2
+ OP = None
+ EVAL_AS_BOOLS = True
+
+ def __init__(self, ast, left, right):
+ super(TwoOperatorExpression, self).__init__(ast)
+ self.left = left
+ self.right = right
+
+ def __unicode__(self):
+ return u'%s %s %s' % (self.left, self.KEY, self.right)
+
+ def eval(self, context, **kwargs):
+ self.value = self.OP(self.left.eval(context, **kwargs), self.right.eval(context, **kwargs))
+ context.eval(self.ast, self, self.value)
+ return self.value
+
+class TwoOperatorBooleanExpression(TwoOperatorExpression):
+ def eval(self, context, **kwargs):
+ self.value = self.OP(bool(self.left.eval(context, **kwargs)), bool(self.right.eval(context, **kwargs)))
+ context.eval(self.ast, self, self.value)
+ return self.value
+
+class TerminalExpression(Expression):
+ KEY = 'terminal'
+
+ def __init__(self, ast, expression):
+ super(TerminalExpression, self).__init__(ast)
+ self.expression = expression
+
+ def eval(self, context, **kwargs):
+ """ Use context to eval the value
+ Expression on TerminalExpression is feature reference or value
+ context should handle the reference conversion to correct value
+ """
+ from cone.public import exceptions
+ try:
+ context.configuration.get_default_view().get_feature(self.expression)
+ self.value = context.handle_terminal(self.expression)
+ except exceptions.NotFound:
+ self.value = context.convert_value(self.expression)
+
+ return self.value
+
+ def __unicode__(self):
+ return self.expression
+
+ def __repr__(self):
+ return self.expression
+
+ def get_ref(self):
+ """
+ @return: The setting reference, e.g. 'MyFeature.MySetting'
+ """
+ return self.expression
+
+
+class NegExpression(OneParamExpression):
+ PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
+ KEY= '-'
+ OP = ops.neg
+
+class AndExpression(TwoOperatorBooleanExpression):
+ PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
+ KEY= 'and'
+ OP = truth_and
+
+class NandExpression(TwoOperatorBooleanExpression):
+ PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
+ KEY = 'nand'
+ OP = nand
+
+class OrExpression(TwoOperatorBooleanExpression):
+ PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
+ KEY = 'or'
+ OP = ops.or_
+
+class XorExpression(TwoOperatorBooleanExpression):
+ PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
+ KEY = 'xor'
+ OP = ops.xor
+
+class NorExpression(TwoOperatorBooleanExpression):
+ PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
+ KEY = 'nor'
+ OP = nor
+
+class EqualExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '=='
+ OP = ops.eq
+
+class NotEqualExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '!='
+ OP = ops.ne
+
+class LessThanExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '<'
+ OP = ops.lt
+
+class GreaterThanExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '>'
+ OP = ops.gt
+
+class LessThanEqualExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '<='
+ OP = ops.le
+
+class GreaterThanEqualExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
+ KEY = '>='
+ OP = ops.ge
+
+
+def handle_require(expression, left, right):
+ if left and right:
+ return True
+ elif not left:
+ return True
+ return False
+
+class RequireExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['RELATION_OPERATORS']
+ KEY = 'requires'
+ OP = handle_require
+
+ def eval(self, context, **kwargs):
+ super(RequireExpression, self).eval(context, **kwargs)
+ if not self.value:
+ left_keys = []
+ for ref in self.ast.extract_refs(unicode(self.left)):
+ for key in context.get_keys(ref):
+ left_keys.append(key)
+
+ for key in left_keys:
+ self.ast.add_error(key, { 'error_string' : 'REQUIRES right side value is "False"',
+ 'left_key' : key,
+ 'rule' : self.ast.expression
+ })
+ return self.value
+
+def handle_exclude(expression, left, right):
+ if left and not right:
+ return True
+ elif not left:
+ return True
+ return False
+
+class ExcludeExpression(TwoOperatorExpression):
+ PRECEDENCE = PRECEDENCES['RELATION_OPERATORS']
+ KEY = 'excludes'
+ OP = handle_exclude
+
+ def eval(self, context, **kwargs):
+ super(ExcludeExpression, self).eval(context, **kwargs)
+ if not self.value:
+ left_keys = []
+ for ref in self.ast.extract_refs(unicode(self.left)):
+ for key in context.get_keys(ref):
+ left_keys.append(key)
+
+ for key in left_keys:
+ self.ast.add_error(key, { 'error_string' : 'EXCLUDE right side value is "True"',
+ 'left_key' : key,
+ 'rule' : self.ast.expression
+ })
+ return self.value
+
+
+class NotExpression(OneParamExpression):
+ PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
+ KEY = 'not'
+ OP = ops.not_
+
+class TruthExpression(OneParamExpression):
+ PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
+ KEY = 'truth'
+ OP = ops.truth
+
+LEFT_PARENTHESIS = '('
+RIGHT_PARENTHESIS = ')'
+class SimpleCondition(EqualExpression):
+ """
+ A simple condition object that can refer to a model object and evaluate if the value matches
+ """
+ def __init__(self, left, right):
+ lterm = TerminalExpression(None, left)
+ rterm = TerminalExpression(None, right)
+ EqualExpression.__init__(self, None, lterm, rterm)
+
+
+# in format KEY : OPERATOR CLASS
+OPERATORS = {
+ 'and' : AndExpression,
+ 'nand' : NandExpression,
+ 'or' : OrExpression,
+ 'xor' : XorExpression,
+ 'nor' : NorExpression,
+ 'not' : NotExpression,
+ 'truth' : TruthExpression,
+ '==' : EqualExpression,
+ '!=' : NotEqualExpression,
+ '<' : LessThanExpression,
+ '>' : GreaterThanExpression,
+ '<=' : LessThanEqualExpression,
+ '>=' : GreaterThanEqualExpression,
+ 'requires' : RequireExpression,
+ 'excludes' : ExcludeExpression,
+ '-' : NegExpression
+ }
+
+def add_operator(key, operator_class=None, baseclass=RequireExpression):
+ """
+ Add new operator key and operator class.
+ If operator class isn't provided the baseclass parameter is used as
+ operator base. The baseclass parameter is RequireExpression by default
+ which has success condition left_rule=True and right_rule=True
+
+ """
+ OPERATORS[key] = operator_class or create_new_class(key, baseclass)
+
+def create_new_class(key, baseclass):
+ ns = baseclass.__dict__.copy()
+ ns['KEY'] = key
+ key_pieces = key.split('_')
+ class_prefix = ''.join([key_piece.capitalize() for key_piece in key_pieces])
+ new_class = type(class_prefix + 'Expression', (baseclass,), ns)
+ return new_class
+
+class ParseException(Exception): pass
+
+class ASTInterpreter(object):
+ def __init__(self, infix_expression=None, context=None):
+ """ Takes infix expression as string """
+ self.context = context or DefaultContext(None)
+ # logger.debug("AST init context: %s" % self.context)
+ self._init_locals(infix_expression)
+ if infix_expression:
+ self.create_ast()
+
+ def _init_locals(self, infix_expression):
+ # The result value of full eval of the parse_tree
+ self.value = None
+ self.warnings = {}
+ self.errors = {}
+ self.postfix_array = []
+ self.parse_tree = []
+ self.expression = infix_expression
+
+ def __unicode__(self):
+ s = ''
+ for expr in self.parse_tree:
+ s += unicode(expr)
+ return s
+
+ def add_error(self, key, error_dict):
+ if self.errors.has_key(key):
+ self.errors[key].append(error_dict)
+ else:
+ self.errors[key] = [error_dict]
+
+ def create_ast(self, infix_expression=None):
+ if infix_expression:
+ self._init_locals(infix_expression)
+ self._infix_to_postfix()
+ self._create_parse_tree()
+ return self.parse_tree
+
+ def _infix_to_postfix(self):
+ """
+ Shunting yard algorithm used to convert infix presentation to postfix.
+ """
+ if not self.expression:
+ raise ParseException('Expression is None')
+ tokens = get_tokens(self.expression) # [token for token in self.expression.split()]
+ stack = []
+ # logger.debug('TOKENS: %s' % tokens)
+ for token in tokens:
+ # logger.debug('TOKEN: %s' % token)
+ if token.lower() in OPERATORS:
+ op_class = OPERATORS.get(token)
+ if stack:
+ while len(stack) != 0:
+ top = stack[-1]
+ if top in OPERATORS:
+ top_operator = OPERATORS.get(top)
+ if op_class.PRECEDENCE <= top_operator.PRECEDENCE:
+ self.postfix_array.append(stack.pop())
+ else:
+ # Break from loop if top operator precedence is less.
+ break
+ else:
+ # If top not operator break from loop
+ break
+ stack.append(token)
+ elif token == LEFT_PARENTHESIS:
+ # logger.debug('Left parenthesis')
+ stack.append(token)
+ elif token == RIGHT_PARENTHESIS:
+ # logger.debug('Right parenthesis')
+ left_par_found = False
+ stack_token = stack.pop()
+ while stack_token:
+ if stack_token != LEFT_PARENTHESIS:
+ self.postfix_array.append(stack_token)
+ else:
+ left_par_found = True
+ break
+ if stack:
+ stack_token = stack.pop()
+ else:
+ stack_token = None
+
+ if not left_par_found:
+ raise ParseException('Mismatched parenthesis "%s".' % LEFT_PARENTHESIS)
+ else:
+ # logger.debug('Adding value to output. %s' % repr((token)))
+ self.postfix_array.append((token))
+
+ # There should be only operators left in the stack
+ if stack:
+ # logger.debug('Operators in stack.')
+ operator = stack.pop()
+ while operator:
+ if operator != LEFT_PARENTHESIS:
+ self.postfix_array.append(operator)
+ else:
+ raise ParseException('Mismatched parenthesis "%s".' % LEFT_PARENTHESIS)
+ if stack:
+ operator = stack.pop()
+ else:
+ operator = None
+
+ # logger.debug('Infix to postfix conversion: %s' % self.postfix_array)
+ return self.postfix_array
+
+ def _create_parse_tree(self):
+ self.parse_tree = []
+ for token in self.postfix_array:
+ if token in OPERATORS:
+ # logger.debug('OP: %s' % (token))
+ expression_class = OPERATORS[token]
+ params = []
+ for i in range(expression_class.PARAM_COUNT):
+ try:
+ params.append(self.parse_tree.pop())
+ except IndexError, e:
+ raise ParseException('Syntax error: "%s"' % self.expression)
+ params.reverse()
+ expression = expression_class(self, *params)
+
+ # logger.debug('The operation: %s' % expression)
+ self.parse_tree.append(expression)
+ else:
+ expression = TerminalExpression(self, token)
+ self.parse_tree.append(expression)
+
+ #logger.debug('THE STACK: %s' % self.parse_tree)
+ #for s in self.parse_tree:
+ # logger.debug('Stack e: %s' % str(s))
+
+ return self.parse_tree
+
+ def eval(self, context=None, **kwargs):
+ """ Evals the AST
+ If empty expression is given, None is returned
+ """
+ for expression in self.parse_tree:
+ self.value = expression.eval(context, **kwargs)
+ return self.value
+
+ @staticmethod
+ def extract_refs(expression):
+ tokens = get_tokens(expression)
+ refs = []
+ for token in tokens:
+ if not token.lower() in OPERATORS and token != LEFT_PARENTHESIS and token != RIGHT_PARENTHESIS:
+ refs.append(token.strip('%s%s' % (LEFT_PARENTHESIS, RIGHT_PARENTHESIS)))
+ return refs
+
+##################################################################
+# Create and configure the main level logger
+logger = logging.getLogger('cone')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+#
+# 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:
+#
+
+import sys, os, unittest
+
+# Path to the directory where this file is located
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+from testautomation import plugin_utils
+plugin_utils.plugin_test_init(ROOT_PATH)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/confml/testdata.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/confml/testdata.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/implml/terminalexpression.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/implml/terminalexpression.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+ True configures EvalTest.StringLenResult = 22
+ True configures EvalTest.StringLenResult = {% SOME_VALUE %}
+ SOME_VALUE = 12345
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/confml/invalid_python_eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/confml/invalid_python_eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/implml/invalid_python_eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ True configures EvalTest2.StringResult = {% -> this is invalid python code %}
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test2/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/confml/invalid_python_eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/confml/invalid_python_eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/implml/invalid_python_eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+ True configures EvalTest3.StringResult = 22
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/implml/scripts/test_eval.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/implml/scripts/test_eval.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+#
+# 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:
+#
+
+this is some other invalid python code
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test3/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/confml/invalid_python_eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/confml/invalid_python_eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/implml/invalid_python_eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+ True configures EvalTest4.StringResult = 22
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test4/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/confml/invalid_python_eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/confml/invalid_python_eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/implml/invalid_python_eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ True configures EvalTest5.StringResult = {% 7/0 %}
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/implml/scripts/test_eval.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/implml/scripts/test_eval.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+#
+# 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:
+#
+
+this is some other invalid python code
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test5/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/confml/invalid_python_eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/confml/invalid_python_eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/implml/invalid_python_eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ True configures EvalTest6.StringResult = Invalid.setting
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/errorruleproject/test6/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/.metadata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/.project
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/.project Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+
+
+ config_project
+
+
+
+
+
+ com.nokia.tools.variant.confml.core.ConfMLLayerBuilder
+
+
+
+
+
+ com.nokia.tools.variant.confml.core.ConfMLLayerNature
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/.metadata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/confml/actionpriorities.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/confml/actionpriorities.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5
+ 25
+ 7
+ 5
+ 10
+ 2
+ 6
+ 10
+ 9
+ Hello
+ World
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/implml/gsm.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/implml/gsm.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+ operations.minus == 5 configures operations.minus = operations.minus1 - operations.minus2
+ operations.minus1 == 25 configures operations.minus1 = operations.minus3 * operations.minus2
+ operations.minus4 == 10 configures operations.minus4 = operations.minus4 / operations.minus5
+ operations.minus6 == 6 configures operations.minus6 = operations.minus7 + operations.minus8
+ operations.string1 == 'Hello' configures operations.string1 = operations.string1 + operations.string2
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/rule/config_project/platforms/customsw/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/.metadata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/arithmetic.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/arithmetic.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5
+ 20
+
+ 5
+ 20
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/commsdatcreator.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/commsdatcreator.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1935 @@
+
+
+ Used to configure whether CommsDat generation from these settings is enabled.
+
+ This is the master switch that determines whether CommsDat is created in the first boot
+ of the device based on Configuration Tool output. Set this to Yes if you are creating variant
+ and need to configure anything under Default CommsDat settings.
+
+
+
+
+ Read-only flag that indicates the CommsDatCreator start-up status in runtime.
+
+
+
+
+ Global networking related settings not tied to individual connection methods.
+
+
+
+ GPRS attach mode (attach when needed/when available).
+
+
+
+
+
+
+ Default GPRS access point. Used when the phone is used as a modem for a PC.
+ The corresponding UI setting is Connection-Packet data-Access point.
+
+
+
+
+ Default icon for destination networks.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default priority for LAN bearer type.
+
+
+
+
+ Default priority for WLAN bearer type.
+
+
+
+
+ Default priority for PAN bearer type.
+
+
+
+
+ Default priority for outgoing GPRS bearer type.
+
+
+
+
+ Default priority for incoming GPRS bearer type.
+
+
+
+
+ Default priority for CDMA 2000 bearer type.
+
+
+
+
+ Default priority for outgoing dial bearer type.
+
+
+
+
+ Default priority for incoming dial bearer type.
+
+
+
+
+ Default priority for VPN bearer type.
+
+
+
+
+ Default priority for MIP bearer type.
+
+
+
+
+ Default UI priority of LAN connection.
+
+
+
+
+ Default UI priority for WLAN bearer type.
+
+
+
+
+ Default UI priority for PAN bearer type.
+
+
+
+
+ Default UI priority for outgoing GPRS bearer type.
+
+
+
+
+ Default UI priority for incoming GPRS bearer type.
+
+
+
+
+ Default UI priority for CDMA 2000 bearer type.
+
+
+
+
+ Default UI priority for outgoing dial bearer type.
+
+
+
+
+ Default UI priority for incoming dial bearer type.
+
+
+
+
+ Default UI priority for VPN bearer type.
+
+
+
+
+ Default UI priority for MIP bearer type.
+
+
+
+
+ Specifies how the applications' default connection is specified.
+
+
+
+
+
+
+
+
+ The name of the default connection (connection method or destination network).
+ Default connection type parameter needs to be set accordingly.
+
+
+
+
+ For GPRS the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For GPRS the time (in seconds) to stay online when session has closed. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For GPRS the time (in seconds) to stay online when socket has closed. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For CSD the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For CSD the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For CSD the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For WLAN the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For WLAN the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ For WLAN the time (in seconds) to stay online when all socket activity has ceased. -1 for unlimited time.
+ Leave empty to use the product default value.
+
+
+
+
+ How often WLAN networks are scanned when idle.
+
+
+
+
+
+
+
+
+ Defines whether default values are being used for the advanced WLAN settings (recommended).
+
+
+
+
+ Defines how many times packets bigger than RTS Threshold are been resent.
+
+
+ Defines how many times packets smaller than RTS Threshold are been resent.
+
+
+ Minimum size of a packet for which CTS/RTS handshake has been used.
+
+
+ Transmission power level in use. In mWs. 4, 10 or 100 mW.
+
+
+
+
+
+ Defines whether the CCX radio measurements are allowed.
+
+
+
+
+ Defines whether power saving methods are active. Disabling WLAN
+ power save might increase interoperability but will dramatically shorten battery life.
+
+
+
+
+
+ GPRS connection method (CM) definitions
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Addressing that the network uses.
+
+
+
+
+ The access point name for this GPRS connection
+
+
+ User name
+
+
+ Prompt password at connection time.
+
+
+
+
+ Password.
+
+
+ Password authentication method.
+
+
+
+
+ WAP gateway IP address.
+
+
+ Start page of the connection method. In URL format.
+
+
+ Attempts a secure WTLS connection to the gateway.
+
+
+
+
+ Indicates whether a connection-oriented or connectionless API should be used.
+
+
+
+
+ IP address of the interface.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ Allow EDGE usage.
+
+
+
+
+ Specifies the service provider type. Used when filtering connection methods for certain purpose.
+
+
+
+
+
+
+
+ WLAN connection method (CM) definitions
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Service set identifier (SSID) of the primary WLAN network.
+
+
+ Start page of the connection method. In URL format.
+
+
+ Determines the network infrastructure.
+ If there is a WLAN access point in the network then this should be Infrastructure.
+
+
+
+
+ Security mode of the WLAN network.
+
+
+
+
+
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically in which case this should be empty.
+
+
+ The gateway IP address.
+ Typically allocated automatically in which case this should be empty.
+
+
+ Network mask. Typically allocated automatically in which case this should be empty.
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ Defines whether the SSID should be actively scanned.
+ This is needed if the SSID is hidden (not broadcasted by the AP)
+
+
+
+
+
+ 802.11 Channel ID (1-14). Used only when connecting/setting up adhoc network.
+
+
+
+ IP address of the interface.
+ Typically allocated automatically so this can be left empty.
+
+
+ Index of default WEP key. Used only when security mode is WEP.
+
+
+
+
+
+
+ WEP authentication mode. Only used when security mode is WEP.
+
+
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WEP key length in bits.
+
+
+
+
+
+ WEP key format.
+
+
+
+
+ WEP key data (in format specified by corresponding WEP key format field).
+
+
+ WPA/WPA2 pre-shared key in plain text. ASCII character set values between 32-126 must be used. Minimum length is 8 characters and maximum 63.
+ You need to also define the WPA pre-shared key length field accordingly
+
+
+ Specifies that when the security mode is WPA or WPA2 if the PSK mode is enabled.
+ If this is off then EAP mode is used and the list of EAPs needs to be defined.
+
+
+
+
+ The length of the specified pre-shared key (in WPA pre-shared key field)
+
+
+
+ A list of Extensible Authentication Protocols (EAPs) in use. The format is +xxx,+xxx,+xxx where xxx indicates the enabled EAP method ID as
+ specified in the IANA registry: http://www.iana.org/assignments/eap-numbers. For example to enable EAP-SIM the string needs to be "+018".
+ The list is in priority order, highest priority first.
+
+
+
+ The username used with EAP-GTC.
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear).
+
+
+ Defines which EAP tunneling method is used with EAP-GTC.
+
+
+
+
+
+ The username used with EAP-TLS.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether the server's realm is compared with own realm.
+ This provides extra security but it depends on the network infrastructure and set-up whether this will work.
+
+
+
+
+ Specifies whether TLS requires that the server authenticates it (the client).
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear)
+
+
+ The list of allowed cipher suites. In the format +xxx,+xxx,+xxx... where xxx is the cipher suite identifier.
+ 004: TLS_RSA_WITH_RC4_128_MD5, 005: TLS_RSA_WITH_RC4_128_SHA, 010: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ 019: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 022: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 047: TLS_RSA_WITH_AES_128_CBC_SHA
+ 050: TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 051: TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 052: TLS_DH_anon_WITH_AES_128_CBC_SHA
+ For example +004 enables only RSA with RC4 and MD5.
+
+
+
+ The subject key id value of the user certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the user certificate. Ignored by the implementation currently!
+
+
+ The serial number of the user certificate. Ignored by the implementation currently!
+
+
+ The subject key id value of the CA certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the CA certificate. Ignored by the implementation currently!
+
+
+ The serial number of the CA certificate. Ignored by the implementation currently!
+
+
+ Defines which EAP tunneling method is used with EAP-TLS.
+
+
+
+
+
+
+ The username used with EAP-LEAP.
+
+
+ The password used with EAP-LEAP.
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear).
+
+
+ The username used with EAP-SIM.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether IMSI is sent always when authentication or is pseudonym usage allowed.
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear)
+
+
+ Defines which EAP tunneling method is used with EAP-SIM.
+
+
+
+
+
+
+ The username used with EAP-TTLS.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether the server's realm is compared with own realm.
+ This provides extra security but it depends on the network infrastructure and set-up whether this will work.
+
+
+
+
+ Specifies whether TTLS requires that the server authenticates it (the client).
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear).
+
+
+ The list of allowed cipher suites. In the format +xxx,+xxx,+xxx... where xxx is the cipher suite identifier.
+ 004: TLS_RSA_WITH_RC4_128_MD5, 005: TLS_RSA_WITH_RC4_128_SHA, 010: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ 019: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 022: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 047: TLS_RSA_WITH_AES_128_CBC_SHA
+ 050: TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 051: TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 052: TLS_DH_anon_WITH_AES_128_CBC_SHA
+ For example +004 enables only RSA with RC4 and MD5.
+
+
+
+ A list of Extensible Authentication Protocols (EAPs) in tunneled by EAP-TTLS. The format is +xxx,+xxx,+xxx where xxx indicates the enabled EAP method ID as
+ specified in the IANA registry: http://www.iana.org/assignments/eap-numbers. For example to enable EAP-SIM encapsulation the string needs to be "+018".
+ The list is in priority order, highest priority first. Note that the encapsulate type's encapsulation parameter needs to be configured accordingly.
+
+
+ The subject key id value of the user certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the user certificate. Ignored by the implementation currently!
+
+
+ The serial number of the user certificate. Ignored by the implementation currently!
+
+
+ The subject key id value of the CA certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the CA certificate. Ignored by the implementation currently!
+
+
+ The serial number of the CA certificate. Ignored by the implementation currently!
+
+
+ The username used with EAP-AKA.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether IMSI is sent always when authentication or is pseudonym usage allowed.
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear).
+
+
+ Defines which EAP tunneling method is used with EAP-AKA.
+
+
+
+
+
+
+ The username used with EAP-PEAP.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether the server's realm is compared with own realm.
+ This provides extra security but it depends on the network infrastructure and set-up whether this will work.
+
+
+
+
+ Specifies whether PEAP requires that the server authenticates it (the client).
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear)
+
+
+ The list of allowed cipher suites. In the format +xxx,+xxx,+xxx... where xxx is the cipher suite identifier.
+ 004: TLS_RSA_WITH_RC4_128_MD5, 005: TLS_RSA_WITH_RC4_128_SHA, 010: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ 019: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 022: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 047: TLS_RSA_WITH_AES_128_CBC_SHA
+ 050: TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 051: TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 052: TLS_DH_anon_WITH_AES_128_CBC_SHA
+ For example +004 enables only RSA with RC4 and MD5.
+
+
+
+ Is PEAP version 0 allowed. If in doubt enable only this one.
+
+
+
+
+ Is PEAP version 1 allowed.
+
+
+
+
+ Is PEAP version 2 allowed.
+
+
+
+
+ A list of Extensible Authentication Protocols (EAPs) in tunneled by EAP-PEAP. The format is +xxx,+xxx,+xxx where xxx indicates the enabled EAP method ID as
+ specified in the IANA registry: http://www.iana.org/assignments/eap-numbers. For example to enable EAP-SIM encapsulation the string needs to be "+018".
+ The list is in priority order, highest priority first. Note that the encapsulate type's encapsulation parameter needs to be configured accordingly.
+
+
+ The subject key id value of the user certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the user certificate. Ignored by the implementation currently!
+
+
+ The serial number of the user certificate. Ignored by the implementation currently!
+
+
+ The subject key id value of the CA certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the CA certificate. Ignored by the implementation currently!
+
+
+ The serial number of the CA certificate. Ignored by the implementation currently!
+
+
+ The username used with EAP-MSCHAPv2.
+
+
+ The password used with EAP-MSCHAPv2.
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear)
+
+
+ Defines which EAP tunneling method is used with EAP-MSCHAPv2.
+
+
+
+
+
+ The username used with EAP-FAST.
+
+
+ The realm used for device identification to the server.
+
+
+ Specifies whether the server's realm is compared with own realm.
+ This provides extra security but it depends on the network infrastructure and set-up whether this will work.
+
+
+
+
+ Specifies whether TTLS requires that the server authenticates it (the client).
+
+
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear)
+
+
+ The list of allowed cipher suites. In the format +xxx,+xxx,+xxx... where xxx is the cipher suite identifier.
+ 004: TLS_RSA_WITH_RC4_128_MD5, 005: TLS_RSA_WITH_RC4_128_SHA, 010: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ 019: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 022: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 047: TLS_RSA_WITH_AES_128_CBC_SHA
+ 050: TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 051: TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 052: TLS_DH_anon_WITH_AES_128_CBC_SHA
+ For example +004 enables only RSA with RC4 and MD5.
+
+
+
+ A list of Extensible Authentication Protocols (EAPs) in tunneled by EAP-FAST. The format is +xxx,+xxx,+xxx where xxx indicates the enabled EAP method ID as
+ specified in the IANA registry: http://www.iana.org/assignments/eap-numbers. For example to enable EAP-SIM encapsulation the string needs to be "+018".
+ The list is in priority order, highest priority first. Note that the encapsulate type's encapsulation parameter needs to be configured accordingly.
+
+
+ EAP-FAST authenticated provisioning mode allowed
+
+
+
+
+ EAP-FAST unauthenticated provisioning mode allowed
+
+
+
+
+ EAP-FAST warn ADHP no PAC
+
+
+
+
+ EAP-FAST warn ADHP no matching PAC
+
+
+
+
+ EAP-FAST warn not default server
+
+
+
+
+ The subject key id value of the user certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the user certificate. Ignored by the implementation currently!
+
+
+ The serial number of the user certificate. Ignored by the implementation currently!
+
+
+ The subject key id value of the CA certificate.
+ Currently this field is the only one that can be used to identify the certificate.
+
+
+ The issuer of the CA certificate. Ignored by the implementation currently!
+
+
+ The serial number of the CA certificate. Ignored by the implementation currently!
+
+
+ The username used with MSCHAPv2.
+
+
+ The password used with MSCHAPv2.
+
+
+ Specifies how long single session is kept in memory (so no new password queries or similar appear).
+
+
+ Defines which EAP tunneling method is used with MSCHAPv2. Needs to be EAP-TTLS.
+
+
+
+
+
+ Circuit-Switched Data connection methods
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Username for the connection.
+
+
+ Prompt password on connection set-up time.
+
+
+
+
+ Password.
+
+
+ Password authentication type.
+
+
+
+
+ WAP gateway IP.
+
+
+ Starting page.
+
+
+ WTLS security.
+
+
+
+
+ Connection type.
+
+
+
+
+ IP address of the interface.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ Default telephone number.
+
+
+ Bearer speed
+
+
+
+
+
+
+
+
+
+
+ Bearer Call Type Isdn
+
+
+
+
+
+ Is callback enabled.
+
+
+
+
+ Callback type.
+
+
+
+
+ Callback number.
+
+
+ Enable compression
+
+
+
+
+ Use login script
+
+
+
+
+ Login script
+
+
+ Modem init string
+
+
+
+
+ High-speed Circuit-Switched Data connection methods
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ User name
+
+
+ Prompt password at connection time.
+
+
+
+
+ Password.
+
+
+ Password authentication method.
+
+
+
+
+ WAP gateway IP address.
+
+
+ Start page of the connection method.
+
+
+ Attempts a secure WTLS connection to the gateway.
+
+
+
+
+ Indicates whether a connection-oriented or connectionless API should be used.
+
+
+
+
+ IP address of the interface.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ Default telephone number.
+
+
+ Bearer speed
+
+
+
+
+
+
+
+
+
+
+ Bearer Call Type Isdn
+
+
+
+
+
+ Is callback enabled.
+
+
+
+
+ Callback type.
+
+
+
+
+ Callback number.
+
+
+ Enable compression
+
+
+
+
+ Use login script
+
+
+
+
+ Login script
+
+
+ Modem init string
+
+
+
+
+ LAN connection methods
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ WAP gateway IP address.
+
+
+ Start page of the connection method.
+
+
+ Attempts a secure WTLS connection to the gateway.
+
+
+
+
+ Indicates whether a connection-oriented or connectionless API should be used.
+
+
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ LAN interface networks.
+
+
+ LAN interface netmask.
+
+
+ LAN IP Gateway.
+
+
+ IP address of the interface.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the primary DNS server that resolves host names.
+ Typically allocated automatically so this can be left empty.
+
+
+ Address of the secondary DNS server to connect if the primary DNS server is not available.
+ Typically allocated automatically so this can be left empty.
+
+
+
+
+ Virtual Private Network connection methods
+
+
+ The CM name that is visible to the user.
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Defines whether connection method is protected (= cannot be edited by the user).
+
+
+
+
+ Defines whether connection method is hidden.
+
+
+
+
+ Connection method is hidden in CConnDlg or not (used to divide MMS and non-MMS CMs).
+
+
+
+
+ Connection method is highlighted or not.
+
+
+
+
+ Defines whether an IAP can be roamed to.
+
+
+
+
+ Address of the HTTP/HTTPS proxy server.
+
+
+ Port number of the HTTP/HTTPS proxy server.
+
+
+ Name of the protocol for which this proxy can be used.
+ Typically http or https.
+
+
+ The network connection provider IAP name.
+
+
+ Service policy.
+
+
+
+
+ Destination network (SNAP) definitions.
+
+
+ The name that is visible to the user
+
+
+ The CommsDat record id can be manually specified here. If left empty it is allocated automatically.
+ Note: It needs to be verified carefully that the IDs are globally unique if allocated manually!
+ So a good idea is to either specify all the IDs manually or none at all.
+
+
+ Metadata that specifies a few default destination networks that applications can use
+
+
+
+
+
+
+
+ DN protection level. Destination contents mean the connection methods inside the destination and their priorities.
+
+
+
+
+
+ Is DN hidden or not.
+
+
+
+
+ Is DN hidden in CConnDlg or not
+
+
+
+
+ Is DN highlighted or not.
+
+
+
+
+ Icon to be assigned to DN.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of an embedded DN that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+ Name of the Connection Method that is bound to DN.
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+ Normal
+ On
+ Continuous
+ Autodetect
+ Analogue
+ Yes
+ Server Number
+ No
+ No
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User Defined
+ 0
+ No
+ No
+ No
+ 11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Internet
+ 1
+ Internet
+ 2
+ No
+ No
+ Yes
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MMS
+ 2
+ MMS
+ 2
+ No
+ Yes
+ No
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Operator
+ 3
+ Operator
+ 2
+ No
+ No
+ No
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ whenavailable
+ 11
+ Ask once
+
+
+ 1
+ 0
+ 100
+ 1
+ 1
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 253
+ 254
+ 9
+ 0
+ 8
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 4
+ 7
+ 2347
+ 300
+ 1
+ 300
+ -1
+ 1
+ -1
+ -1
+ 1
+ -1
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+ IPv4
+ No
+ Normal
+ On
+ Continuous
+ Yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+ IPv4
+ No
+ Normal
+ On
+ Continuous
+ Yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+ No
+ Normal
+ On
+ Continuous
+ Autodetect
+ Analogue
+ Yes
+ Server Number
+ No
+ No
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ Confirm first
+ On
+ Continuous
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+ Infrastructure
+ Open
+ No
+ key1
+ Shared
+ 64
+ ASCII
+ 64
+ ASCII
+ 64
+ ASCII
+ 64
+ ASCII
+ No
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+
+
+
+
+
+
+
+
+
+ No
+ No
+ No
+ No
+ ConfirmFirst
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+ false
+ false
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/comparison_operators.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/comparison_operators.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+ 2
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/eval.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+ 0
+
+
+
+ 10
+ false
+ false
+ false
+ false
+
+
+
+
+ Default
+ 0
+
+
+ Stripped 1
+ 1
+
+
+ Stripped 2
+ 2
+
+
+
+ Default
+ 0
+ 0.5
+ false
+
+
+ Full 1
+ 10
+ 1.5
+ true
+
+
+ Full 2
+ 20
+ 2.5
+ false
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/filename_testdata.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/filename_testdata.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ some/folder1
+ sounds/file1.txt
+ Z:\\data\\sound.mp3
+
+ x
+ x
+ x
+ x
+ x
+ x
+ x
+ x
+ x
+ x
+ x
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/testdata.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/confml/testdata.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+ image_conf_imakerapi.mk
+
+
+ 0
+ V .50.2009.04.0113 RND
+ myProduct
+ myProduct
+
+
+
+ 5
+ 25
+ 7
+ 5
+ 10
+ 2
+ 5
+ 10
+ 8
+
+
+ String 1
+ String 2
+ x
+ x
+ x
+ x
+ x
+ x
+
+
+ <ударениÑ>
+ <ελληνικά>カタカナελληνικά>
+ ударениÑ>
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/arithmetic.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/arithmetic.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,37 @@
+
+
+
+ True configures Arithmetic.AdditionResult1 = 2 + 6
+ True configures Arithmetic.AdditionResult2 = Arithmetic.Value1 + 6
+ True configures Arithmetic.AdditionResult3 = 2 + Arithmetic.Value2
+ True configures Arithmetic.AdditionResult4 = Arithmetic.Value1 + Arithmetic.Value2
+
+ True configures Arithmetic.SubtractionResult1 = 2 - 6
+ True configures Arithmetic.SubtractionResult2 = Arithmetic.Value1 - 6
+ True configures Arithmetic.SubtractionResult3 = 2 - Arithmetic.Value2
+ True configures Arithmetic.SubtractionResult4 = Arithmetic.Value1 - Arithmetic.Value2
+
+ True configures Arithmetic.MultiplicationResult1 = 2 * 6
+ True configures Arithmetic.MultiplicationResult2 = Arithmetic.Value1 * 6
+ True configures Arithmetic.MultiplicationResult3 = 2 * Arithmetic.Value2
+ True configures Arithmetic.MultiplicationResult4 = Arithmetic.Value1 * Arithmetic.Value2
+
+ True configures Arithmetic.DivisionResult1 = 6 / 2
+ True configures Arithmetic.DivisionResult2 = Arithmetic.Value2 / 4
+ True configures Arithmetic.DivisionResult3 = 10 / Arithmetic.Value1
+ True configures Arithmetic.DivisionResult4 = Arithmetic.Value2 / Arithmetic.Value1
+
+ True configures Arithmetic.MixedResult1 = (6 / 2 + 3 * 9) - 7
+ True configures Arithmetic.MixedResult2 = (6 / 2 + Arithmetic.Value1 * 9) - 7
+ True configures Arithmetic.MixedResult3 = (Arithmetic.Value2 / 2 + Arithmetic.Value1 * 9) - 7
+ True configures Arithmetic.MixedResult4 = (Arithmetic.Value2 / Arithmetic.Value1 + Arithmetic.Value1 * Arithmetic.Value1) - Arithmetic.Value2
+ True configures Arithmetic.MixedResult5 = 4 + 6 / 2 - 3 * 9 + 10 / 5 - 8
+
+ True configures Arithmetic.RealResult1 = 5.0 / 2.0
+ True configures Arithmetic.RealResult2 = Arithmetic.RealValue1 / 2
+ True configures Arithmetic.RealResult3 = 0.25 * Arithmetic.RealValue2
+ True configures Arithmetic.RealResult4 = Arithmetic.RealValue1 / 2.0 * Arithmetic.RealValue2
+
+ True configures Arithmetic.RealCalcIntoIntResult = 0.25 * Arithmetic.RealValue1
+ True configures Arithmetic.IntCalcIntoRealResult = 3 * Arithmetic.Value1
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/commsdat.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/commsdat.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ (APs.AP != []) or (VPN_APs.VPN_AP != []) configures KCRUidCommsDatCreator.KCommsDatCreatorInputFileName = 'test.xml'
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/comparison_operators.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/comparison_operators.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+
+
+ 0 == 0 configures CompOperTest.LiteralsResult1 = true
+ 0 != 1 configures CompOperTest.LiteralsResult2 = true
+ 1 < 2 configures CompOperTest.LiteralsResult3 = true
+ 2 > 1 configures CompOperTest.LiteralsResult4 = true
+ 1 <= 1 configures CompOperTest.LiteralsResult5 = true
+ 1 <= 2 configures CompOperTest.LiteralsResult6 = true
+ 1 >= 1 configures CompOperTest.LiteralsResult7 = true
+ 2 >= 1 configures CompOperTest.LiteralsResult8 = true
+
+ CompOperTest.Zero == CompOperTest.Zero configures CompOperTest.RefsResult1 = true
+ CompOperTest.Zero != CompOperTest.One configures CompOperTest.RefsResult2 = true
+ CompOperTest.One < CompOperTest.Two configures CompOperTest.RefsResult3 = true
+ CompOperTest.Two > CompOperTest.One configures CompOperTest.RefsResult4 = true
+ CompOperTest.One <= CompOperTest.One configures CompOperTest.RefsResult5 = true
+ CompOperTest.One <= CompOperTest.Two configures CompOperTest.RefsResult6 = true
+ CompOperTest.One >= CompOperTest.One configures CompOperTest.RefsResult7 = true
+ CompOperTest.Two >= CompOperTest.One configures CompOperTest.RefsResult8 = true
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/container_with_rules.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/container_with_rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+
+
+
+
+
+ imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
+ True configures StringConcatenationTest.Result1 = "Test " + "test"
+ True configures StringConcatenationTest.Result2 = StringConcatenationTest.Value1 + " Literal 2"
+
+
+
+
+
+ True configures StringConcatenationTest.Result3 = "Literal 1 " + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result4 = StringConcatenationTest.Value1 + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result5 = StringConcatenationTest.Value1 + " & " + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result6 = StringConcatenationTest.Value1 + u" € カタカナ"
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/eval.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,42 @@
+
+
+ True configures EvalTest.StringLenResult = {% len("faklskjh") %}
+ True configures EvalTest.EvalConstantResult = {% SOME_VALUE %}
+ True configures EvalTest.EvalFileImport = {% do_something(SOME_VALUE) %}
+
+ {% ${EvalTest.Bitmask} & 0x1 %} configures EvalTest.Bit0Result = True
+ {% ${EvalTest.Bitmask} & 0x2 %} configures EvalTest.Bit1Result = True
+ True configures EvalTest.Bit2Result = {%
+ bool(${EvalTest.Bitmask} & 0x4)
+ %}
+
+
+ True configures EvalTest.Bit3Result = {% bool(${EvalTest.Bitmask} & 0x8) %}
+
+
+ True configures EvalTest.FullSequence = {% append_stripped_seq_to_full_seq(
+ @{EvalTest.StrippedSequence},
+ @{EvalTest.FullSequence})
+ %}
+
+
+
+ False configures {% @{EvalTest.UnchangedValue}.set_value(54321) %}
+
+ True configures EvalTest.UnicodeResult1 = {% u'100€' %}
+ True configures EvalTest.UnicodeResult2 = {% @{ударениÑ.ελληνικά}.get_value() %}
+
+ True configures EvalTest.EvalBuiltinResult = {% ruleml.configuration.get_name() %}
+
+ SOME_VALUE = 12345
+
+
+def append_stripped_seq_to_full_seq(stripped_seq, full_seq):
+ stripped_values = stripped_seq.get_value()
+ full_values = full_seq.get_value()
+ for sv in stripped_values:
+ full_values.append([sv[0], sv[1], '0.1', 'false'])
+ return full_values
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/filename_rules.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/filename_rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,14 @@
+
+
+ True configures FilenamejoinTest.Result1 = FilenamejoinTest.String1 filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result2 = "some/content/dir/somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result3 = "some/content/dir/" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result4 = "some\\content\\dir\\somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result5 = "some\\content\\dir\\" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result6 = "Z:\\\\some\\\\content\\\\dir\\\\somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result7 = "Z:\\\\some\\\\content\\\\dir\\\\" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result8 = "somedir" filenamejoin FilenamejoinTest.File1.localPath
+ True configures FilenamejoinTest.Result9 = "somedir" filenamejoin "somefile.txt"
+ True configures FilenamejoinTest.Result10 = "somedir" filenamejoin "somefile.txt" + ';' + r'Z:\\some\\dir\\' filenamejoin FilenamejoinTest.File1.localPath
+ True and FilenamejoinTest.String1==r'Z:\\data\\sound.mp3' and True configures FilenamejoinTest.Result11 = "some" + "dir" filenamejoin "somefile.txt"
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/rules.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,24 @@
+
+
+ {% ${imaker.imagetarget} %} configures imakerapi.outputLocation = imaker.imagetarget
+ mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True
+ mms.imagesize == 'small' configures pd.ref1 = False and pd.ref2 = True
+ mms.imagesize == 'extrasmall' configures pd.ref1 = False and pd.ref2 = False
+ mms.imagesize == 'extralarge' configures pd.ref1 = True and pd.ref2 = False
+ imakerapi.outputLocationY == None configures imakerapi.outputLocationY = 'hello'
+ operations.minus == 5 configures operations.minus = operations.minus1 - operations.minus2
+ operations.minus1 == 25 configures operations.minus1 = operations.minus3 * operations.minus2
+ operations.minus4 == 10 configures operations.minus4 = operations.minus4 / operations.minus5
+ operations.minus6 == 5 configures operations.minus6 = operations.minus7 + operations.minus8
+
+ True configures StringConcatenationTest.Result1 = "Test " + "test"
+ True configures StringConcatenationTest.Result2 = StringConcatenationTest.Value1 + " Literal 2"
+ True configures StringConcatenationTest.Result3 = "Literal 1 " + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result4 = StringConcatenationTest.Value1 + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result5 = StringConcatenationTest.Value1 + " & " + StringConcatenationTest.Value2
+ True configures StringConcatenationTest.Result6 = StringConcatenationTest.Value1 + u" € カタカナ"
+
+ True configures ударениÑ.ελληνικά = ударениÑ.ελληνικά + u" € カタカナ"
+
+ {% @{Foo.Bar}.value %} configures ${Foo.Baz} = 'gaa'
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/scripts/test_eval.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/implml/scripts/test_eval.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,18 @@
+#
+# 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:
+#
+
+def do_something(param):
+ return param + 1
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/ruleproject/rules/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/runtests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+#
+# 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:
+#
+
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_eval.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_eval.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,106 @@
+# *-* coding: utf-8 *-*
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import re
+
+from legacyruleplugin import ruleml, relations
+from cone.public import api, exceptions
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class MockObject(object):
+ pass
+
+class MockFeature(object):
+ def __init__(self, ref, feature_values):
+ self.ref = ref
+ self.feature_values = feature_values
+
+ def get_value(self):
+ return self.feature_values[self.ref]
+
+ def set_value(self, value):
+ self.feature_values[self.ref] = value
+
+class MockConfigurationContext(object):
+ def __init__(self, feature_values):
+ self.configuration = MockObject()
+ default_view = MockObject()
+ default_view.get_feature = lambda ref: MockFeature(ref, feature_values)
+ self.configuration.get_default_view = lambda: default_view
+ self.ref_eval_callback = None
+
+class MockExpression(object):
+ def __init__(self, expression):
+ self.expression = repr(expression)
+
+class TestEvalExpression(unittest.TestCase):
+ def test_extract_refs(self):
+ ee = relations.EvalExpression(
+ None, MockExpression("'%05d 0x%08X %d' % (${Feature1.Setting1}.get_value(), ${Feature1.Setting2}.get_value(), ${Feature2.Setting1}.get_value())"))
+ self.assertEquals(sorted(ee.extract_refs()), sorted(["Feature1.Setting1", "Feature1.Setting2", "Feature2.Setting1"]))
+
+ ee = relations.EvalExpression(None, MockExpression("'%05d 0x%08X %d' % (1, 2, 3)"))
+ self.assertEquals(ee.extract_refs(), [])
+
+ ee = relations.EvalExpression(None, MockExpression(u"${ударениÑ.ελληνικά}"))
+ self.assertEquals(ee.extract_refs(), [u'ударениÑ.ελληνικά'])
+
+ def test_execute(self):
+ feature_values = {
+ "Feature1.Setting1": 16,
+ "Feature1.Setting2": 32,
+ "Feature2.Setting1": 64,
+ u'ударениÑ.ελληνικά': 100,
+ }
+ context = MockConfigurationContext(feature_values)
+
+ ee = relations.EvalExpression(None,
+ MockExpression("'%05d 0x%08X %d' % (@{Feature1.Setting1}.get_value(), @{Feature1.Setting2}.get_value(), @{Feature2.Setting1}.get_value())"))
+ self.assertEquals(ee.eval(context), "00016 0x00000020 64")
+
+ ee = relations.EvalExpression(None, MockExpression("'%05d 0x%08X %d' % (1, 2, 3)"))
+ self.assertEquals(ee.eval(context), "00001 0x00000002 3")
+
+ ee = relations.EvalExpression(None, MockExpression(u"'%d' % @{ударениÑ.ελληνικά}.get_value()"))
+ self.assertEquals(ee.eval(context), "100")
+
+class TestReplaceEvalBlocks(unittest.TestCase):
+ def test_replace_eval_blocks(self):
+ replace = ruleml.RuleImplReader2._replace_eval_blocks
+
+ orig = """some.setting configures x = y"""
+ self.assertEquals(replace(orig), orig)
+
+ orig = """some.setting configures x = {% do_something(@{Fea.Set}) %}"""
+ self.assertEquals(replace(orig), """some.setting configures x = __eval__ 'do_something(@{Fea.Set})'""")
+
+ orig = """{% 'test' %}"""
+ self.assertEquals(replace(orig), '''__eval__ "'test'"''')
+ orig = """{%'test'%}"""
+ self.assertEquals(replace(orig), '''__eval__ "'test'"''')
+
+ orig = """{% len(@{Fea.Set}.get_value()) %} == 3 configures x = {% do_something('test') %}"""
+ self.assertEquals(replace(orig), '''__eval__ 'len(@{Fea.Set}.get_value())' == 3 configures x = __eval__ "do_something('test')"''')
+
+ orig = u"True configures X.Y = {% len(@{ударениÑ.ελληνικά}.get_value()) %}"
+ self.assertEquals(replace(orig), u"True configures X.Y = __eval__ %r" % u"len(@{ударениÑ.ελληνικά}.get_value())")
+
+if __name__ == "__main__":
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_parseruleml.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_parseruleml.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,95 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+try:
+ from cElementTree import ElementTree
+except ImportError:
+ try:
+ from elementtree import ElementTree
+ except ImportError:
+ try:
+ from xml.etree import cElementTree as ElementTree
+ except ImportError:
+ from xml.etree import ElementTree
+
+from legacyruleplugin import ruleml, relations
+from cone.public import api, exceptions, utils, plugin
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+ruleml_string = \
+'''
+
+ imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
+ imaker.imagename configures imakerapi.outputLocation = imaker.imagename
+
+'''
+
+class TestParseRuleimpl(unittest.TestCase):
+ def setUp(self): relations.register()
+ def tearDown(self): relations.unregister()
+
+ def test_parse_rules(self):
+ etree = ElementTree.fromstring(ruleml_string)
+ reader = ruleml.RuleImplReader2(None, None)
+ rules = reader.parse_rules("",etree)
+ self.assertTrue(isinstance(rules[0],relations.ConfigureRelation))
+ self.assertTrue(isinstance(rules[1],relations.ConfigureRelation))
+ self.assertTrue(rules[0].has_ref('imaker.imagetarget'))
+ self.assertFalse(rules[0].has_ref('imakerapi.imagename'))
+ self.assertTrue(rules[0].has_ref('imakerapi.outputLocation'))
+
+
+class TestRulemlFromFile(unittest.TestCase):
+ def setUp(self): pass
+ def tearDown(self): relations.unregister()
+
+ def test_create_from_file(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ config = project.get_configuration('root.confml')
+ ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/rules.ruleml', config)[0]
+ relation_container = ruleimpl.get_relation_container()
+ self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
+ self.assertEquals(relation_container.get_relation_count(), 18)
+
+ def test_create_from_file_with_common_container(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ config = project.get_configuration('root.confml')
+ ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/container_with_rules.ruleml', config)[0]
+ relation_container = ruleimpl.get_relation_container()
+ self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
+ self.assertEquals(relation_container.get_relation_count(), 7)
+
+ def test_create_from_file_filename(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ config = project.get_configuration('root.confml')
+ ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/filename_rules.ruleml', config)[0]
+ relation_container = ruleimpl.get_relation_container()
+ self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
+ self.assertEquals(relation_container.get_relation_count(), 11)
+
+ def test_parse_eval(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ config = project.get_configuration('root.confml')
+ ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/eval.ruleml', config)[0]
+ relation_container = ruleimpl.get_relation_container()
+ self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
+ self.assertEquals(relation_container.get_relation_count(), 12)
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_empty_plugin.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_empty_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,71 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import logging
+
+from cone.public import exceptions,plugin,api,container
+from cone.storage import filestorage
+from legacyruleplugin import ruleml
+
+# Hardcoded value of testdata folder that must be under the current working dir
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+testdata = os.path.join(ROOT_PATH,'rule')
+
+class TestRuleEmptyPlugin(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+
+ def test_rule_with_empty_value1(self):
+ return
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
+ config = project.get_configuration('root.confml')
+ implcontainer = plugin.get_impl_set(config)
+ implcontainer.generate()
+ lastconfig = config.get_last_configuration()
+ self.assertEquals(lastconfig.get_path(),ruleml.RuleImpl.AUTOCONFIGURATION_CONFML)
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_ref(),'outputLocation')
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_value(),'2')
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocationY').get_value(),'hello')
+ self.assertEquals(lastconfig.get_data('operations.minus').get_value(),'18')
+ self.assertEquals(lastconfig.get_data('operations.minus1').get_value(),'35')
+ self.assertEquals(lastconfig.get_data('operations.minus4').get_value(),'5')
+ project.close()
+
+
+ def test_rule_with_empty_value2(self):
+ return
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'rule/config_project/platforms/customsw'), "a" ))
+ config = project.get_configuration('root.confml')
+ implcontainer = plugin.get_impl_set(config)
+ implcontainer.generate()
+ lastconfig = config.get_last_configuration()
+ self.assertEquals(lastconfig.get_data('operations.minus').get_value(),'18')
+ self.assertEquals(lastconfig.get_data('operations.minus1').get_value(),'35')
+ self.assertEquals(lastconfig.get_data('operations.minus4').get_value(),'5')
+ self.assertEquals(lastconfig.get_data('operations.minus6').get_value(),'19')
+ self.assertEquals(lastconfig.get_data('operations.string1').get_value(),'HelloWorld')
+ project.close()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_plugin.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,93 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import logging
+
+from cone.public import exceptions,plugin,api,container
+from cone.storage import filestorage
+from legacyruleplugin import ruleml
+
+# Hardcoded value of testdata folder that must be under the current working dir
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+testdata = os.path.join(ROOT_PATH,'ruleproject')
+
+class TestRulePlugin(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+class TestRulePluginOnFileStorage(unittest.TestCase):
+ def test_get_impl_container(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ config = project.get_configuration('root.confml')
+ implcontainer = plugin.get_impl_set(config, 'ruleml$')
+ impl = implcontainer.get_implementations_by_file('implml/rules.ruleml')[0]
+
+ EXPECTED_REFS = sorted([
+ 'imaker.imagetarget',
+ 'mms.imagesize',
+ 'imakerapi.outputLocationY',
+ 'operations.minus',
+ 'operations.minus1',
+ 'operations.minus4',
+ 'operations.minus6',
+ 'Foo.Bar'])
+ self.assertEquals(EXPECTED_REFS, sorted(impl.get_child_refs()))
+ self.assertEquals([], impl.list_output_files())
+
+ def test_impl_container_execute_pre_rules(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
+ config = project.get_configuration('root.confml')
+
+ implcontainer = plugin.get_impl_set(config, 'ruleml$')
+ ruleimpl = implcontainer.get_implementations_by_file('implml/container_with_rules.ruleml')[0]
+ context = plugin.GenerationContext(configuration=config)
+ context.phase = "pre"
+ ruleimpl.generate(context)
+
+ lastconfig = config.get_last_configuration()
+ self.assertEquals(lastconfig.get_path(), plugin.AUTOCONFIG_CONFML)
+ self.assertEquals(lastconfig.list_all_datas(),['imakerapi',
+ 'imakerapi.outputLocation',
+ 'StringConcatenationTest',
+ 'StringConcatenationTest.Result1',
+ 'StringConcatenationTest.Result2'])
+
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_ref(),'outputLocation')
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_value(),'2')
+ project.close()
+
+ def test_impl_container_execute_rules(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
+ config = project.get_configuration('root.confml')
+ context = plugin.GenerationContext(configuration=config)
+ implcontainer = plugin.get_impl_set(config, 'ruleml$')
+ implcontainer.generate(context)
+
+ lastconfig = config.get_last_configuration()
+ self.assertEquals(lastconfig.get_path(), plugin.AUTOCONFIG_CONFML)
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_ref(),'outputLocation')
+ self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_value(),'2')
+ project.close()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_plugin_errors.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rule_plugin_errors.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,109 @@
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+import logging
+
+from cone.public import exceptions,plugin,api,container
+from cone.storage import filestorage
+from legacyruleplugin import ruleml
+from testautomation.base_testcase import BaseTestCase
+
+# Hardcoded value of testdata folder that must be under the current working dir
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+testdata = os.path.join(ROOT_PATH,'errorruleproject')
+
+class TestErrorReporting(BaseTestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def _prepare_workdir(self, workdir):
+ workdir = os.path.join(ROOT_PATH, workdir)
+ self.recreate_dir(workdir)
+ return workdir
+
+ def _prepare_log(self, log_file, level=logging.DEBUG, formatter="%(levelname)s - %(name)s - %(message)s", logger='cone'):
+ FULL_PATH = os.path.join(ROOT_PATH, "temp", log_file)
+ self.remove_if_exists(FULL_PATH)
+ self.create_dir_for_file_path(FULL_PATH)
+
+ handler = logging.FileHandler(FULL_PATH)
+ handler.setLevel(level)
+ frm = logging.Formatter(formatter)
+ handler.setFormatter(frm)
+ logger = logging.getLogger(logger)
+ logger.addHandler(handler)
+
+ return [FULL_PATH, handler, logger]
+
+ def _execute_rules(self, project_location):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH, project_location)))
+ config = project.get_configuration('root.confml')
+ context = plugin.GenerationContext(configuration=config)
+ implcontainer = plugin.get_impl_set(config, r'\.ruleml$')
+ implcontainer.get_relation_container().execute(context)
+ lastconfig = config.get_last_configuration()
+ project.close()
+
+ def test_terminal_expression_repr(self):
+ log_file, handler, logger = self._prepare_log('test1.log')
+ self._execute_rules('errorruleproject/test1')
+ logger.removeHandler(handler)
+
+ self.assert_file_does_not_contain(log_file, " this is invalid python code")
+ self.assert_file_contains(log_file, "ERROR - cone.ruleml_relation_container(implml/invalid_python_eval.ruleml:3) - '-> this is invalid python code'")
+
+ def test_invalid_python_code_eval_globals(self):
+ log_file, handler, logger = self._prepare_log('test3.log')
+ self._execute_rules('errorruleproject/test3')
+ logger.removeHandler(handler)
+ self.assert_file_contains(log_file, "WARNING - cone.ruleml(implml/invalid_python_eval.ruleml) - Cannot import eval file: implml/scripts/test_eval.py. Exception: invalid syntax (, line 17)")
+
+ def test_invalid_file_reference_in_eval_globals_file_attribute(self):
+ log_file, handler, logger = self._prepare_log('test4.log')
+ self._execute_rules('errorruleproject/test4')
+ logger.removeHandler(handler)
+ self.assert_file_contains(log_file, "WARNING - cone.ruleml(implml/invalid_python_eval.ruleml) - Cannot import eval file: implml/scripts/not_valid_filename.py. Exception: implml/scripts/not_valid_filename.py, [Errno 2] No such file or directory:")
+ self.assert_file_contains(log_file, '/implml/scripts/not_valid_filename.py')
+
+ def test_runtime_error_when_running_an_eval_block_inside_rule(self):
+ log_file, handler, logger = self._prepare_log('test5.log')
+ self._execute_rules('errorruleproject/test5')
+ logger.removeHandler(handler)
+
+ self.assert_file_contains(log_file, "Execution failed for eval: 7/0 : integer division or modulo by zero")
+
+ def test_references_non_existent_settings(self):
+ log_file, handler, logger = self._prepare_log('test6.log')
+ self._execute_rules('errorruleproject/test6')
+ logger.removeHandler(handler)
+ #self.assert_file_contains(log_file, "Execution failed for eval: 7/0 : integer division or modulo by zero")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rules.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/tests/unittest_rules.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,178 @@
+# *-* coding: utf-8 *-*
+#
+# 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:
+#
+
+import unittest
+import os, shutil
+import sys
+# import legacyruleplugin_testinit
+
+from legacyruleplugin import ruleml
+from cone.public import api, plugin
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+class TestRuleExecutes(unittest.TestCase):
+
+ def setUp(self):
+ self.project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
+ self.config = self.project.get_configuration('root.confml')
+
+ def tearDown(self):
+ self.project.close()
+
+ def _execute_rules(self, impl_filter):
+ implcontainer = plugin.get_impl_set(self.config, impl_filter)
+ context = plugin.GenerationContext(configuration=self.config)
+ implcontainer.generate(context)
+ return context.generation_output
+
+ def test_arithmetic_operations(self):
+ self._execute_rules(r'^implml/arithmetic\.ruleml$')
+
+ # Values used in the ConfML (the calculations are duplicated here to make
+ # the tests more readable)
+ value1 = 5
+ value2 = 20
+ config = self.config
+ self.assert_setting_equals(config, 'Arithmetic.AdditionResult1', 2 + 6)
+ self.assert_setting_equals(config, 'Arithmetic.AdditionResult2', value1 + 6)
+ self.assert_setting_equals(config, 'Arithmetic.AdditionResult3', 2 + value2)
+ self.assert_setting_equals(config, 'Arithmetic.AdditionResult4', value1 + value2)
+
+ self.assert_setting_equals(config, 'Arithmetic.SubtractionResult1', 2 - 6)
+ self.assert_setting_equals(config, 'Arithmetic.SubtractionResult2', value1 - 6)
+ self.assert_setting_equals(config, 'Arithmetic.SubtractionResult3', 2 - value2)
+ self.assert_setting_equals(config, 'Arithmetic.SubtractionResult4', value1 - value2)
+
+ self.assert_setting_equals(config, 'Arithmetic.MultiplicationResult1', 2 * 6)
+ self.assert_setting_equals(config, 'Arithmetic.MultiplicationResult2', value1 * 6)
+ self.assert_setting_equals(config, 'Arithmetic.MultiplicationResult3', 2 * value2)
+ self.assert_setting_equals(config, 'Arithmetic.MultiplicationResult4', value1 * value2)
+
+ self.assert_setting_equals(config, 'Arithmetic.DivisionResult1', 6 / 2)
+ self.assert_setting_equals(config, 'Arithmetic.DivisionResult2', value2 / 4)
+ self.assert_setting_equals(config, 'Arithmetic.DivisionResult3', 10 / value1)
+ self.assert_setting_equals(config, 'Arithmetic.DivisionResult4', value2 / value1)
+
+ self.assert_setting_equals(config, 'Arithmetic.MixedResult1', (6 / 2 + 3 * 9) - 7)
+ self.assert_setting_equals(config, 'Arithmetic.MixedResult2', (6 / 2 + value1 * 9) - 7)
+ self.assert_setting_equals(config, 'Arithmetic.MixedResult3', (value2 / 2 + value1 * 9) - 7)
+ self.assert_setting_equals(config, 'Arithmetic.MixedResult4', (value2 / value1 + value1 * value1) - value2)
+ self.assert_setting_equals(config, 'Arithmetic.MixedResult5', 4 + 6 / 2 - 3 * 9 + 10 / 5 - 8)
+
+ rvalue1 = float(value1)
+ rvalue2 = float(value2)
+ self.assert_setting_equals(config, 'Arithmetic.RealResult1', 5.0 / 2.0)
+ self.assert_setting_equals(config, 'Arithmetic.RealResult2', rvalue1 / 2.0)
+ self.assert_setting_equals(config, 'Arithmetic.RealResult3', 0.25 * rvalue2)
+ self.assert_setting_equals(config, 'Arithmetic.RealResult4', rvalue1 / 2.0 * rvalue2)
+#
+ self.assert_setting_equals(config, 'Arithmetic.RealCalcIntoIntResult', int(0.25 * rvalue1))
+ self.assert_setting_equals(config, 'Arithmetic.IntCalcIntoRealResult', float(3 * value1))
+
+ def test_string_concatenation(self):
+ self._execute_rules(r'^implml/rules\.ruleml$')
+
+ config = self.config
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result1', 'Test test')
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result2', 'String 1 Literal 2')
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result3', 'Literal 1 String 2')
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result4', 'String 1String 2')
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result5', 'String 1 & String 2')
+ self.assert_setting_equals(config, 'StringConcatenationTest.Result6', u'String 1 € カタカナ')
+
+ self.assert_setting_equals(config, u'ударениÑ.ελληνικά', u'カタカナ € カタカナ')
+
+
+ def test_filenamejoin(self):
+ self._execute_rules(r'^implml/filename_rules\.ruleml$')
+
+ config = self.config
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result1', r'Z:\\data\\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result2', r'some/content/dir/file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result3', r'some/content/dir/file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result4', r'some\content\dir\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result5', r'some\content\dir\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result6', r'Z:\\some\\content\\dir\\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result7', r'Z:\\some\\content\\dir\\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result8', r'somedir/file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result9', r'somedir/somefile.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result10', r'somedir/somefile.txt;Z:\\some\\dir\\file1.txt')
+ self.assert_setting_equals(config, 'FilenamejoinTest.Result11', r'somedir/somefile.txt')
+
+ def test_comparison_operators(self):
+ self._execute_rules(r'^implml/comparison_operators\.ruleml$')
+
+ for i in xrange(1, 8):
+ ref = 'CompOperTest.LiteralsResult%d' % i
+ self.assert_setting_equals(self.config, ref, True, "Setting %s is not True" % ref)
+
+ for i in xrange(1, 8):
+ ref = 'CompOperTest.RefsResult%d' % i
+ self.assert_setting_equals(self.config, ref, True, "Setting %s is not True" % ref)
+
+ def test_eval(self):
+ config = self.config
+
+ self.assert_setting_equals(config, 'EvalTest.FullSequence',
+ [['Full 1', 10, 1.5, True],
+ ['Full 2', 20, 2.5, False]])
+
+ self._execute_rules(r'^implml/eval\.ruleml$')
+
+ self.assert_setting_equals(config, 'EvalTest.StringLenResult', 8)
+ self.assert_setting_equals(config, 'EvalTest.EvalConstantResult', 12345)
+ self.assert_setting_equals(config, 'EvalTest.EvalFileImport', 12346)
+ self.assert_setting_equals(config, 'EvalTest.UnchangedValue', 0)
+ self.assert_setting_equals(config, 'EvalTest.UnicodeResult1', u'100€')
+ self.assert_setting_equals(config, 'EvalTest.UnicodeResult2', u'カタカナ')
+ self.assert_setting_equals(config, 'EvalTest.Bit0Result', False)
+ self.assert_setting_equals(config, 'EvalTest.Bit1Result', True)
+ self.assert_setting_equals(config, 'EvalTest.Bit2Result', False)
+ self.assert_setting_equals(config, 'EvalTest.Bit3Result', True)
+ self.assert_setting_equals(config, 'EvalTest.FullSequence',
+ [['Full 1', 10, 1.5, True],
+ ['Full 2', 20, 2.5, False],
+ ['Stripped 1', 1, 0.1, False],
+ ['Stripped 2', 2, 0.1, False]])
+ self.assert_setting_equals(config, 'EvalTest.EvalBuiltinResult', 'ruleml_test_config')
+
+ def assert_setting_equals(self, config, setting, expected_value, msg=None):
+ if msg == None:
+ self.assertEquals(config.get_default_view().get_feature(setting).get_value(), expected_value)
+ else:
+ self.assertEquals(config.get_default_view().get_feature(setting).get_value(), expected_value, msg)
+
+ def test_rule_execution_results(self):
+ results = self._execute_rules(r'^implml/rules\.ruleml$')
+
+ outputs = [(output.name, output.implementation.get_refs()) for output in results if output.type == 'ref']
+ self.assertEquals(outputs, [(u'imakerapi.outputLocation', [u'imaker.imagetarget']),
+ (u'imakerapi.outputLocationY', [u'imakerapi.outputLocationY']),
+ (u'operations.minus', [u'operations.minus']),
+ (u'operations.minus1', [u'operations.minus1']),
+ (u'operations.minus4', [u'operations.minus4']),
+ (u'operations.minus6', [u'operations.minus6']),
+ (u'StringConcatenationTest.Result1', []),
+ (u'StringConcatenationTest.Result2', []),
+ (u'StringConcatenationTest.Result3', []),
+ (u'StringConcatenationTest.Result4', []),
+ (u'StringConcatenationTest.Result5', []),
+ (u'StringConcatenationTest.Result6', []),
+ (u'\u0443\u0434\u0430\u0440\u0435\u043d\u0438\u044f.\u03b5\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac', [])])
+
+if __name__ == '__main__':
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/xsd/ruleml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/xsd/ruleml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ RuleML v1 implementation for specifying rules to execute.
+
+
+
+
+
+
+
+ The rule element specifies a single rule to execute.
+
+
+ For example:
+ <rule>MyFeature.MySetting1 == 'test' configures MyFeature.MySetting2 = '1'</rule>
+ This would cause the value '1' to be assigned to the setting 'MyFeature.MySetting2'
+ if the value of the setting 'MyFeature.MySetting1' is 'test'.
+
+ ]]>
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/xsd/ruleml2.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/xsd/ruleml2.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ RuleML v2 implementation for specifying rules to execute.
+
+
+
+
+
+
+
+ The rule element specifies a single rule to execute.
+
+
+ For example:
+ <rule>MyFeature.MySetting1 == 'test' configures MyFeature.MySetting2 = '1'</rule>
+ This would cause the value '1' to be assigned to the setting 'MyFeature.MySetting2'
+ if the value of the setting 'MyFeature.MySetting1' is 'test'.
+
+
+
+ Arbitrary Python code can also be executed in the rule by enclosing the eval block
+ with {% %}. For example:
+ <rule>True configures MyFeature.MySetting = {% get_some_value() %}</rule>
+ This would cause the value got from evaluating the Python function call
+ get_some_value() to be assigned to the setting 'MyFeature.MySetting'.
+
+
+
+ Any settings referenced inside an eval block must be enclosed with ${ }
+ to differentiate them from the Python code. For example:
+ <rule>True configures MyFeature.MySetting = {% get_some_value(${MyFeature.MySetting1}) %}</rule>
+ This would cause the value of the setting 'MyFeature.MySetting1' to be passed as a
+ parameter to the function call.
+ The actual feature object handled by ConE can be accessed by enclosing the setting
+ reference with @{ }.
+
+
+
+ Any functions or variables (like get_some_value() in the above examples) need
+ to be defined using eval_globals elements inside the ruleml element.
+
+ ]]>
+
+
+
+
+
+
+ An eval_globals block can be used to add Python variables
+ or functions to the evaluation context of the rules contained
+ within the current ruleml implementation. The Python code can be contained
+ either directly inside the XML element or inside a file pointed by the
+ 'file' attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Path to the file containing the Python code of the eval_globals element.
+ Should be a path relative to the current implementation file.
+ Specifying the 'file' attribute causes the text content of the eval_globals
+ element to be ignored.
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/setup.cfg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/setup.cfg Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+[egg_info]
+tag_svn_revision = 1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeLegacyRulePlugin/setup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeLegacyRulePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,40 @@
+#
+# 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:
+#
+
+import os, os.path
+from setuptools import setup, find_packages
+from legacyruleplugin import __version__
+
+setup(
+ name = "conelegacyruleplugin",
+ version = __version__,
+ packages = find_packages(exclude=["*.tests"]),
+ package_data = {'legacyruleplugin': ['xsd/*.xsd']},
+ test_suite = "legacyruleplugin.tests.collect_suite",
+
+ # metadata for upload to PyPI
+ author = "Teemu Rytkonen",
+ author_email = "teemu.rytkonen@nokia.com",
+ description = "Configuration Engine rule plugin",
+ license = "Eclipse Public License v1.0",
+ keywords = "cone",
+ url = "http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware", # project home page, if any
+ zip_safe = True,
+
+ # entrypoint info
+ entry_points={'cone.plugins.implmlreaders': ['ruleml_1 = legacyruleplugin.ruleml:RuleImplReader1',
+ 'ruleml_2 = legacyruleplugin.ruleml:RuleImplReader2']}
+)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/__init__.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,15 +16,3 @@
__version__ = 0.1
-
-import pkg_resources
-import sys,os
-
-try:
- pkg_resources.require("Cone")
-except pkg_resources.DistributionNotFound:
- ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
- sys.path.append(ROOT_PATH)
- sys.path.append(os.path.join(ROOT_PATH,'..'))
- sys.path.append(os.path.join(ROOT_PATH,'../..'))
- sys.path.append(os.path.join(ROOT_PATH,'../../..'))
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/accesspoint_id_counter.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/accesspoint_id_counter.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/accesspoint_id_counter.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,59 +21,55 @@
logger = logging.getLogger('cone.ruleplugin.evals.accesspoint_id_counter')
-def get_apindex_by_apname(aps, dns, apname):
+def get_apindex_by_apname(wlan_aps, aps, dns, apname):
"""
Returns AccessPoint index by given AccessPoint name
"""
- cnt = _get_ApDnContainer_(aps, dns)
+ cnt = _get_ApDnContainer_(wlan_aps, aps, dns)
return cnt.get_apindex_by_apname(apname)
-def get_apid_by_apname(aps, dns, apname, wlan_support=True):
+def get_apid_by_apname(wlan_aps, aps, dns, apname):
"""
Returns AccessPoint id by given AccessPoint name
"""
- cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ cnt = _get_ApDnContainer_(wlan_aps, aps, dns)
return cnt.get_apid_by_apname(apname)
-def get_dnid_by_dnname(aps, dns, dnname, wlan_support=True):
+def get_dnid_by_dnname(aps, dns, dnname):
"""
Return DestinationNetwork id by given DestinationNetworks name
"""
- cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ cnt = _get_ApDnContainer_(wlan_aps, aps, dns)
return cnt.get_dnid_by_dnname(dnname)
-def get_apid_by_dnname_and_apname(aps, dns, dnname, apname, wlan_support=True):
+def get_apid_by_dnname_and_apname(wlan_aps, aps, dns, dnname, apname):
"""
Returns AccessPoint id by given DestinationNetwork name and AccessPoint name.
"""
- cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ cnt = _get_ApDnContainer_(wlan_aps, aps, dns)
return cnt.get_apid_by_dnname_and_apname(dnname, apname)
-def get_all_in_array(aps, dns, wlan_support=True):
+def get_all_in_array(wlan_aps, aps, dns):
"""
Returns array containing all data:
[DN name],[DN id], [IAPS names], [IAPS ids], [IAPS indexes]
"""
- cnt = _get_ApDnContainer_(aps, dns, wlan_support)
+ cnt = _get_ApDnContainer_(wlan_aps, aps, dns)
return cnt.get_all_in_array()
-def _get_ApDnContainer_(aps, dns, wlan_support=True):
+def _get_ApDnContainer_(wlan_aps, aps, dns):
"""
Returns populated ApDnContainer
"""
cnt = ApDnContainer()
_read_dns_(dns, cnt)
+ _read_wlan_aps_(wlan_aps, cnt)
_read_aps_(aps, cnt)
cnt._calc_dn_ids_()
-
- if wlan_support:
- cnt._calc_ap_ids_(2)
- else:
- cnt._calc_ap_ids_(1)
-
- cnt._calc_ap_indexes_(1)
+ cnt._calc_ap_ids_()
+ cnt._calc_ap_indexes_()
return cnt
@@ -127,6 +123,12 @@
cnt.add_dn(mydn)
return cnt
+def _read_all_aps_(wlan_aps, aps, cnt):
+ """
+ Reads WLAN_APs and APs to internal objects to ApDnContainer
+ """
+
+
def _read_aps_(aps, cnt):
"""
Reads APs to internal objects to ApDnContainer.
@@ -159,7 +161,39 @@
cnt.add_ap(myap)
return cnt
-def _get_next_free_id_(bases, start_index=1):
+def _read_wlan_aps_(wlan_aps, cnt):
+ """
+ Reads APs to internal objects to ApDnContainer.
+ """
+ ap_names = None
+ ap_ids1 = None
+
+ for ap in wlan_aps.WLAN_AP:
+ if ap.ref == 'ConnectionName':
+ ap_names = ap.value
+ if ap.ref == 'ConnectionId':
+ ap_ids1 = ap.value
+
+ ap_ids2 = [None]*len(ap_names)
+ if ap_ids1 == None:
+ ap_ids1 = []
+
+
+ for i in range(len(ap_ids1)):
+ ap_ids2[i] = ap_ids1[i]
+
+
+ logger.info('Parsed WLAN_AP names: %s' % ap_names)
+ logger.info('Parsed WLAN_AP ids: %s' % ap_ids2)
+
+ for i in range(len(ap_names)):
+ myap = Ap()
+ myap.set_id(ap_ids2[i])
+ myap.set_name(ap_names[i])
+ cnt.add_ap(myap)
+ return cnt
+
+def _get_next_free_id_(bases, start_index=0):
"""
Returns next id as a string that is not in use.
"""
@@ -206,7 +240,6 @@
def _calc_ap_indexes_(self, ind=1):
index = ind
-
for dn in self.dns:
for iap in dn.get_iaps():
if iap != None:
@@ -215,16 +248,11 @@
ap.set_index(str(index))
index += 1
- def _calc_ap_ids_(self, start_index=1):
- """
- Calculates unique index for every AccessPoint, if Easy_WLAN is given it always have index 1.
+ def _calc_ap_ids_(self, start_index=0):
"""
-
- for ap in self.aps:
- if ap.name == 'Easy WLAN':
- ap.set_id('1')
- logger.info('Easy_WLAN AP found. Setting 1 to AP id.')
-
+ Calculates unique index for every AccessPoint.
+ """
+
for ap in self.aps:
if ap.get_id() == None or ap.get_id() == '':
ap.set_id(_get_next_free_id_(self.aps, int(start_index)))
@@ -237,6 +265,7 @@
for ap in self.aps:
if ap.name == apname:
return ap.get_id()
+ logger.warning('ApId not found by ApName: %s' % apname)
return None
def get_apindex_by_apname(self, apname):
@@ -247,6 +276,7 @@
for ap in self.aps:
if ap.get_name() == apname:
return ap.get_index()
+ logger.warning('ApIndex not found by ApName: %s' % apname)
return None
@@ -257,6 +287,7 @@
for dn in self.dns:
if dn.name == dnname:
return dn.id
+ logger.warning('DnId not found by DnName: %s' % dnname)
return None
def get_apid_by_dnname_and_apname(self, dnname, apname):
@@ -269,6 +300,7 @@
for iap in range(len(iaps)):
if iaps[iap] != None and iaps[iap] == apname:
return self.get_apid_by_apname(apname)
+ logger.warning('ApId not found by DnName: %s ApName: %s' % dnname, apname)
return None
def get_all_in_array(self):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -1,9 +1,9 @@
# 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"
+# under the terms of the License "Symbian Foundation License v1.0"
# which accompanies this distribution, and is available
-# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+# at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
@@ -17,12 +17,52 @@
Ruleml eval extension to check is passed ref changed on given layer(range).
'''
-from cone.public import api
+from cone.public import api, plugin
import logging
+import re
logger = logging.getLogger('cone.ruleplugin.evals.layer_utils')
+
+def layers_used(config, layers_or_regex, impl_tags):
+ """
+ Return True if matching layers are used by any implementation with given tag.
+ @param config: The configuration.
+ @param layers_or_regex: List of layer objects to check against, or regular
+ expression (string) for resolving the list of layers.
+ @param impl_tags: Implementation tags to use.
+ """
+ # Resolve layer list
+ if isinstance(layers_or_regex, basestring):
+ layers = []
+ for lay in config.list_configurations():
+ if re.search(layers_or_regex, lay):
+ layers.append(config.get_configuration(lay))
+ else:
+ layers = layers_or_regex
+
+ impls = plugin.filtered_impl_set(config).filter_implementations(tags=impl_tags)
+ context = plugin.GenerationContext(tags=impl_tags,
+ configuration=config)
+ for impl in impls:
+ if impl.uses_layers(layers, context) == True:
+ return True
+ return False
+
+
+def get_all_layers(feat):
+ """
+ Returns all layers.
+ """
+
+ root_conf = feat.get_root_configuration()
+ result = []
+
+ for i in range(0, len(root_conf.list_configurations())):
+ result.append(root_conf.get_configuration_by_index(i))
+ return result
+
def give_changed_layers(feat):
"""
Returns a list of booleans where True means that feature is changed in that layer. Index is
@@ -33,22 +73,9 @@
root_conf = feat.get_root_configuration()
nro_of_layers = len(root_conf.list_configurations())
- result = [False] * nro_of_layers
-
+ result = []
for i in range(0, nro_of_layers):
- conf = root_conf.get_configuration_by_index(i)
- logger.debug("Traversing data from configuration: %s" % conf.get_path())
- datas = conf._traverse(type=api.Data, filters=[lambda d: d.fqr==feat.fqr])
- for data in datas:
- try:
- if data.get_value() != None:
- logger.debug("Feature '%s' is changed in layer %s with data '%s'" % (feat.fqr, i, data.get_value()))
- result[i] = True
- except Exception, e:
- logger.debug("Failed to check Feature '%s' data in layer %s:", (e,i))
- if result[i] == False:
- logger.debug("Feature '%s' is not changed in layer: %s" % (feat.fqr, i))
- logger.debug("Feature '%s' is changed in layers: %s" % (feat.fqr, result))
+ result.append(_changed_on_layer(feat, root_conf.get_configuration_by_index(i)))
return result
def changed_on_last_layer(feat):
@@ -58,18 +85,7 @@
root_conf = feat.get_root_configuration()
conf = root_conf.get_configuration_by_index(-2)#autoconfig layer is ignored
-
- def check(node):
- if isinstance(node, api.Data) and node.fqr == feat.fqr:
- return True
- for obj in node._objects():
- if check(obj):
- return True
-
- if check(conf):
- return True
- else:
- return False
+ return _changed_on_layer(feat, conf)
def changed_on_autoconfig_layer(feat):
"""
@@ -77,19 +93,8 @@
"""
root_conf = feat.get_root_configuration()
- conf = root_conf.get_configuration_by_index(-1)
-
- def check(node):
- if isinstance(node, api.Data) and node.fqr == feat.fqr:
- return True
- for obj in node._objects():
- if check(obj):
- return True
-
- if check(conf):
- return True
- else:
- return False
+ conf = root_conf.get_configuration_by_index(-1)
+ return _changed_on_layer(feat, conf)
def changed_on_layer(feat, layer):
"""
@@ -97,23 +102,72 @@
"""
try:
return give_changed_layers(feat)[layer]
- except IndexError, e:
+ except IndexError:
logger.warning("Given layer is not found: %s" % (layer))
return False
+def _changed_on_layer(feature, layer_obj):
+ """
+ Return whether the given feature is changed on the given layer.
+ """
+ # Check recursively if the layer contains any data objects with
+ # the same FQR as the feature
+ def check(node):
+ if isinstance(node, api.Data) and node.fqr == feature.fqr:
+ return True
+ for obj in node._objects():
+ if check(obj):
+ return True
+ return False
+
+ return check(layer_obj)
+
def changed_on_layers(feat, findex, tindex):
"""
Returns True if feature is changed in layer of given range.
"""
- layers = give_changed_layers(feat)
+ root_conf = feat.get_root_configuration()
+ nro_of_layers = len(root_conf.list_configurations())
- if findex == tindex:
- return changed_on_layer(feat, findex)
+ # Convert negative indices to positive
+ def neg_index_to_pos(index):
+ if index < 0: return nro_of_layers + index
+ else: return index
+ begin = neg_index_to_pos(findex)
+ end = neg_index_to_pos(tindex)
- for i in range(findex, tindex):
- if i > len(layers):
+ if end == begin:
+ return changed_on_layer(feat, begin)
+
+ # Check the layers inside the range
+ if end > begin: index_range = xrange(begin, end)
+ else: index_range = xrange(end, begin)
+ for i in index_range:
+ if i < 0 or i >= nro_of_layers:
continue
- if layers != None and layers[i] != None and layers[i]:
+
+ layer = root_conf.get_configuration_by_index(i)
+ if _changed_on_layer(feat, layer):
return True
return False
+def changed_on_layers_regex(feat, regex):
+ """
+ Return whether the given feature is changed on any layer that matches
+ the given regular expression.
+ """
+ pattern = re.compile(regex)
+ root_conf = feat.get_root_configuration()
+ for config_path in root_conf.list_configurations():
+ if pattern.search(config_path):
+ layer = root_conf.get_configuration(config_path)
+ if _changed_on_layer(feat, layer):
+ return True
+ return False
+
+def changed_on_custvariant_layer(feat):
+ """
+ Return whether the given feature is changed on any of the custvariant layers
+ (layers that match the regex '/custvariant(_.*)?/').
+ """
+ return changed_on_layers_regex(feat, r'/custvariant(_.*)?/')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/shortcuts_conversion.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/shortcuts_conversion.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/shortcuts_conversion.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,79 +17,79 @@
import os
def get_fixed_target_path(feature, setting):
- type_ref = setting + '_type'
- type = feature.get_feature(type_ref)
- type_value = type.get_value()
- ret = ""
- if type_value == '1':
- None
- elif type_value == '2':
- icon = feature.get_feature(setting + '_icon')
- if icon != None:
- ret = get_fixed_icon_target(icon)
- else:
- None
-
- return ret
+ type_ref = setting + '_type'
+ type = feature.get_feature(type_ref)
+ type_value = type.get_value()
+ ret = ""
+ if type_value == '1':
+ None
+ elif type_value == '2':
+ icon = feature.get_feature(setting + '_icon')
+ if icon != None:
+ ret = get_fixed_icon_target(icon)
+ else:
+ None
+
+ return ret
def get_fixed_icon_target(icon):
- targetPath = icon.get_feature('targetPath').get_value()
- localPath = icon.get_feature('localPath').get_value()
- target = get_target_without_extension(targetPath)
- extension = get_correct_extension(localPath)
- fixed = ""
- if extension != None:
- if len(target) > 0 and len(extension) > 0:
- fixed = target + extension
- return fixed
+ targetPath = icon.get_feature('targetPath').get_value()
+ localPath = icon.get_feature('localPath').get_value()
+ target = get_target_without_extension(targetPath)
+ extension = get_correct_extension(localPath)
+ fixed = ""
+ if extension != None:
+ if len(target) > 0 and len(extension) > 0:
+ fixed = target + extension
+ return fixed
def get_target_without_extension(targetPath):
- (target,_) = os.path.splitext(targetPath)
- return target
+ (target,_) = os.path.splitext(targetPath)
+ return target
def get_correct_extension(localPath):
-
- if localPath != None:
- (_,extension) = os.path.splitext(localPath)
- if extension == '.bmp':
- return '.mbm'
- elif extension == '.svg':
- return '.mif'
- else:
- return extension
- else:
- return None
+
+ if localPath != None:
+ (_,extension) = os.path.splitext(localPath)
+ if extension == '.bmp':
+ return '.mbm'
+ elif extension == '.svg':
+ return '.mif'
+ else:
+ return extension
+ else:
+ return None
def get_shortcut_string(feature, setting):
- type_ref = setting + '_type'
- type_value = feature.get_feature(type_ref).get_value()
- ret = ""
- if type_value == '1':
- app_ref = setting + '_app'
- application = feature.get_feature(app_ref).get_value()
- ret = application
- elif type_value == '2':
- url = feature.get_feature(setting+'_URL').get_value()
- title = feature.get_feature(setting+'_title').get_value()
+ type_ref = setting + '_type'
+ type_value = feature.get_feature(type_ref).get_value()
+ ret = ""
+ if type_value == '1':
+ app_ref = setting + '_app'
+ application = feature.get_feature(app_ref).get_value()
+ ret = application
+ elif type_value == '2':
+ url = feature.get_feature(setting+'_URL').get_value()
+ title = feature.get_feature(setting+'_title').get_value()
- if title == None:
- title = ""
- else:
- title = 'customtitle=' + title
-
- icon = feature.get_feature(setting + '_icon')
- image_path = icon.get_feature('targetPath').get_value()
-
- icon_str = ""
-
- if image_path != None and image_path != "":
- icon_str = 'iconmifpath='
- if image_path.endswith('.mif'): index = '16384'
- else: index = '0'
- icon_str = icon_str + image_path + ';' + index + '&'
-
- ret = url + '?custom?' + icon_str + title
- return ret
+ if title == None:
+ title = ""
+ else:
+ title = 'customtitle=' + title
+
+ icon = feature.get_feature(setting + '_icon')
+ image_path = icon.get_feature('targetPath').get_value()
+
+ icon_str = ""
+
+ if image_path != None and image_path != "":
+ icon_str = 'iconmifpath='
+ if image_path.endswith('.mif'): index = '16384'
+ else: index = '0'
+ icon_str = icon_str + image_path + ';' + index + '&'
+
+ ret = url + '?custom?' + icon_str + title
+ return ret
#print get_shortcut_string('1', '2', '3')
#http://www.nokia2.com?custom?iconmifpath=Z:\\resource\\apps\\icon2.mbm;1&customtitle=Nokia2
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/__init__.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,4 @@
#
# Description:
#
-import sys, os, unittest
-# Path to the directory where this file is located
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
-plugin_utils.plugin_test_init(ROOT_PATH, '../../..')
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/confml/test_feature.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/confml/test_feature.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ true
+ 0
+
+
+ false
+ false
+
+
+ 0
+ 0
+ 0
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer7/foo.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer7/foo.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Foo
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer9/bar.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer9/bar.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Bar
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer9/foo.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/layer9/foo.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Foo
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/content/test.txt
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/base.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/base.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+ Value: {{ feat_tree.TestFeature.BaseLayerSetting._value }}
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer1.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer1.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer1Setting._value }}
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer10.content
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer10.content Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer11.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer11.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+ ${TestFeature.EnableLayer11Content} configures ${TempLayer11InputFiles} = {% "layer9/foo.txt, layer9/bar.txt" %}
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer2.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer2.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer2Setting._value }}
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer3.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer3.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer3Setting._value }}
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer4.content
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer4.content Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer5.content
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer5.content Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer6.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer6.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer6Setting._value }}
+
+
+
+
+
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer6Setting._value }}
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer7.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer7.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer8.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer8.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Value: {{ feat_tree.TestFeature.Layer8Setting._value }}
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer9.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/layer9.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+ TestFeature.EnableLayer9Content configures TempLayer9InputFiles = {% "layer9/foo.txt, layer9/bar.txt" %}
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/uses_layers_test.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/implml/uses_layers_test.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,100 @@
+
+
+
+
+ {% check_uses_layer() %} configures "foo" = "baar"
+
+
+import os
+
+from ruleplugin.evals import layer_utils
+
+def check_uses_layer():
+ results = [('Layer', 'Tag', 'Expected', 'Actual', 'Outcome')]
+
+ def check(layer_index, tag, expected):
+ layer = ruleml.configuration.get_configuration_by_index(layer_index)
+ result = layer_utils.layers_used(ruleml.configuration, [layer], {'target' : [tag]})
+
+ if result == expected: outcome = "OK"
+ else: outcome = "FAIL"
+
+ results.append((layer.get_path(), tag, expected, result, outcome))
+
+ # BASE
+ check(layer_index = 0, tag = 'uda', expected = True)
+ check(layer_index = 0, tag = 'rofs3', expected = True)
+ check(layer_index = 0, tag = 'rofs2', expected = True)
+
+ # LAYER 1
+ check(layer_index = 1, tag = 'uda', expected = True)
+ check(layer_index = 1, tag = 'rofs3', expected = False)
+ check(layer_index = 1, tag = 'rofs2', expected = False)
+
+ # LAYER 2
+ check(layer_index = 2, tag = 'uda', expected = False)
+ check(layer_index = 2, tag = 'rofs3', expected = False)
+ check(layer_index = 2, tag = 'rofs2', expected = True)
+
+ # LAYER 3
+ check(layer_index = 3, tag = 'uda', expected = False)
+ check(layer_index = 3, tag = 'rofs3', expected = False)
+ check(layer_index = 3, tag = 'rofs2', expected = False)
+
+ # LAYER 4
+ check(layer_index = 4, tag = 'uda', expected = True)
+ check(layer_index = 4, tag = 'rofs3', expected = False)
+ check(layer_index = 4, tag = 'rofs2', expected = False)
+
+ # LAYER 5
+ check(layer_index = 5, tag = 'uda', expected = False)
+ check(layer_index = 5, tag = 'rofs3', expected = True)
+ check(layer_index = 5, tag = 'rofs2', expected = False)
+
+ # LAYER 6
+ check(layer_index = 6, tag = 'uda', expected = True)
+ check(layer_index = 6, tag = 'rofs3', expected = True)
+ check(layer_index = 6, tag = 'rofs2', expected = False)
+
+ # LAYER 7
+ check(layer_index = 7, tag = 'uda', expected = True)
+ check(layer_index = 7, tag = 'rofs3', expected = False)
+ check(layer_index = 7, tag = 'rofs2', expected = False)
+
+ # LAYER 8
+ check(layer_index = 8, tag = 'uda', expected = False)
+ check(layer_index = 8, tag = 'rofs3', expected = False)
+ check(layer_index = 8, tag = 'rofs2', expected = False)
+
+ # LAYER 9
+ check(layer_index = 9, tag = 'uda', expected = True)
+ check(layer_index = 9, tag = 'rofs3', expected = False)
+ check(layer_index = 9, tag = 'rofs2', expected = False)
+
+ # LAYER 10
+ check(layer_index = 10, tag = 'uda', expected = True)
+ check(layer_index = 10, tag = 'rofs3', expected = False)
+ check(layer_index = 10, tag = 'rofs2', expected = False)
+
+ # LAYER 11
+ check(layer_index = 11, tag = 'uda', expected = True)
+ check(layer_index = 11, tag = 'rofs3', expected = False)
+ check(layer_index = 11, tag = 'rofs2', expected = False)
+
+ # Write the results to output
+ f = open(os.path.join(ruleml.context.output, 'uses_layers_test.txt'),'w')
+ try:
+ # Column widths
+ layer_cw = max([len(str(r[0])) for r in results]) + 2
+ tag_cw = max([len(str(r[1])) for r in results]) + 2
+ expected_cw = max([len(str(r[2])) for r in results])
+ actual_cw = max([len(str(r[3])) for r in results]) + 2
+
+ format = "%%-%ss %%-%ss %%-%ss %%-%ss %%s\n" % (layer_cw, tag_cw, expected_cw, actual_cw)
+ for r in results:
+ f.write(format % r)
+ finally:
+ f.close()
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/base/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer1/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer1/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ 1
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/content/layer10/foo.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/content/layer10/foo.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Foo
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer10/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer11/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer11/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer11/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer11/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer2/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer2/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ 2
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer2/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer2/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer3/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer3/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ 2
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer3/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer3/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer4/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer4/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,9 @@
+
+
+
+
+ test_input.txt
+ test_output.txt
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer4/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer4/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer5/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer5/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ test_extinput.txt
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer5/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer5/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer6/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer6/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ 6
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer6/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer6/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer7/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer7/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer7/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer7/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer8/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer8/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ 8
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer8/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer8/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer9/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer9/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer9/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/assets/layer9/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/configurator/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/configurator/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ false
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/configurator/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/configurator/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/manual/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/manual/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ false
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/manual/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/customer/custvariant_123_xyz/manual/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/rnd/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/rnd/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,8 @@
+
+
+
+
+ false
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/rnd/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foo/bar/rnd/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foobar_root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/foobar_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/layer1/confml/test.confml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/layer1/confml/test.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/layerproject/layer1/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,12 +1,22 @@

-
-
-
-
-
-
- String 1
-
-
+
+
+
+
+
+
+
+
+
+
+
+ String 1
+
+
+ false
+ false
+ false
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/ruleproject/layer2/confml/data.confml
Binary file configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/ruleproject/layer2/confml/data.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/runtests.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_accesspoint_id_counter.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_accesspoint_id_counter.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_accesspoint_id_counter.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,15 +15,9 @@
#
import unittest
-import os, shutil
-import sys
-import pkg_resources
-import re
+import os
-import __init__
-
-from ruleplugin import ruleml, relations
-from cone.public import api, exceptions
+from cone.public import api
from ruleplugin.evals import accesspoint_id_counter
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -33,29 +27,32 @@
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
self.assertEquals('Internet', container.get_all_dns()[0].get_name())
self.assertEquals('1', container.get_all_dns()[0].get_id())
- self.assertEquals(['IAP11', 'IAP12', 'IAP13', None, None, None, None, None, None, None], container.get_all_dns()[0].get_iaps())
+ self.assertEquals(['IAP11', 'IAP12', 'IAP13', 'WIAP16', None, None, None, None, None, None],
+ container.get_all_dns()[0].get_iaps())
self.assertEquals('MMS', container.get_all_dns()[1].get_name())
self.assertEquals('2', container.get_all_dns()[1].get_id())
- self.assertEquals(['IAP21', 'IAP22', 'IAP23', 'IAP13', None, None, None, None, None, None], container.get_all_dns()[1].get_iaps())
+ self.assertEquals(['IAP21', 'IAP22', 'IAP23', None, None, None, None, None, None, None],
+ container.get_all_dns()[1].get_iaps())
self.assertEquals('Operator', container.get_all_dns()[2].get_name())
self.assertEquals('3', container.get_all_dns()[2].get_id())
- self.assertEquals(['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None], container.get_all_dns()[2].get_iaps())
+ self.assertEquals(['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None],
+ container.get_all_dns()[2].get_iaps())
- self.assertEquals('IAP11', container.get_all_aps()[0].get_name())
- self.assertEquals('1', container.get_all_aps()[0].get_id())
+ self.assertEquals('WIAP16', container.get_all_aps()[0].get_name())
+ self.assertEquals('5', container.get_all_aps()[0].get_id())
def test_get_apid_by_apname(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
self.assertEquals('1', container.get_apid_by_apname('IAP11'))
self.assertEquals('2', container.get_apid_by_apname('IAP12'))
@@ -66,7 +63,7 @@
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
self.assertEquals('1', container.get_dnid_by_dnname('Internet'))
self.assertEquals('2', container.get_dnid_by_dnname('MMS'))
@@ -78,7 +75,7 @@
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
self.assertEquals('2', container.get_apid_by_dnname_and_apname('Internet', 'IAP12'))
@@ -87,25 +84,40 @@
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
-
- self.assertEquals('9', container.get_all_aps()[6].get_id())
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
+
+ self.assertEquals('6', container.get_all_aps()[6].get_id())
+ self.assertEquals('5', container.get_all_aps()[0].get_id())
def test_all_in_array(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
- self.assertEquals(container.get_all_in_array(), [['Internet', '1', ['IAP11', 'IAP12', 'IAP13', None, None, None, None, None, None, None], ['1', '2', '7', None, None, None, None, None, None, None], ['1', '2', '3', None, None, None, None, None, None, None]], ['MMS', '2', ['IAP21', 'IAP22', 'IAP23', 'IAP13', None, None, None, None, None, None], ['4', '8', '6', '7', None, None, None, None, None, None], ['4', '5', '6', '3', None, None, None, None, None, None]], ['Operator', '3', ['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None], [None, None, '9', None, None, None, None, None, None, None], [None, None, '7', None, None, None, None, None, None, None]]])
+ self.assertEquals(container.get_all_in_array(),
+ [
+ ['Internet', '1',
+ ['IAP11', 'IAP12', 'IAP13', 'WIAP16', None, None, None, None, None, None],
+ ['1', '2', '7', '5', None, None, None, None, None, None],
+ ['1', '2', '3', '4', None, None, None, None, None, None]],
+ ['MMS', '2',
+ ['IAP21', 'IAP22', 'IAP23', None, None, None, None, None, None, None],
+ ['4', '8', '6', None, None, None, None, None, None, None],
+ ['5', '6', '7', None, None, None, None, None, None, None]],
+ ['Operator', '3',
+ ['IAP31', 'IAP32', 'IAP33', None, None, None, None, None, None, None],
+ [None, None, '9', None, None, None, None, None, None, None],
+ [None, None, '8', None, None, None, None, None, None, None]]
+ ]
+ )
def test_get_next_free_id(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject')))
config = project.get_configuration('root.confml')
dview = config.get_default_view()
-
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
self.assertEquals("4", accesspoint_id_counter._get_next_free_id_(container.get_all_dns()))
self.assertEquals("10", accesspoint_id_counter._get_next_free_id_(container.get_all_aps()))
@@ -115,9 +127,9 @@
config = project.get_configuration('root.confml')
dview = config.get_default_view()
- container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("APs"), dview.get_feature("DNs"), True)
+ container = accesspoint_id_counter._get_ApDnContainer_(dview.get_feature("WLAN_APs"), dview.get_feature("APs"), dview.get_feature("DNs"))
- self.assertEquals("4", container.get_apindex_by_apname("IAP21"))
+ self.assertEquals("5", container.get_apindex_by_apname("IAP21"))
self.assertEquals("1", container.get_apindex_by_apname("IAP11"))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_layer_utils.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_layer_utils.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/tests/unittest_layer_utils.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,16 +15,9 @@
#
import unittest
-import os, shutil
-import sys
-import pkg_resources
-import re
-import logging
+import os
-import __init__
-
-from ruleplugin import ruleml, relations
-from cone.public import api, exceptions
+from cone.public import api
from ruleplugin.evals import layer_utils
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -86,7 +79,163 @@
self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value1"),8,9))
self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),0,1))
self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),1,5))
+
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),3,5))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),5,3))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-2,-1))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-1,-2))
+
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),2,5))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),5,2))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-3,-1))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-1,-3))
+
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),3,1000))
+ self.assertFalse(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-1000,1))
+ self.assertTrue(layer_utils.changed_on_layers(dview.get_feature("StringFeatureTest.Value2"),-1000,1000))
+ def test_layers_used_single_layer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layer_filtering_project')))
+ root_config = project.get_configuration('root.confml')
+ layer_base_config = root_config.get_configuration_by_index(0)
+ layer1_config = root_config.get_configuration_by_index(1)
+ layer2_config = root_config.get_configuration_by_index(2)
+ layer3_config = root_config.get_configuration_by_index(3)
+ layer4_config = root_config.get_configuration_by_index(4)
+ layer5_config = root_config.get_configuration_by_index(5)
+ layer6_config = root_config.get_configuration_by_index(6)
+ layer7_config = root_config.get_configuration_by_index(7)
+ layer8_config = root_config.get_configuration_by_index(8)
+ layer9_config = root_config.get_configuration_by_index(9)
+ layer10_config = root_config.get_configuration_by_index(10)
+ layer11_config = root_config.get_configuration_by_index(11)
+
+ self.assertTrue(layer_utils.layers_used(root_config, [root_config], {'target' : ['uda']}))
+ self.assertTrue(layer_utils.layers_used(root_config, [root_config], {'target' : ['rofs2']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, [layer_base_config], {'target' : ['uda']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer1_config], {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer2_config], {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer3_config], {'target' : ['uda']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer4_config], {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer5_config], {'target' : ['uda']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, [layer_base_config], {'target' : ['rofs2']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer1_config], {'target' : ['rofs2']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer2_config], {'target' : ['rofs2']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer3_config], {'target' : ['rofs2']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, [layer5_config], {'target' : ['rofs3']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer5_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer6_config], {'target' : ['rofs2']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer6_config], {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer6_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer7_config], {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer7_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer8_config], {'target' : ['rofs3']}))
+ self.assertFalse(layer_utils.layers_used(root_config, [layer8_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer9_config], {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer9_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer10_config], {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer10_config], {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, [layer11_config], {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, [layer11_config], {'target' : ['uda']}))
+
+ def test_layers_used_regex(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'layer_filtering_project')))
+ root_config = project.get_configuration('root.confml')
+
+ self.assertTrue(layer_utils.layers_used(root_config, r'/base/', {'target' : ['uda']}))
+ self.assertTrue(layer_utils.layers_used(root_config, r'/base/', {'target' : ['rofs2']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, r'/base/', {'target' : ['uda']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer1/', {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer2/', {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer3/', {'target' : ['uda']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer4/', {'target' : ['uda']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer5/', {'target' : ['uda']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, r'/base/', {'target' : ['rofs2']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer1/', {'target' : ['rofs2']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer2/', {'target' : ['rofs2']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer3/', {'target' : ['rofs2']}))
+
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer5/', {'target' : ['rofs3']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer5/', {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer6/', {'target' : ['rofs2']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer6/', {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer6/', {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer7/', {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer7/', {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer8/', {'target' : ['rofs3']}))
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer8/', {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer9/', {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer9/', {'target' : ['uda']}))
+
+ self.assertFalse(layer_utils.layers_used(root_config, r'/layer10/', {'target' : ['rofs3']}))
+ self.assertTrue( layer_utils.layers_used(root_config, r'/layer10/', {'target' : ['uda']}))
+
+ def test_changed_on_layers_regex(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH, 'layerproject')))
+ config = project.get_configuration('foobar_root.confml')
+ dview = config.get_default_view()
+
+ def check(regex, feature, expected):
+ self.assertEquals(layer_utils.changed_on_layers_regex(dview.get_feature(feature), regex),
+ expected)
+
+ check(r'.*', 'TestFeature.CustvariantManual', True)
+
+ regex = r'/custvariant(_.*)?/manual/'
+ check(regex, 'TestFeature.CustvariantManual', True)
+ check(regex, 'TestFeature.CustvariantConfigurator', False)
+ check(regex, 'TestFeature.Rnd', False)
+
+ regex = r'/custvariant(_.*)?/configurator/'
+ check(regex, 'TestFeature.CustvariantManual', False)
+ check(regex, 'TestFeature.CustvariantConfigurator', True)
+ check(regex, 'TestFeature.Rnd', False)
+
+ regex = r'/custvariant(_.*)?/'
+ check(regex, 'TestFeature.CustvariantManual', True)
+ check(regex, 'TestFeature.CustvariantConfigurator', True)
+ check(regex, 'TestFeature.Rnd', False)
+
+ regex = r'foo/bar/'
+ check(regex, 'StringFeatureTest.Value1', False)
+ check(regex, 'TestFeature.CustvariantManual', True)
+ check(regex, 'TestFeature.CustvariantConfigurator', True)
+ check(regex, 'TestFeature.Rnd', True)
+
+ regex = r'/rnd/'
+ check(regex, 'TestFeature.CustvariantManual', False)
+ check(regex, 'TestFeature.CustvariantConfigurator', False)
+ check(regex, 'TestFeature.Rnd', True)
+
+ def test_changed_on_custvariant_layer(self):
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH, 'layerproject')))
+ config = project.get_configuration('foobar_root.confml')
+ dview = config.get_default_view()
+
+ def check(feature, expected):
+ self.assertEquals(layer_utils.changed_on_custvariant_layer(dview.get_feature(feature)),
+ expected)
+ check('StringFeatureTest.Value1', False)
+ check('StringFeatureTest.Value2', False)
+ check('TestFeature.CustvariantManual', True)
+ check('TestFeature.CustvariantConfigurator', True)
+ check('TestFeature.Rnd', False)
+
if __name__ == "__main__":
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/relations.py Tue Aug 10 14:29:28 2010 +0300
@@ -40,13 +40,13 @@
raise exceptions.NotSupportedException("No Relation class found for name %s" % relation_name)
@ classmethod
- def get_relations(cls, configuration, relation):
+ def get_relations(cls, relation):
try:
relations = []
(left_expression,relation_name,right_expression) = parse_rule(relation)
- relation = cls.get_relation_by_name(relation_name)(configuration, left_expression, right_expression)
+ relation = cls.get_relation_by_name(relation_name)(left_expression, right_expression)
relations.append(relation)
- propagated_relations = cls.get_relations(configuration, right_expression)
+ propagated_relations = cls.get_relations(right_expression)
if propagated_relations:
for relation in propagated_relations:
relations.append(relation)
@@ -55,86 +55,32 @@
return None
-class ConfigurationContext(rules.DefaultContext):
-
- def __init__(self, data):
- rules.DefaultContext.__init__(self, data)
-
- # A note on the callback variables that follow:
- # in order to collect rule execution results for the
- # generation report, a callback system is implemented in
- # ConfigurationContext. It all boils down to ConfigureRelation
- # using configure_expression_result_callback to catch the result
- # in its execute() method. The ConfigurationContext just works as
- # a "callback hub" because a reference to the context is available
- # in all expression evaluations.
-
- # Callback called with a plugin.RelationExecutionResult object
- # when a ConfigureExpression has been evaluated
- self.configure_expression_result_callback = None
-
- # Callback called with the setting reference when a setting is dereferenced
- # as a terminal expression
- self.ref_terminal_callback = None
-
- # Callback called with the setting reference when a setting is dereferenced
- # inside an EvalExpression
- self.ref_eval_callback = None
-
- # Callback called with the setting reference when the value of a setting
- # is set inside a SetExpression
- self.ref_set_callback = None
-
- def handle_terminal(self, expression):
- try:
- value = self.data.get_default_view().get_feature(expression).get_value()
-
- # Got a valid ref, call the callback
- if self.ref_terminal_callback:
- self.ref_terminal_callback(expression)
-
- return value
- except exceptions.NotFound,e:
- """ return the expression itself if it is not a fearef """
- #print "handle_terminal constant %s" % (expression)
- try:
- return eval(expression)
- except (NameError,SyntaxError), e:
- return expression
-
- def eval(self, ast, expression, value):
- #print "expression %s = %s" % (expression,value)
- pass
-
class ConfigurationBaseRelation(rules.BaseRelation):
- def __init__(self, data, left, right):
- self.context = ConfigurationContext(data)
- super(ConfigurationBaseRelation, self).__init__(data, left, right)
+ def __init__(self, left, right):
+ super(ConfigurationBaseRelation, self).__init__(None, left, right)
+ self.context = None
class RequireRelation(ConfigurationBaseRelation):
KEY = 'requires'
- def __init__(self, data, left, right):
- super(RequireRelation, self).__init__(data, left, right)
- self.context = ConfigurationContext(data)
+ relation_name = 'requires'
+ def __init__(self, left, right):
+ super(RequireRelation, self).__init__(left, right)
class ConfigureRelation(ConfigurationBaseRelation):
KEY = 'configures'
- def __init__(self, data, left, right):
- self.context = ConfigurationContext(data)
- super(ConfigureRelation, self).__init__(data, left, right)
+ relation_name = 'configures'
+ def __init__(self, left, right):
+ super(ConfigureRelation, self).__init__(left, right)
# A plugin.RelationExecutionResult object is stored here
self._execution_result = None
- def execute(self):
+ def execute(self, context):
self._execution_result = None
exec_results = []
- # Call BaseRelation.execute() and catch any ConfigureExpression result objects
- self.context.configure_expression_result_callback = lambda result: exec_results.append(result)
- result = rules.BaseRelation.execute(self)
- self.context.configure_expression_result_callback = None
+ result = rules.BaseRelation.execute(self, context)
if len(exec_results) > 0:
# There should be only one ConfigureExpression inside a ConfigureRelation
@@ -157,9 +103,6 @@
return True
return False
-def handle_set(self, left, right):
- left.set_value(right)
-
def handle_filenamejoin(self, left, right):
def extract_dirname(path):
"""Extract directory name (will always contain a trailing slash or backslash)"""
@@ -174,44 +117,21 @@
return extract_dirname(left) + extract_filename(right)
-def handle_plus(self, left, right):
- return left + right
-
-def handle_minus(self, left, right):
- return left - right
-
-def handle_multiply(self, left, right):
- return left * right
-
-def handle_divide(self, left, right):
- return left / right
class ConfigureExpression(rules.TwoOperatorExpression):
PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS']
KEY = 'configures'
OP = handle_configure
- def eval(self, context):
+ def eval(self, context, **kwargs):
input_refs = []
affected_refs = []
- # Evaluate the left-hand side expression, catching refs for the result
- try:
- context.ref_terminal_callback = lambda ref: input_refs.append(ref)
- context.ref_eval_callback = lambda ref: input_refs.append(ref)
- evaluated_left = self.left.eval(context)
- finally:
- context.ref_terminal_callback = None
- context.ref_eval_callback = None
-
+ # Evaluate the left-hand side expression
+ evaluated_left = self.left.eval(context, **kwargs)
if evaluated_left:
- # If left evaluated to True, evaluate the right-hand side and
- # catch refs from SetExpression evaluations
- try:
- context.ref_set_callback = lambda ref: affected_refs.append(ref)
- self.value = self.right.eval(context)
- finally:
- context.ref_set_callback = None
+ # If left evaluated to True, evaluate the right-hand side
+ self.value = self.right.eval(context, **kwargs)
else:
self.value = True
@@ -220,53 +140,20 @@
for ref in self.ast.extract_refs(str(self.left)):
for key in context.get_keys(ref):
left_keys.append(key)
-
for key in left_keys:
self.ast.add_error(key, { 'error_string' : 'CONFIGURES right side value is "False"',
'left_key' : key,
'rule' : self.ast.expression
})
-
- # Return a RelationExecutionResult if necessary
- if input_refs or affected_refs:
- if context.configure_expression_result_callback:
- result = plugin.RelationExecutionResult(utils.distinct_array(input_refs),
- utils.distinct_array(affected_refs))
- context.configure_expression_result_callback(result)
-
return self.value
-class MultiplyExpression(rules.TwoOperatorExpression):
- expression = "multiply_operation"
- PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
- KEY= '*'
- OP = handle_multiply
-
-class DivideExpression(rules.TwoOperatorExpression):
- expression = "divide_operation"
- PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
- KEY= '/'
- OP = handle_divide
-
-class PlusExpression(rules.TwoOperatorExpression):
- expression = "plus_operation"
- PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
- KEY= '+'
- OP = handle_plus
-
-class MinusExpression(rules.TwoOperatorExpression):
- expression = "minus_operation"
- PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
- KEY= '-'
- OP = handle_minus
-
class EvalExpression(rules.OneParamExpression):
expression = "__eval__"
PRECEDENCE = rules.PRECEDENCES['PREFIX_OPERATORS']
KEY = '__eval__'
- def __init__(self, ast, expression):
- super(rules.OneParamExpression, self).__init__(ast)
+ def __init__(self, ast, expression):
+ super(EvalExpression, self).__init__(ast, expression)
self.expression = expression
self._str_to_eval = eval(expression.expression)
#self.default_view = default_view
@@ -277,26 +164,26 @@
result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('@{', '}')))
return result
- def eval(self, context):
+ def get_refs(self):
+ return self.extract_refs()
+
+ def eval(self, context, **kwargs):
# Using the configuration to pass the eval globals dictionary to here,
# since there isn't any easy way to do this more elegantly
globals_and_locals = {}
- if hasattr(context.data, '_eval_expression_globals_dict'):
- globals_and_locals = context.data._eval_expression_globals_dict
+ if hasattr(context, '_eval_expression_globals_dict'):
+ globals_and_locals = context._eval_expression_globals_dict
str_to_eval = self._str_to_eval
def expand_feature_ref(ref, index):
var_name = "__fea_%05d" % index
- globals_and_locals[var_name] = context.data.get_default_view().get_feature(ref)
- if context.ref_eval_callback:
- context.ref_eval_callback(ref)
+ globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref)
return var_name
+
def expand_value_ref(ref, index):
var_name = "__feaval_%05d" % index
- globals_and_locals[var_name] = context.data.get_default_view().get_feature(ref).get_value()
- if context.ref_eval_callback:
- context.ref_eval_callback(ref)
+ globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref).get_value()
return var_name
str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_feature_ref, delimiters=('@{', '}'))
@@ -317,7 +204,6 @@
logging.getLogger('cone.ruleml').warning("Execution failed for eval: %s %s: %s" % (str_to_eval, type(e), e) )
self.ast.add_error(self.expression, { 'error_string' : 'Execution failed for eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
-rules.OPERATORS[EvalExpression.KEY] = EvalExpression
class FilenamejoinExpression(rules.TwoOperatorExpression):
expression = "filenamejoin"
@@ -325,62 +211,12 @@
KEY = 'filenamejoin'
OP = handle_filenamejoin
+# Register relations and operators to rules
+rules.RELATIONS[RequireRelation.KEY] = RequireRelation
+rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
rules.OPERATORS[FilenamejoinExpression.KEY] = FilenamejoinExpression
-
-class SetExpression(rules.TwoOperatorExpression):
- PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS']
- KEY= '='
- OP = handle_set
-
- def eval(self, context):
- try:
- variable = context.data.get_default_view().get_feature(self.left.expression)
- value = self.right.eval(context)
- variable.set_value(value)
- logging.getLogger('cone.ruleml').info("Set %r = %r from %r" % (self.left.expression, value, self.right.expression) )
- if context.ref_set_callback:
- context.ref_set_callback(self.left.expression)
- return True
- except exceptions.NotFound,e:
- self.ast.add_error(self.left.expression, { 'error_string' : 'Setting value failed, because of %s' % e,
- 'left_key' : self.left.expression,
- 'rule' : self.ast.expression})
- return False
-
-_relations_and_operators_backup = None
-
-def register():
- """
- Register the relations and operators to ConE rules.
- """
- global _relations_and_operators_backup
- if _relations_and_operators_backup is None:
- # Create the backup copies of the dictionaries
- rels_backup = rules.RELATIONS.copy()
- ops_backup = rules.OPERATORS.copy()
- assert rels_backup is not rules.RELATIONS
- assert ops_backup is not rules.OPERATORS
- _relations_and_operators_backup = (rels_backup, ops_backup)
-
- # Register relations and operators to rules
- rules.RELATIONS[RequireRelation.KEY] = RequireRelation
- rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
- rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
- rules.OPERATORS[PlusExpression.KEY] = PlusExpression
- rules.OPERATORS[SetExpression.KEY] = SetExpression
- rules.OPERATORS[MinusExpression.KEY] = MinusExpression
- rules.OPERATORS[MultiplyExpression.KEY] = MultiplyExpression
- rules.OPERATORS[DivideExpression.KEY] = DivideExpression
-
-def unregister():
- """
- Undo the changes made by a call to register().
- """
- global _relations_and_operators_backup
- if _relations_and_operators_backup is not None:
- rules.RELATIONS = _relations_and_operators_backup[0]
- rules.OPERATORS = _relations_and_operators_backup[1]
- _relations_and_operators_backup = None
+rules.OPERATORS[EvalExpression.KEY] = EvalExpression
+rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
def parse_rule(rulestring):
"""
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/ruleml.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/ruleml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/ruleml.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,21 +19,13 @@
import os
-import sys
import logging
-import shutil
-
-import __init__
-import re
+import pkg_resources
from ruleplugin import relations
-from cone.public import exceptions,plugin,utils,api,rules
+from cone.public import plugin,utils,rules
class RuleImpl(plugin.ImplBase):
- """
- MakeImpl plugin finds feature references that are configured in a .ruleml file
- and generate a rule from them
- """
IMPL_TYPE_ID = 'ruleml'
DEFAULT_INVOCATION_PHASE = 'pre'
@@ -42,7 +34,6 @@
Overloading the default constructor
"""
plugin.ImplBase.__init__(self,ref,configuration)
- self.logger = logging.getLogger('cone.ruleml(%s)' % self.ref)
self.relation_container = relation_container
def list_output_files(self):
@@ -51,19 +42,63 @@
"""
return []
+ def get_refs(self):
+ """
+ Return a list of all ConfML setting references that affect this
+ implementation. May also return None if references are not relevant
+ for the implementation.
+ """
+ refs = []
+ relations = self.get_relations()
+ for relation in relations:
+ # get refs from relation return a tuple (left side refs, right side refs)
+ # only the left side refs are the "input" refs
+ refs += relation.get_refs()
+ # If the rules do not have any references return None to disable filter by refs
+ if refs == []:
+ refs = None
+ return refs
+
+ def get_target_refs(self):
+ """
+ Return a list of all ConfML setting references that are affected by this
+ implementation. May also return None if references are not relevant
+ for the implementation.
+ """
+ refs = []
+ relations = self.get_relations()
+ for relation in relations:
+ refs += relation.get_set_refs()
+ return refs
+
+ def get_outputs(self):
+ """
+ Return a list of GenerationOutput objets as a list.
+ """
+ outputs = []
+ phase = None
+ if self.generation_context: phase = self.generation_context.phase
+ for rel in self.get_relations():
+ outrefs = rel.get_set_refs()
+ for ref in outrefs:
+ outputs.append(plugin.GenerationOutput(ref,rel,type='ref', phase=phase))
+ return outputs
+
def generate(self, context=None):
- self.logger.info("Generating rules from %s" % self.ref)
+ logging.getLogger('cone.ruleml(%s)' % self.ref).info("Generating rules from %s" % self.ref)
relation_container = self.get_relation_container()
relation_container.context = context
- return relation_container.execute()
-
- def has_tag(self, tags, policy=None):
- # RuleML should always be executed, regardless of the tags
- return True
+ return relation_container.execute(context)
def get_relation_container(self):
return self.relation_container
+ def get_relations(self):
+ return self.relation_container.get_relations()
+
+class RuleBuiltinsModule(object):
+ pass
+
class RulemlRelationContainer(plugin.RelationContainer):
"""
Relation container for RuleML rules.
@@ -73,7 +108,6 @@
"""
def __init__(self, configuration, source, rule_list, eval_globals):
plugin.RelationContainer.__init__(self, configuration, source=source)
- self.logger = logging.getLogger('cone.ruleml_relation_container(%s)' % self.source)
self.configuration = configuration
self.relation_container = rules.RelationContainerImpl()
self.eval_globals = eval_globals
@@ -81,124 +115,100 @@
for rule in rule_list:
self.relation_container.add_relation(rule)
- def execute(self):
+ def execute(self, context=None):
results = []
-
+ if context: self.context = context
+
# Create the autoconfig if not done already
- plugin.get_autoconfig(self.configuration)
+ autoconfig = plugin.get_autoconfig(self.configuration)
- # Register relations etc. to the rule engine.
- # Due to unit test issues the relations are not registered
- # in the relations module, but only for the duration of
- # rule parsing and execution
- relations.register()
- try:
- # Using the configuration to pass the eval globals dict to the
- # eval expression. The configuration only contains the globals
- # dict for the duration of the rule execution, so hopefully this
- # shouldn't mess anything up
- self._set_builtin_eval_globals()
- self.configuration._eval_expression_globals_dict = self.eval_globals
- for i, rel in enumerate(self.relation_container):
- index = i + 1
-
- # Execute
- self._execute_relation_and_log_error(rel, self.source, index)
-
- # Collect execution result if supported
- if hasattr(rel, 'get_execution_result'):
- result = rel.get_execution_result()
- if isinstance(result, plugin.RelationExecutionResult):
- result.source = self.source
- result.index = index
- results.append(result)
+ # Using the configuration to pass the eval globals dict to the
+ # eval expression. The configuration only contains the globals
+ # dict for the duration of the rule execution, so hopefully this
+ # shouldn't mess anything up
+ self._set_builtin_eval_globals()
+ self.context._eval_expression_globals_dict = self.eval_globals
+ for i, rel in enumerate(self.relation_container):
+ index = i + 1
+ # Execute
+ self._execute_relation_and_log_error(rel, self.source, index, context)
- del self.configuration._eval_expression_globals_dict
-
- if self.relation_container.has_errors():
- for error in self.relation_container.get_errors():
- self.logger.error(error)
-
- if self.context:
- self.context.results += results
- return results
- finally:
- relations.unregister()
+ del self.context._eval_expression_globals_dict
+
+ if self.relation_container.has_errors():
+ for error in self.relation_container.get_errors():
+ logging.getLogger('cone.ruleml_relation_container(%s)' % self.source).error(error)
+
+ if self.context:
+ self.context.results += results
+ return results
def get_relation_count(self):
return len(self.relation_container)
+ def get_relations(self):
+ return list(self.relation_container)
+
def _set_builtin_eval_globals(self):
"""
Add built-in attributes into the eval globals dictionary.
"""
- class RuleBuiltinsModule(object):
- pass
-
- builtins = RuleBuiltinsModule()
+ builtins = RuleBuiltinsModule()
builtins.configuration = self.configuration
+ builtins.context = self.context
self.eval_globals['ruleml'] = builtins
-class RuleImplReaderBase(plugin.ReaderBase):
- NAMESPACE = None # Used as a base class, so should have no namespace
+class RuleImplReader(plugin.ReaderBase):
+ NAMESPACE = 'http://www.s60.com/xml/ruleml/3'
+ NAMESPACE_ID = 'ruleml3'
+ ROOT_ELEMENT_NAME = 'ruleml'
FILE_EXTENSIONS = ['ruleml']
def __init__(self, resource_ref, configuration):
self.resource_ref = resource_ref
self.configuration = configuration
- self.logger = logging.getLogger('cone.ruleml(%s)' % self.resource_ref)
@classmethod
def read_impl(cls, resource_ref, configuration, etree):
reader = cls(resource_ref, configuration)
+ rules = reader.parse_rules(resource_ref, etree)
+ eval_globals = reader.parse_eval_globals(etree)
+ lineno = utils.etree.get_lineno(etree)
- # Register relations etc. to the rule engine.
- # Due to unit test issues the relations are not registered
- # in the relations module, but only for the duration of
- # rule parsing and execution
- relations.register()
- try:
- rules = reader.parse_rules(etree)
- eval_globals = reader.parse_eval_globals(etree)
-
+ # Create an ImplContainer to hold each rule as its own
+ # RuleML implementation
+ main_impl = plugin.ImplContainer(resource_ref, configuration)
+ main_impl.lineno = lineno
+
+ for rule in rules:
relation_container = RulemlRelationContainer(
configuration = configuration,
- source = resource_ref,
- rule_list = rules,
+ source = "%s:%d" % (resource_ref, rule.lineno),
+ rule_list = [rule],
eval_globals = eval_globals)
-
- impl = RuleImpl(resource_ref, configuration, relation_container)
- finally:
- relations.unregister()
- return impl
-
-class RuleImplReader1(RuleImplReaderBase):
- NAMESPACE = 'http://www.s60.com/xml/ruleml/1'
+ impl = RuleImpl(resource_ref, configuration, relation_container)
+ impl.lineno = rule.lineno
+ rule.implml = impl
+
+ main_impl.append(impl)
+ return main_impl
- def __init__(self, resource_ref, configuration):
- RuleImplReaderBase.__init__(self, resource_ref, configuration)
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('ruleplugin', 'xsd/ruleml3.xsd')
- def parse_rules(self, etree):
+ def parse_rules(self, ref, etree):
rules = []
for elem in etree.getiterator("{%s}rule" % self.NAMESPACE):
- rules.extend(relations.RelationFactory.get_relations(self.configuration, elem.text))
- return rules
-
- def parse_eval_globals(self, etree):
- return {}
-
-class RuleImplReader2(RuleImplReaderBase):
- NAMESPACE = 'http://www.s60.com/xml/ruleml/2'
-
- def __init__(self, resource_ref, configuration):
- RuleImplReaderBase.__init__(self, resource_ref, configuration)
-
- def parse_rules(self, etree):
- rules = []
- for elem in etree.getiterator("{%s}rule" % self.NAMESPACE):
- rules.extend(relations.RelationFactory.get_relations(self.configuration, self._replace_eval_blocks(elem.text)))
+ lineno = utils.etree.get_lineno(elem)
+ rule_str = self._replace_eval_blocks(elem.text or '')
+ rels = relations.RelationFactory.get_relations(rule_str) or []
+ for rule in rels:
+ rule.ref = ref
+ rule.lineno = lineno
+ rules.append(rule)
return rules
def parse_eval_globals(self, etree):
@@ -214,7 +224,7 @@
text = elem.text.strip()
exec(text, eval_globals)
except Exception, e:
- self.logger.warning('Failed to evaluate eval_globals block, exception: %s' % (e))
+ logging.getLogger('cone.ruleml(%s)' % self.resource_ref).warning('Failed to evaluate eval_globals block, exception: %s' % (e))
return eval_globals
def _read_eval_globals_from_file(self, relative_path, eval_globals):
@@ -228,7 +238,7 @@
text = resource.read()
exec(text.replace('\r', ''), eval_globals)
except Exception, e:
- self.logger.warning('Cannot import eval file: %s. Exception: %s' % (pyfile_path, e))
+ logging.getLogger('cone.ruleml(%s)' % self.resource_ref).warning('Cannot import eval file: %s. Exception: %s' % (pyfile_path, e))
finally:
if resource is not None: resource.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/__init__.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,19 +18,5 @@
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test1/implml/terminalexpression.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test1/implml/terminalexpression.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test1/implml/terminalexpression.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,6 +1,6 @@
-
- True configures EvalTest.StringLenResult = 22
- True configures EvalTest.StringLenResult = {% SOME_VALUE %}
+
+ True configures ${EvalTest.StringLenResult} = 22
+ True configures ${EvalTest.StringLenResult} = {% SOME_VALUE %}SOME_VALUE = 12345
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test2/implml/invalid_python_eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test2/implml/invalid_python_eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test2/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
- True configures EvalTest2.StringResult = {% -> this is invalid python code %}
+
+ True configures ${EvalTest2.StringResult} = {% -> this is invalid python code %}
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test3/implml/invalid_python_eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test3/implml/invalid_python_eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test3/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,5 +1,5 @@
-
- True configures EvalTest3.StringResult = 22
+
+ True configures ${EvalTest3.StringResult} = 22
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test4/implml/invalid_python_eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test4/implml/invalid_python_eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test4/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,5 +1,5 @@
-
- True configures EvalTest4.StringResult = 22
+
+ True configures ${EvalTest4.StringResult} = 22
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test5/implml/invalid_python_eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test5/implml/invalid_python_eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test5/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
- True configures EvalTest5.StringResult = {% 7/0 %}
+
+ True configures ${EvalTest5.StringResult} = {% 7/0 %}
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test6/implml/invalid_python_eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test6/implml/invalid_python_eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/errorruleproject/test6/implml/invalid_python_eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
- True configures EvalTest6.StringResult = Invalid.setting
+
+ True configures ${EvalTest6.StringResult} = ${Invalid.setting}
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/eval.confml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/eval.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/eval.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,6 +1,10 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/testdata.confml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/testdata.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/confml/testdata.confml Tue Aug 10 14:29:28 2010 +0300
@@ -46,6 +46,12 @@
+
+
+
+
+
+ 2
@@ -83,5 +89,11 @@
<ударениÑ>
<ελληνικά>カタカナελληνικά>
ударениÑ>
+
+
+ yeah
+ 3
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/arithmetic.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/arithmetic.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/arithmetic.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,37 +1,37 @@
-
+
- True configures Arithmetic.AdditionResult1 = 2 + 6
- True configures Arithmetic.AdditionResult2 = Arithmetic.Value1 + 6
- True configures Arithmetic.AdditionResult3 = 2 + Arithmetic.Value2
- True configures Arithmetic.AdditionResult4 = Arithmetic.Value1 + Arithmetic.Value2
+ True configures ${Arithmetic.AdditionResult1} = 2 + 6
+ True configures ${Arithmetic.AdditionResult2} = ${Arithmetic.Value1} + 6
+ True configures ${Arithmetic.AdditionResult3} = 2 + ${Arithmetic.Value2}
+ True configures ${Arithmetic.AdditionResult4} = ${Arithmetic.Value1} + ${Arithmetic.Value2}
- True configures Arithmetic.SubtractionResult1 = 2 - 6
- True configures Arithmetic.SubtractionResult2 = Arithmetic.Value1 - 6
- True configures Arithmetic.SubtractionResult3 = 2 - Arithmetic.Value2
- True configures Arithmetic.SubtractionResult4 = Arithmetic.Value1 - Arithmetic.Value2
+ True configures ${Arithmetic.SubtractionResult1} = 2 - 6
+ True configures ${Arithmetic.SubtractionResult2} = ${Arithmetic.Value1} - 6
+ True configures ${Arithmetic.SubtractionResult3} = 2 - ${Arithmetic.Value2}
+ True configures ${Arithmetic.SubtractionResult4} = ${Arithmetic.Value1} - ${Arithmetic.Value2}
- True configures Arithmetic.MultiplicationResult1 = 2 * 6
- True configures Arithmetic.MultiplicationResult2 = Arithmetic.Value1 * 6
- True configures Arithmetic.MultiplicationResult3 = 2 * Arithmetic.Value2
- True configures Arithmetic.MultiplicationResult4 = Arithmetic.Value1 * Arithmetic.Value2
+ True configures ${Arithmetic.MultiplicationResult1} = 2 * 6
+ True configures ${Arithmetic.MultiplicationResult2} = ${Arithmetic.Value1} * 6
+ True configures ${Arithmetic.MultiplicationResult3} = 2 * ${Arithmetic.Value2}
+ True configures ${Arithmetic.MultiplicationResult4} = ${Arithmetic.Value1} * ${Arithmetic.Value2}
- True configures Arithmetic.DivisionResult1 = 6 / 2
- True configures Arithmetic.DivisionResult2 = Arithmetic.Value2 / 4
- True configures Arithmetic.DivisionResult3 = 10 / Arithmetic.Value1
- True configures Arithmetic.DivisionResult4 = Arithmetic.Value2 / Arithmetic.Value1
+ True configures ${Arithmetic.DivisionResult1} = 6 / 2
+ True configures ${Arithmetic.DivisionResult2} = ${Arithmetic.Value2} / 4
+ True configures ${Arithmetic.DivisionResult3} = 10 / ${Arithmetic.Value1}
+ True configures ${Arithmetic.DivisionResult4} = ${Arithmetic.Value2} / ${Arithmetic.Value1}
- True configures Arithmetic.MixedResult1 = (6 / 2 + 3 * 9) - 7
- True configures Arithmetic.MixedResult2 = (6 / 2 + Arithmetic.Value1 * 9) - 7
- True configures Arithmetic.MixedResult3 = (Arithmetic.Value2 / 2 + Arithmetic.Value1 * 9) - 7
- True configures Arithmetic.MixedResult4 = (Arithmetic.Value2 / Arithmetic.Value1 + Arithmetic.Value1 * Arithmetic.Value1) - Arithmetic.Value2
- True configures Arithmetic.MixedResult5 = 4 + 6 / 2 - 3 * 9 + 10 / 5 - 8
+ True configures ${Arithmetic.MixedResult1} = (6 / 2 + 3 * 9) - 7
+ True configures ${Arithmetic.MixedResult2} = (6 / 2 + ${Arithmetic.Value1} * 9) - 7
+ True configures ${Arithmetic.MixedResult3} = (${Arithmetic.Value2} / 2 + ${Arithmetic.Value1} * 9) - 7
+ True configures ${Arithmetic.MixedResult4} = (${Arithmetic.Value2} / ${Arithmetic.Value1} + ${Arithmetic.Value1} * ${Arithmetic.Value1}) - ${Arithmetic.Value2}
+ True configures ${Arithmetic.MixedResult5} = 4 + 6 / 2 - 3 * 9 + 10 / 5 - 8
- True configures Arithmetic.RealResult1 = 5.0 / 2.0
- True configures Arithmetic.RealResult2 = Arithmetic.RealValue1 / 2
- True configures Arithmetic.RealResult3 = 0.25 * Arithmetic.RealValue2
- True configures Arithmetic.RealResult4 = Arithmetic.RealValue1 / 2.0 * Arithmetic.RealValue2
+ True configures ${Arithmetic.RealResult1} = 5.0 / 2.0
+ True configures ${Arithmetic.RealResult2} = ${Arithmetic.RealValue1} / 2
+ True configures ${Arithmetic.RealResult3} = 0.25 * ${Arithmetic.RealValue2}
+ True configures ${Arithmetic.RealResult4} = ${Arithmetic.RealValue1} / 2.0 * ${Arithmetic.RealValue2}
- True configures Arithmetic.RealCalcIntoIntResult = 0.25 * Arithmetic.RealValue1
- True configures Arithmetic.IntCalcIntoRealResult = 3 * Arithmetic.Value1
+ True configures ${Arithmetic.RealCalcIntoIntResult} = 0.25 * ${Arithmetic.RealValue1}
+ True configures ${Arithmetic.IntCalcIntoRealResult} = 3 * ${Arithmetic.Value1}
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/commsdat.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/commsdat.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/commsdat.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
- (APs.AP != []) or (VPN_APs.VPN_AP != []) configures KCRUidCommsDatCreator.KCommsDatCreatorInputFileName = 'test.xml'
+ (${APs.AP} != []) or (${VPN_APs.VPN_AP} != []) configures ${KCRUidCommsDatCreator.KCommsDatCreatorInputFileName} = 'test.xml'
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/comparison_operators.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/comparison_operators.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/comparison_operators.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,20 +1,20 @@
-
- 0 == 0 configures CompOperTest.LiteralsResult1 = true
- 0 != 1 configures CompOperTest.LiteralsResult2 = true
- 1 < 2 configures CompOperTest.LiteralsResult3 = true
- 2 > 1 configures CompOperTest.LiteralsResult4 = true
- 1 <= 1 configures CompOperTest.LiteralsResult5 = true
- 1 <= 2 configures CompOperTest.LiteralsResult6 = true
- 1 >= 1 configures CompOperTest.LiteralsResult7 = true
- 2 >= 1 configures CompOperTest.LiteralsResult8 = true
+
+ 0 == 0 configures ${CompOperTest.LiteralsResult1} = true
+ 0 != 1 configures ${CompOperTest.LiteralsResult2} = true
+ 1 < 2 configures ${CompOperTest.LiteralsResult3} = true
+ 2 > 1 configures ${CompOperTest.LiteralsResult4} = true
+ 1 <= 1 configures ${CompOperTest.LiteralsResult5} = true
+ 1 <= 2 configures ${CompOperTest.LiteralsResult6} = true
+ 1 >= 1 configures ${CompOperTest.LiteralsResult7} = true
+ 2 >= 1 configures ${CompOperTest.LiteralsResult8} = true
- CompOperTest.Zero == CompOperTest.Zero configures CompOperTest.RefsResult1 = true
- CompOperTest.Zero != CompOperTest.One configures CompOperTest.RefsResult2 = true
- CompOperTest.One < CompOperTest.Two configures CompOperTest.RefsResult3 = true
- CompOperTest.Two > CompOperTest.One configures CompOperTest.RefsResult4 = true
- CompOperTest.One <= CompOperTest.One configures CompOperTest.RefsResult5 = true
- CompOperTest.One <= CompOperTest.Two configures CompOperTest.RefsResult6 = true
- CompOperTest.One >= CompOperTest.One configures CompOperTest.RefsResult7 = true
- CompOperTest.Two >= CompOperTest.One configures CompOperTest.RefsResult8 = true
+ ${CompOperTest.Zero} == ${CompOperTest.Zero} configures ${CompOperTest.RefsResult1} = true
+ ${CompOperTest.Zero} != ${CompOperTest.One} configures ${CompOperTest.RefsResult2} = true
+ ${CompOperTest.One} < ${CompOperTest.Two} configures ${CompOperTest.RefsResult3} = true
+ ${CompOperTest.Two} > ${CompOperTest.One} configures ${CompOperTest.RefsResult4} = true
+ ${CompOperTest.One} <= ${CompOperTest.One} configures ${CompOperTest.RefsResult5} = true
+ ${CompOperTest.One} <= ${CompOperTest.Two} configures ${CompOperTest.RefsResult6} = true
+ ${CompOperTest.One} >= ${CompOperTest.One} configures ${CompOperTest.RefsResult7} = true
+ ${CompOperTest.Two} >= ${CompOperTest.One} configures ${CompOperTest.RefsResult8} = true
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/container_with_rules.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/container_with_rules.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/container_with_rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -2,19 +2,24 @@
-
- imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
- True configures StringConcatenationTest.Result1 = "Test " + "test"
- True configures StringConcatenationTest.Result2 = StringConcatenationTest.Value1 + " Literal 2"
+
+ {% dummy_function(${imakerapi.PRODUCT_NAME}) %} configures ${imakerapi.PRODUCT_NAME} = "test product"
+ ${imaker.imagetarget} configures ${imakerapi.outputLocation} = ${imaker.imagetarget}
+ True configures ${StringConcatenationTest.Result1} = "Test " + "test"
+ True configures ${StringConcatenationTest.Result2} = ${StringConcatenationTest.Value1} + " Literal 2"
+
+def dummy_function(ref):
+ return ref
+
-
- True configures StringConcatenationTest.Result3 = "Literal 1 " + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result4 = StringConcatenationTest.Value1 + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result5 = StringConcatenationTest.Value1 + " & " + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result6 = StringConcatenationTest.Value1 + u" € カタカナ"
+
+ True configures ${StringConcatenationTest.Result3} = "Literal 1 " + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result4} = ${StringConcatenationTest.Value1} + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result5} = ${StringConcatenationTest.Value1} + " & " + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result6} = ${StringConcatenationTest.Value1} + u" € カタカナ"
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/eval.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/eval.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/eval.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,20 +1,20 @@

-
- True configures EvalTest.StringLenResult = {% len("faklskjh") %}
- True configures EvalTest.EvalConstantResult = {% SOME_VALUE %}
- True configures EvalTest.EvalFileImport = {% do_something(SOME_VALUE) %}
+
+ True configures ${EvalTest.StringLenResult} = {% len("faklskjh") %}
+ True configures ${EvalTest.EvalConstantResult} = {% SOME_VALUE %}
+ True configures ${EvalTest.EvalFileImport} = {% do_something(SOME_VALUE) %}
- {% ${EvalTest.Bitmask} & 0x1 %} configures EvalTest.Bit0Result = True
- {% ${EvalTest.Bitmask} & 0x2 %} configures EvalTest.Bit1Result = True
- True configures EvalTest.Bit2Result = {%
+ {% ${EvalTest.Bitmask} & 0x1 %} configures ${EvalTest.Bit0Result} = True
+ {% ${EvalTest.Bitmask} & 0x2 %} configures ${EvalTest.Bit1Result} = True
+ True configures ${EvalTest.Bit2Result} = {%
bool(${EvalTest.Bitmask} & 0x4)
%}
- True configures EvalTest.Bit3Result = {% bool(${EvalTest.Bitmask} & 0x8) %}
+ True configures ${EvalTest.Bit3Result} = {% bool(${EvalTest.Bitmask} & 0x8) %}
- True configures EvalTest.FullSequence = {% append_stripped_seq_to_full_seq(
+ True configures ${EvalTest.FullSequence} = {% append_stripped_seq_to_full_seq(
@{EvalTest.StrippedSequence},
@{EvalTest.FullSequence})
%}
@@ -23,10 +23,10 @@
False configures {% @{EvalTest.UnchangedValue}.set_value(54321) %}
- True configures EvalTest.UnicodeResult1 = {% u'100€' %}
- True configures EvalTest.UnicodeResult2 = {% @{ударениÑ.ελληνικά}.get_value() %}
+ True configures ${EvalTest.UnicodeResult1} = {% u'100€' %}
+ True configures ${EvalTest.UnicodeResult2} = {% @{ударениÑ.ελληνικά}.get_value() %}
- True configures EvalTest.EvalBuiltinResult = {% ruleml.configuration.get_name() %}
+ True configures ${EvalTest.EvalBuiltinResult} = {% ruleml.configuration.get_name() %}SOME_VALUE = 12345
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/eval_generation_context.ruleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/eval_generation_context.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,10 @@
+
+
+ True configures ${EvalTest.output} = {% test_get_output_folder() %}
+ True configures ${EvalTest.file} = {% test_add_file_to_output_folder() %}
+
+ SOME_VALUE = 12345
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/filename_rules.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/filename_rules.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/filename_rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,14 +1,14 @@
-
- True configures FilenamejoinTest.Result1 = FilenamejoinTest.String1 filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result2 = "some/content/dir/somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result3 = "some/content/dir/" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result4 = "some\\content\\dir\\somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result5 = "some\\content\\dir\\" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result6 = "Z:\\\\some\\\\content\\\\dir\\\\somefile.csv" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result7 = "Z:\\\\some\\\\content\\\\dir\\\\" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result8 = "somedir" filenamejoin FilenamejoinTest.File1.localPath
- True configures FilenamejoinTest.Result9 = "somedir" filenamejoin "somefile.txt"
- True configures FilenamejoinTest.Result10 = "somedir" filenamejoin "somefile.txt" + ';' + r'Z:\\some\\dir\\' filenamejoin FilenamejoinTest.File1.localPath
- True and FilenamejoinTest.String1==r'Z:\\data\\sound.mp3' and True configures FilenamejoinTest.Result11 = "some" + "dir" filenamejoin "somefile.txt"
+
+ True configures ${FilenamejoinTest.Result1} = ${FilenamejoinTest.String1} filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result2} = "some/content/dir/somefile.csv" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result3} = "some/content/dir/" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result4} = "some\\content\\dir\\somefile.csv" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result5} = "some\\content\\dir\\" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result6} = "Z:\\\\some\\\\content\\\\dir\\\\somefile.csv" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result7} = "Z:\\\\some\\\\content\\\\dir\\\\" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result8} = "somedir" filenamejoin ${FilenamejoinTest.File1.localPath}
+ True configures ${FilenamejoinTest.Result9} = "somedir" filenamejoin "somefile.txt"
+ True configures ${FilenamejoinTest.Result10} = "somedir" filenamejoin "somefile.txt" + ';' + r'Z:\\some\\dir\\' filenamejoin ${FilenamejoinTest.File1.localPath}
+ True and ${FilenamejoinTest.String1}==r'Z:\\data\\sound.mp3' and True configures ${FilenamejoinTest.Result11} = "some" + "dir" filenamejoin "somefile.txt"
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/rules.ruleml
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/rules.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/rules.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,22 +1,27 @@
-
- imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
- mms.imagesize == 'large' configures pd.ref1 = True and pd.ref2 = True
- mms.imagesize == 'small' configures pd.ref1 = False and pd.ref2 = True
- mms.imagesize == 'extrasmall' configures pd.ref1 = False and pd.ref2 = False
- mms.imagesize == 'extralarge' configures pd.ref1 = True and pd.ref2 = False
- imakerapi.outputLocationY == None configures imakerapi.outputLocationY = 'hello'
- operations.minus == 5 configures operations.minus = operations.minus1 - operations.minus2
- operations.minus1 == 25 configures operations.minus1 = operations.minus3 * operations.minus2
- operations.minus4 == 10 configures operations.minus4 = operations.minus4 / operations.minus5
- operations.minus6 == 5 configures operations.minus6 = operations.minus7 + operations.minus8
+
+ {% ${imaker.imagetarget} %} configures ${imakerapi.outputLocation} = ${imaker.imagetarget}
+ ${mms.imagesize} == 'large' configures ${pd.ref1} = True and ${pd.ref2} = True
+ ${mms.imagesize} == 'small' configures ${pd.ref1} = False and ${pd.ref2} = True
+ ${mms.imagesize} == 'extrasmall' configures ${pd.ref1} = False and ${pd.ref2} = False
+ ${mms.imagesize} == 'extralarge' configures ${pd.ref1} = True and ${pd.ref2} = False
+ ${imakerapi.outputLocationY} == None configures ${imakerapi.outputLocationY} = 'hello'
+ ${operations.minus} == 5 configures ${operations.minus} = ${operations.minus1} - ${operations.minus2}
+ ${operations.minus1} == 25 configures ${operations.minus1} = ${operations.minus3} * ${operations.minus2}
+ ${operations.minus4} == 10 configures ${operations.minus4} = ${operations.minus4} / ${operations.minus5}
+ ${operations.minus6} == 5 configures ${operations.minus6} = ${operations.minus7} + ${operations.minus8}
- True configures StringConcatenationTest.Result1 = "Test " + "test"
- True configures StringConcatenationTest.Result2 = StringConcatenationTest.Value1 + " Literal 2"
- True configures StringConcatenationTest.Result3 = "Literal 1 " + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result4 = StringConcatenationTest.Value1 + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result5 = StringConcatenationTest.Value1 + " & " + StringConcatenationTest.Value2
- True configures StringConcatenationTest.Result6 = StringConcatenationTest.Value1 + u" € カタカナ"
+ True configures ${StringConcatenationTest.Result1} = "Test " + "test"
+ True configures ${StringConcatenationTest.Result2} = ${StringConcatenationTest.Value1} + " Literal 2"
+ True configures ${StringConcatenationTest.Result3} = "Literal 1 " + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result4} = ${StringConcatenationTest.Value1} + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result5} = ${StringConcatenationTest.Value1} + " & " + ${StringConcatenationTest.Value2}
+ True configures ${StringConcatenationTest.Result6} = ${StringConcatenationTest.Value1} + u" € カタカナ"
- True configures ударениÑ.ελληνικά = ударениÑ.ελληνικά + u" € カタカナ"
+ True configures ${ударениÑ.ελληνικά} = ${ударениÑ.ελληνικά} + u" € カタカナ"
+
+ True configures ${SequenceTest.Sequence1} = {% [['foo', 1], ['bar', 2], ['baz', 3]] %}
+
+ {% @{Foo.Bar}.value %} configures ${Foo.Baz} = 'gaa'
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/scripts/test_eval_generation_context.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/ruleproject/rules/implml/scripts/test_eval_generation_context.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,34 @@
+#
+# 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:
+#
+
+
+
+def test_get_output_folder():
+ output = ruleml.context.output
+ return output
+
+
+#add file to output folder
+def test_add_file_to_output_folder():
+
+ filename = "output_test.txt"
+ output = ruleml.context.output
+
+ f = open(output + '/' + filename,'w')
+ f.writelines("Test!")
+ f.close()
+
+ return output + '/' + filename
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/runtests.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_eval.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_eval.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_eval.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,8 +20,6 @@
import sys
import re
-import __init__
-
from ruleplugin import ruleml, relations
from cone.public import api, exceptions
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -42,10 +40,10 @@
class MockConfigurationContext(object):
def __init__(self, feature_values):
- self.data = MockObject()
+ self.configuration = MockObject()
default_view = MockObject()
default_view.get_feature = lambda ref: MockFeature(ref, feature_values)
- self.data.get_default_view = lambda: default_view
+ self.configuration.get_default_view = lambda: default_view
self.ref_eval_callback = None
class MockExpression(object):
@@ -85,7 +83,7 @@
class TestReplaceEvalBlocks(unittest.TestCase):
def test_replace_eval_blocks(self):
- replace = ruleml.RuleImplReader2._replace_eval_blocks
+ replace = ruleml.RuleImplReader._replace_eval_blocks
orig = """some.setting configures x = y"""
self.assertEquals(replace(orig), orig)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_parseruleml.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_parseruleml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_parseruleml.py Tue Aug 10 14:29:28 2010 +0300
@@ -28,28 +28,24 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
-
from ruleplugin import ruleml, relations
from cone.public import api, exceptions, utils, plugin
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
ruleml_string = \
'''
-
- imaker.imagetarget configures imakerapi.outputLocation = imaker.imagetarget
- imaker.imagename configures imakerapi.outputLocation = imaker.imagename
+
+ ${imaker.imagetarget} configures ${imakerapi.outputLocation} = ${imaker.imagetarget}
+ ${imaker.imagename} configures ${imakerapi.outputLocation} = ${imaker.imagename}
'''
class TestParseRuleimpl(unittest.TestCase):
- def setUp(self): relations.register()
- def tearDown(self): relations.unregister()
def test_parse_rules(self):
- etree = ElementTree.fromstring(ruleml_string)
- reader = ruleml.RuleImplReader2(None, None)
- rules = reader.parse_rules(etree)
+ etree = utils.etree.fromstring(ruleml_string)
+ reader = ruleml.RuleImplReader(None, None)
+ rules = reader.parse_rules("", etree)
self.assertTrue(isinstance(rules[0],relations.ConfigureRelation))
self.assertTrue(isinstance(rules[1],relations.ConfigureRelation))
self.assertTrue(rules[0].has_ref('imaker.imagetarget'))
@@ -58,8 +54,6 @@
class TestRulemlFromFile(unittest.TestCase):
- def setUp(self): pass
- def tearDown(self): relations.unregister()
def test_create_from_file(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
@@ -67,15 +61,18 @@
ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/rules.ruleml', config)[0]
relation_container = ruleimpl.get_relation_container()
self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
- self.assertEquals(relation_container.get_relation_count(), 17)
-
+ self.assertEquals(relation_container.get_relation_count(), 19)
+ self.assertEquals(len(relation_container.get_relations()), 19)
+ self.assertEquals(relation_container.get_relations()[0].get_refs(),[u'imaker.imagetarget'])
+ self.assertEquals(relation_container.get_relations()[0].implml.ref, 'implml/rules.ruleml')
+
def test_create_from_file_with_common_container(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
config = project.get_configuration('root.confml')
ruleimpl = plugin.ImplFactory.get_impls_from_file('implml/container_with_rules.ruleml', config)[0]
relation_container = ruleimpl.get_relation_container()
self.assertTrue(isinstance(relation_container, plugin.RelationContainer))
- self.assertEquals(relation_container.get_relation_count(), 7)
+ self.assertEquals(relation_container.get_relation_count(), 8)
def test_create_from_file_filename(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_empty_plugin.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_empty_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_empty_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,8 +19,6 @@
import sys
import logging
-import __init__
-
from cone.public import exceptions,plugin,api,container
from cone.storage import filestorage
from ruleplugin import ruleml
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,14 +15,12 @@
#
import unittest
-import os, shutil
-import sys
+import os
import logging
-import __init__
-from cone.public import exceptions,plugin,api,container
-from cone.storage import filestorage
+from cone.public import plugin,api
from ruleplugin import ruleml
+from testautomation.base_testcase import BaseTestCase
# Hardcoded value of testdata folder that must be under the current working dir
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -35,23 +33,68 @@
def tearDown(self):
pass
-class TestRulePluginOnFileStorage(unittest.TestCase):
+class TestRulePluginOnFileStorage(BaseTestCase):
def test_get_impl_container(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules')))
config = project.get_configuration('root.confml')
implcontainer = plugin.get_impl_set(config, 'ruleml$')
impl = implcontainer.get_implementations_by_file('implml/rules.ruleml')[0]
- self.assertEquals(None, impl.get_refs())
+ EXPECTED_REFS = ['imaker.imagetarget',
+ 'mms.imagesize',
+ 'imakerapi.outputLocationY',
+ 'operations.minus',
+ 'operations.minus1',
+ 'operations.minus4',
+ 'operations.minus6',
+ 'Foo.Bar']
+ self.assertEquals(sorted(EXPECTED_REFS), sorted(impl.get_child_refs()))
self.assertEquals([], impl.list_output_files())
- def test_impl_container_execute_pre_rules(self):
+ def test_rules_get_refs(self):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
config = project.get_configuration('root.confml')
implcontainer = plugin.get_impl_set(config, 'ruleml$')
ruleimpl = implcontainer.get_implementations_by_file('implml/container_with_rules.ruleml')[0]
- context = plugin.GenerationContext()
+ self.assertEquals(ruleimpl.get_child_refs(), [u'imakerapi.PRODUCT_NAME',
+ u'imaker.imagetarget'])
+ self.assertEquals(len(ruleimpl.get_outputs()), 8)
+ outputs = [output.name for output in ruleimpl.get_outputs()]
+ self.assertEquals(outputs, [u'imakerapi.PRODUCT_NAME',
+ u'imakerapi.outputLocation',
+ u'StringConcatenationTest.Result1',
+ u'StringConcatenationTest.Result2',
+ u'StringConcatenationTest.Result3',
+ u'StringConcatenationTest.Result4',
+ u'StringConcatenationTest.Result5',
+ u'StringConcatenationTest.Result6'])
+ inputs = []
+ for output in ruleimpl.get_outputs():
+ inputs += output.implementation.get_refs()
+ self.assertEquals(inputs, [u'imakerapi.PRODUCT_NAME',
+ u'imaker.imagetarget'])
+ impls_refs = []
+ for output in ruleimpl.get_outputs():
+ impls_refs.append("%s <= %s" % (output.name, output.implementation.implml.ref))
+ self.assertEquals(impls_refs, [u'imakerapi.PRODUCT_NAME <= implml/container_with_rules.ruleml',
+ u'imakerapi.outputLocation <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result1 <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result2 <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result3 <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result4 <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result5 <= implml/container_with_rules.ruleml',
+ u'StringConcatenationTest.Result6 <= implml/container_with_rules.ruleml'])
+
+
+ def test_impl_container_execute_pre_rules(self):
+
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
+ config = project.get_configuration('root.confml')
+
+ implcontainer = plugin.get_impl_set(config, 'ruleml$')
+ ruleimpl = implcontainer.get_implementations_by_file('implml/container_with_rules.ruleml')[0]
+ context = plugin.GenerationContext(configuration=config)
context.phase = "pre"
ruleimpl.generate(context)
@@ -68,18 +111,51 @@
project.close()
def test_impl_container_execute_rules(self):
- project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "a" ))
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "r" ))
config = project.get_configuration('root.confml')
implcontainer = plugin.get_impl_set(config, 'ruleml$')
- implcontainer.generate()
+ context = plugin.GenerationContext(configuration=config)
+ implcontainer.generate(context)
lastconfig = config.get_last_configuration()
self.assertEquals(lastconfig.get_path(), plugin.AUTOCONFIG_CONFML)
self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_ref(),'outputLocation')
self.assertEquals(lastconfig.get_data('imakerapi.outputLocation').get_value(),'2')
project.close()
+
+ def _prepare_log(self, log_file, level=logging.DEBUG, formatter="%(levelname)s - %(name)s - %(message)s", logger='cone'):
+ FULL_PATH = os.path.join(ROOT_PATH, "temp", log_file)
+ self.remove_if_exists(FULL_PATH)
+ self.create_dir_for_file_path(FULL_PATH)
+ handler = logging.FileHandler(FULL_PATH)
+ handler.setLevel(level)
+ frm = logging.Formatter(formatter)
+ handler.setFormatter(frm)
+ logger = logging.getLogger(logger)
+ logger.addHandler(handler)
+
+ return [FULL_PATH, handler, logger]
+
+ def test_rule_debug_messages(self):
+ log_file, handler, logger = self._prepare_log('debug_msg_test.log')
+ project = None
+ try:
+ project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,'ruleproject/rules'), "r" ))
+ config = project.get_configuration('root.confml')
+
+ implcontainer = plugin.get_impl_set(config, r'rules\.ruleml$')
+ context = plugin.GenerationContext(configuration=config)
+ implcontainer.generate(context)
+
+ self.assert_file_contains(log_file,
+ ["Set imakerapi.outputLocationY = 'hello' from ConfigureRelation(ref='implml/rules.ruleml', lineno=8)",
+ "Set operations.minus = 18 from ConfigureRelation(ref='implml/rules.ruleml', lineno=9)",
+ "Set SequenceTest.Sequence1 = [['foo', 1], ['bar', 2], ['baz', 3]] from ConfigureRelation(ref='implml/rules.ruleml', lineno=23)"])
+ finally:
+ logger.removeHandler(handler)
+ if project: project.close()
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin_errors.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin_errors.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rule_plugin_errors.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,7 +18,6 @@
import os, shutil
import sys
import logging
-import __init__
from cone.public import exceptions,plugin,api,container
from cone.storage import filestorage
@@ -58,9 +57,9 @@
def _execute_rules(self, project_location):
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH, project_location)))
config = project.get_configuration('root.confml')
-
+ context = plugin.GenerationContext(configuration=config)
implcontainer = plugin.get_impl_set(config, r'\.ruleml$')
- implcontainer.get_relation_container().execute()
+ implcontainer.get_relation_container().execute(context)
lastconfig = config.get_last_configuration()
project.close()
@@ -75,9 +74,7 @@
log_file, handler, logger = self._prepare_log('test2.log')
self._execute_rules('errorruleproject/test2')
logger.removeHandler(handler)
- self.assert_file_contains(log_file, "INFO - cone.ruleml - Set u'EvalTest2.StringResult' = None from '-> this is invalid python code'")
self.assert_file_contains(log_file, "WARNING - cone.ruleml - Invalid syntax in eval: -> this is invalid python code")
- self.assert_file_contains(log_file, "ERROR - cone.ruleml_relation_container(implml/invalid_python_eval.ruleml) - '-> this is invalid python code'")
def test_invalid_python_code_eval_globals(self):
log_file, handler, logger = self._prepare_log('test3.log')
@@ -96,7 +93,7 @@
log_file, handler, logger = self._prepare_log('test5.log')
self._execute_rules('errorruleproject/test5')
logger.removeHandler(handler)
-
+
self.assert_file_contains(log_file, "Execution failed for eval: 7/0 : integer division or modulo by zero")
def test_references_non_existent_settings(self):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rules.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rules.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/tests/unittest_rules.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,8 +18,7 @@
import unittest
import os, shutil
import sys
-import __init__
-
+
from ruleplugin import ruleml
from cone.public import api, plugin
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -35,10 +34,29 @@
def _execute_rules(self, impl_filter):
implcontainer = plugin.get_impl_set(self.config, impl_filter)
- context = plugin.GenerationContext()
+ context = plugin.GenerationContext(configuration=self.config)
+ context.output = os.path.join(ROOT_PATH,'temp/output')
+
+ if not os.path.exists(context.output):
+ os.makedirs(context.output)
+
implcontainer.generate(context)
- return context.results
+ return context.generation_output
+ def test_eval_generation_context_access(self):
+ config = self.config
+
+ self._execute_rules(r'^implml/eval_generation_context\.ruleml$')
+ dview = config.get_default_view()
+ self.assertEquals(dview.get_feature("EvalTest.output").value, os.path.join(ROOT_PATH,'temp/output'))
+ self.assertEquals(True, os.path.isfile(dview.get_feature("EvalTest.file").value))
+
+ self.config.close()
+ self.project.close()
+
+ if os.path.exists(os.path.join(ROOT_PATH, 'temp/output')):
+ shutil.rmtree(os.path.join(ROOT_PATH, 'temp/output'))
+
def test_arithmetic_operations(self):
self._execute_rules(r'^implml/arithmetic\.ruleml$')
@@ -128,8 +146,8 @@
config = self.config
self.assert_setting_equals(config, 'EvalTest.FullSequence',
- [['Full 1', '10', '1.5', 'true'],
- ['Full 2', '20', '2.5', 'false']])
+ [['Full 1', 10, 1.5, True],
+ ['Full 2', 20, 2.5, False]])
self._execute_rules(r'^implml/eval\.ruleml$')
@@ -144,10 +162,10 @@
self.assert_setting_equals(config, 'EvalTest.Bit2Result', False)
self.assert_setting_equals(config, 'EvalTest.Bit3Result', True)
self.assert_setting_equals(config, 'EvalTest.FullSequence',
- [['Full 1', '10', '1.5', 'true'],
- ['Full 2', '20', '2.5', 'false'],
- ['Stripped 1', '1', '0.1', 'false'],
- ['Stripped 2', '2', '0.1', 'false']])
+ [['Full 1', 10, 1.5, True],
+ ['Full 2', 20, 2.5, False],
+ ['Stripped 1', 1, 0.1, False],
+ ['Stripped 2', 2, 0.1, False]])
self.assert_setting_equals(config, 'EvalTest.EvalBuiltinResult', 'ruleml_test_config')
def assert_setting_equals(self, config, setting, expected_value, msg=None):
@@ -159,28 +177,21 @@
def test_rule_execution_results(self):
results = self._execute_rules(r'^implml/rules\.ruleml$')
- def r(index, input_refs, affected_refs):
- return plugin.RelationExecutionResult(index = index,
- source = 'implml/rules.ruleml',
- input_refs = input_refs,
- affected_refs = affected_refs)
- expected = [
- r(1, ['imaker.imagetarget'], ['imakerapi.outputLocation']),
- r(6, ['imakerapi.outputLocationY'], ['imakerapi.outputLocationY']),
- r(7, ['operations.minus'], ['operations.minus']),
- r(8, ['operations.minus1'], ['operations.minus1']),
- r(9, ['operations.minus4'], ['operations.minus4']),
- r(10, ['operations.minus6'], ['operations.minus6']),
- r(11, [], ['StringConcatenationTest.Result1']),
- r(12, [], ['StringConcatenationTest.Result2']),
- r(13, [], ['StringConcatenationTest.Result3']),
- r(14, [], ['StringConcatenationTest.Result4']),
- r(15, [], ['StringConcatenationTest.Result5']),
- r(16, [], ['StringConcatenationTest.Result6']),
- r(17, [], [u'ударениÑ.ελληνικά']),
- ]
-
- self.assertEquals(results, expected)
+ outputs = [(output.name, output.implementation.get_refs()) for output in results if output.type == 'ref']
+ self.assertEquals(outputs, [(u'imakerapi.outputLocation', [u'imaker.imagetarget']),
+ (u'imakerapi.outputLocationY', [u'imakerapi.outputLocationY']),
+ (u'operations.minus', [u'operations.minus']),
+ (u'operations.minus1', [u'operations.minus1']),
+ (u'operations.minus4', [u'operations.minus4']),
+ (u'operations.minus6', [u'operations.minus6']),
+ (u'StringConcatenationTest.Result1', []),
+ (u'StringConcatenationTest.Result2', []),
+ (u'StringConcatenationTest.Result3', []),
+ (u'StringConcatenationTest.Result4', []),
+ (u'StringConcatenationTest.Result5', []),
+ (u'StringConcatenationTest.Result6', []),
+ (u'ударениÑ.ελληνικά', []),
+ (u'SequenceTest.Sequence1', [])])
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/xsd/ruleml3.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/xsd/ruleml3.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ RuleML v3 implementation for specifying rules to execute.
+
+
+
+
+
+
+
+ The rule element specifies a single rule to execute.
+
+
+ For example:
+ <rule>${MyFeature.MySetting1} == 'test' configures ${MyFeature.MySetting2} = '1'</rule>
+ This would cause the value '1' to be assigned to the setting 'MyFeature.MySetting2'
+ if the value of the setting 'MyFeature.MySetting1' is 'test'.
+
+
+
+ Arbitrary Python code can also be executed in the rule by enclosing the eval block
+ with {% %}. For example:
+ <rule>True configures ${MyFeature.MySetting} = {% get_some_value() %}</rule>
+ This would cause the value got from evaluating the Python function call
+ get_some_value() to be assigned to the setting 'MyFeature.MySetting'.
+
+
+
+ Any settings referenced inside an eval block must be enclosed with ${ }
+ to differentiate them from the Python code. For example:
+ <rule>True configures ${MyFeature.MySetting} = {% get_some_value(${MyFeature.MySetting1}) %}</rule>
+ This would cause the value of the setting 'MyFeature.MySetting1' to be passed as a
+ parameter to the function call.
+ The actual feature object handled by ConE can be accessed by enclosing the setting
+ reference with @{ }.
+
+
+
+ Any functions or variables (like get_some_value() in the above examples) need
+ to be defined using eval_globals elements inside the ruleml element.
+
+ ]]>
+
+
+
+
+
+
+ An eval_globals block can be used to add Python variables
+ or functions to the evaluation context of the rules contained
+ within the current ruleml implementation. The Python code can be contained
+ either directly inside the XML element or inside a file pointed by the
+ 'file' attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Path to the file containing the Python code of the eval_globals element.
+ Should be a path relative to the current implementation file.
+ Specifying the 'file' attribute causes the text content of the eval_globals
+ element to be ignored.
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeRulePlugin/setup.py
--- a/configurationengine/source/plugins/common/ConeRulePlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "coneruleplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'ruleplugin': ['xsd/*.xsd']},
test_suite = "ruleplugin.tests.collect_suite",
# metadata for upload to PyPI
@@ -34,6 +35,5 @@
zip_safe = True,
# entrypoint info
- entry_points={'cone.plugins.implmlreaders': ['ruleml_1 = ruleplugin.ruleml:RuleImplReader1',
- 'ruleml_2 = ruleplugin.ruleml:RuleImplReader2']}
+ entry_points={'cone.plugins.implmlreaders': ['ruleml_3 = ruleplugin.ruleml:RuleImplReader']}
)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/setup.py
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conetemplateplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'templatemlplugin': ['xsd/*.xsd']},
test_suite = "plugintemplate.tests.collect_suite",
# metadata for upload to PyPI
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/templatemlplugin.py
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/templatemlplugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/templatemlplugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -19,11 +19,10 @@
import re
import os
-import sys
import logging
import codecs
-import xml.parsers.expat
-from jinja2 import Environment, PackageLoader, FileSystemLoader, Template, DictLoader
+import pkg_resources
+from jinja2 import Environment, DictLoader
import traceback
try:
from cElementTree import ElementTree
@@ -47,10 +46,8 @@
except ImportError:
from xml.etree import ElementInclude
-import __init__
-from cone.public import exceptions,plugin,utils,api
-from cone.confml import persistentconfml
+from cone.public import exceptions,plugin,utils
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -62,8 +59,7 @@
Implementation class of template plugin.
"""
- IMPL_TYPE_ID = "templateml"
-
+ IMPL_TYPE_ID = "templateml"
def __init__(self,ref,configuration, reader=None):
"""
@@ -75,24 +71,35 @@
self.reader = reader
if self.reader and self.reader.tags:
self.set_tags(self.reader.tags)
+
+ def __getstate__(self):
+ state = super(TemplatemlImpl, self).__getstate__()
+ state['reader'] = self.reader
+ return state
- def get_context(self):
- if TemplatemlImpl.context == None:
- TemplatemlImpl.context = self.create_dict()
-
- return TemplatemlImpl.context
+ def get_context(self, generation_context):
+ ddict = generation_context.impl_data_dict
+ if ddict.get('templateml_context', None) is None:
+ ddict['templateml_context'] = self.create_dict()
+ return ddict['templateml_context']
def generate(self, context=None):
"""
Generate the given implementation.
"""
-
- self.create_output()
+ self.context = context
+ self.logger.debug('Generating from %s:%s' % (self.ref, self.lineno))
+ self.create_output(context)
return
- def create_output(self, layers=None):
- generator = Generator(self.reader.outputs, self.reader.filters, self.get_context(), self.configuration)
- generator.generate(self.output, self.ref)
+ def create_output(self, generation_context):
+ templateml_context = self.get_context(generation_context)
+ templateml_context['gen_context'] = generation_context
+ if not generation_context.configuration:
+ generation_context.configuration = self.configuration
+ self.reader.expand_output_refs_by_default_view()
+ generator = Generator(self.reader.outputs, self.reader.filters, templateml_context, self)
+ generator.generate(generation_context, self.ref)
return
def get_refs(self):
@@ -100,6 +107,22 @@
for output in self.reader.outputs:
template = output.template.template
refs.extend(self._extract_refs_from_template(template))
+ refs_oa = self._extract_refs_from_output_attribs(output)
+ for r in refs_oa:
+ if refs.count(r) < 1:
+ refs.append(r)
+ return refs
+
+ def _extract_refs_from_output_attribs(self, output):
+ refs = []
+ pattern = re.compile(r'\$\{(.*)\}', re.UNICODE)
+ for key, value in vars(output).iteritems():
+ m = pattern.search(str(value))
+ if m:
+ ref = m.group(1)
+ refs.append(ref)
+ if key == 'ref':
+ refs.append(value)
return refs
@classmethod
@@ -132,20 +155,19 @@
for output in self.reader.outputs:
if re.search("feat_list.*", output.template.template) != None:
return True
-
- refs_in_templates = self.get_refs()
-
- for ref in refs:
- if ref in refs_in_templates:
- return True
- return False
+ return plugin.uses_ref(refs, self.get_refs())
def list_output_files(self):
""" Return a list of output files as an array. """
result = []
for output in self.reader.outputs:
- result.append(os.path.normpath(os.path.join(self.output, output.path, output.filename)))
+ filename = ""
+ if output.fearef != None:
+ filename = self.configuration.get_default_view().get_feature(output.fearef).value
+ else:
+ filename = output.filename
+ result.append(os.path.normpath(os.path.join(self.output, output.path, filename)))
return result
def create_dict(self):
@@ -158,7 +180,7 @@
if self.configuration:
dview = self.configuration.get_default_view()
feat_list = []
- feat_tree = {}
+ feat_tree = FeatureDictProxy(None)
def add_feature(feature, feature_dict):
fea_dict = FeatureDictProxy(feature)
@@ -202,7 +224,10 @@
Parses a single templateml file
"""
NAMESPACE = 'http://www.s60.com/xml/templateml/1'
+ NAMESPACE_ID = 'templateml'
+ ROOT_ELEMENT_NAME = 'templateml'
FILE_EXTENSIONS = ['templateml']
+ NEWLINE_WIN_PARSE_OPTIONS = ['win', 'windows', 'dos', 'symbian', 'symbianos', 'cr+lf', 'crlf']
def __init__(self, resource_ref=None, configuration=None):
self.desc = None
@@ -220,6 +245,10 @@
reader.from_elementtree(etree)
return TemplatemlImpl(resource_ref, configuration, reader)
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('templatemlplugin', 'xsd/templateml.xsd')
+
def fromstring(self, xml_string):
etree = ElementTree.fromstring(xml_string)
self.from_elementtree(etree)
@@ -289,6 +318,7 @@
logging.getLogger('cone.templateml').warning("In template element file attribute and text defined. Using template found from file attribute.")
template_text = _read_relative_file(self.configuration, file, self.resource_ref)
tempfile.set_template(template_text)
+
return tempfile
def parse_outputs(self, etree):
@@ -297,51 +327,73 @@
for output_elem in output_elems:
if output_elem != None:
outputfile = OutputFile()
+ outputfile.set_output_elem(output_elem)
if output_elem.get('encoding') != None:
encoding = output_elem.get('encoding')
- # Check the encoding
- try:
- codecs.lookup(encoding)
- except LookupError:
- raise exceptions.ParseError("Invalid output encoding: %s" % encoding)
-
- if self.configuration != None:
- encoding = utils.expand_refs_by_default_view(encoding, self.configuration.get_default_view())
outputfile.set_encoding(encoding)
if output_elem.get('file') != None:
file = output_elem.get('file')
-
- if self.configuration != None:
- file = utils.expand_refs_by_default_view(file, self.configuration.get_default_view())
outputfile.set_filename(file)
if output_elem.get('dir') != None:
dir = output_elem.get('dir')
- if self.configuration != None:
- dir = utils.expand_refs_by_default_view(dir, self.configuration.get_default_view())
outputfile.set_path(dir)
if output_elem.get('ref'):
# Fetch the output value from a configuration reference
- fea = self.configuration.get_default_view().get_feature(output_elem.get('ref'))
- outputfile.set_filename(fea.value)
+ outputfile.set_fearef(output_elem.get('ref'))
if output_elem.get('bom'):
- outputfile.bom = output_elem.get('bom').lower() in ('1', 'true', 't', 'yes', 'y')
+ outputfile.set_bom(output_elem.get('bom'))
+ if output_elem.get('newline', ''):
+ outputfile.set_newline(output_elem.get('newline', ''))
+
outputfile.set_template(self.parse_template(output_elem))
outputfile.set_filters(self.parse_filters(output_elem))
outputs.append(outputfile)
+
return outputs
+ def expand_output_refs_by_default_view(self):
+ for output in self.outputs:
+ if output.encoding:
+ if self.configuration != None:
+ output.set_encoding(utils.expand_refs_by_default_view(output.encoding, self.configuration.get_default_view()))
+ try:
+ codecs.lookup(output.encoding)
+ except LookupError:
+ raise exceptions.ParseError("Invalid output encoding: %s" % output.encoding)
+ if output.filename:
+ if self.configuration != None:
+ output.set_filename(utils.expand_refs_by_default_view(output.filename, self.configuration.get_default_view()))
+ if output.path:
+ if self.configuration != None:
+ output.set_path(utils.expand_refs_by_default_view(output.path, self.configuration.get_default_view()))
+ if output.newline:
+ newline = output.newline
+ if self.configuration != None:
+ newline = utils.expand_refs_by_default_view(output.newline, self.configuration.get_default_view())
+ if newline.lower() in self.NEWLINE_WIN_PARSE_OPTIONS:
+ output.set_newline(OutputFile.NEWLINE_WIN)
+ if output.bom:
+ bom = output.bom
+ if self.configuration != None:
+ bom = utils.expand_refs_by_default_view(output.bom, self.configuration.get_default_view())
+ output.bom = bom.lower() in ('1', 'true', 't', 'yes', 'y')
+ if output.fearef:
+ if self.configuration != None:
+ fea = self.configuration.get_default_view().get_feature(output.fearef)
+ output.set_filename(fea.value)
+
class Generator(object):
"""
Class that generates
"""
- def __init__(self, outputs, filters, context, configuration=None):
+ def __init__(self, outputs, filters, context, implementation=None):
self.outputs = outputs
self.filters = filters
self.context = context
- self.configuration = configuration
+ self.implementation = implementation
- def generate(self, output_path, ref):
+ def generate(self, generation_context, ref):
"""
Generates output based on templates
"""
@@ -349,35 +401,37 @@
for output in self.outputs:
try:
- logging.getLogger('cone.templateml').debug(output)
- out_path = os.path.abspath(os.path.join(output_path, output.path))
- if out_path != '':
- if not os.path.exists(out_path):
- os.makedirs(out_path)
+ out_path = output.path
+ out_filepath = os.path.join(out_path, output.filename)
+ logging.getLogger('cone.templateml').debug("Output file '%s', encoding '%s'" % (out_filepath, output.encoding))
- out_file = open(os.path.join(out_path, output.filename), 'wb')
+ out_file = generation_context.create_file(out_filepath, implementation=self.implementation)
if output.template.path:
- output.template.template = _read_relative_file(self.configuration, output.template.path, ref)
+ output.template.template = _read_relative_file(generation_context.configuration, output.template.path, ref)
dict_loader = DictLoader({'template': output.template.template})
- env = Environment(loader=dict_loader)
+
+ if output.newline == OutputFile.NEWLINE_WIN:
+ env = Environment(loader=dict_loader, newline_sequence='\r\n')
+ else:
+ env = Environment(loader=dict_loader)
# Common filters
for filter in self.filters:
if filter.path:
- filter.code = _read_relative_file(self.configuration, filter.path, ref)
+ filter.code = _read_relative_file(generation_context.configuration, filter.path, ref)
if not filter.code:
logging.getLogger('cone.templateml').warning("Skipping empty filter definition.")
else:
- env.filters[str(filter.name)] = eval(filter.code)
+ env.filters[str(filter.name)] = eval(filter.code.replace('\r', ''))
# Output file specific filters
for filter in output.filters:
if filter.path:
- filter.code = _read_relative_file(self.configuration, filter.path, ref)
+ filter.code = _read_relative_file(generation_context.configuration, filter.path, ref)
if not filter.code:
logging.getLogger('cone.templateml').warning("Skipping empty filter definition.")
@@ -391,7 +445,9 @@
out_file.close()
except Exception, e:
- logging.getLogger('cone.templateml').error('Failed to generate template: %s %s\n%s' % (type(e), e, traceback.format_exc()) )
+ utils.log_exception(
+ logging.getLogger('cone.templateml'),
+ '%r: Failed to generate output: %s: %s' % (self.implementation, type(e).__name__, e))
else:
logging.getLogger('cone.templateml').info('No (valid) templates found.')
@@ -426,6 +482,9 @@
class OutputFile(object):
+ NEWLINE_UNIX = "unix"
+ NEWLINE_WIN = "win"
+
def __init__(self):
self.filename = ''
self.path = ''
@@ -433,6 +492,12 @@
self.template = TempFile()
self.filters = []
self.bom = None
+ self.newline = self.NEWLINE_UNIX
+ self.fearef = None
+ self.output_elem = None
+
+ def set_newline(self, newline):
+ self.newline = newline
def set_filename(self, filename):
self.filename = filename
@@ -447,14 +512,24 @@
self.template = template
def add_filter(self, filter):
- self.filters.append(filters)
+ self.filters.append(filter)
def set_filters(self, filters):
self.filters = filters
+ def set_bom(self, bom):
+ self.bom = bom
+
+ def set_fearef(self, ref):
+ self.fearef = ref
+
+ def set_output_elem(self, output_elem):
+ self.output_elem = output_elem
+
def __eq__(self, other):
- if (self.template == other.template and self.encoding == other.encoding and self.path == other.path and self.filename == other.filename and self.filters == other.filters):
- return True
+ if other:
+ if (self.template == other.template and self.newline == other.newline and self.encoding == other.encoding and self.path == other.path and self.filename == other.filename and self.filters == other.filters):
+ return True
return False
def __repr__(self):
@@ -483,16 +558,13 @@
self.filters.append(Filter(name, code))
def __eq__(self, other):
- if self.template == other.template and self.filters == other.filters and self.extensions == other.extensions and self.path == other.path:
- return True
+ if other:
+ if self.template == other.template and self.filters == other.filters and self.extensions == other.extensions and self.path == other.path:
+ return True
return False
+
class Filter(object):
- def __init__(self, name, code):
- self.name = name
- self.code = code
- self.path = None
-
def __init__(self):
self.name = None
self.code = None
@@ -522,14 +594,15 @@
self._children = {}
def _get_dict(self):
- result = {
- '_name' : self._feature.name,
- '_namespace' : self._feature.namespace,
- '_value' : self._feature.get_value(),
- '_fqr' : self._feature.fqr,
- '_type' : self._feature.type}
- for ref, obj in self._children.iteritems():
- result[ref] = obj
+ result = {}
+ if self._feature is not None:
+ result.update({
+ '_name' : self._feature.name,
+ '_namespace' : self._feature.namespace,
+ '_value' : self._feature.get_value(),
+ '_fqr' : self._feature.fqr,
+ '_type' : self._feature.type})
+ result.update(self._children)
return result
def items(self):
@@ -539,12 +612,21 @@
return self._get_dict().iteritems()
def __getitem__(self, name):
- if name == '_name': return self._feature.name
- elif name == '_namespace': return self._feature.namespace
- elif name == '_value': return self._feature.get_value()
- elif name == '_fqr': return self._feature.fqr
- elif name == '_type': return self._feature.type
- else: return self._children[name]
+ if self._feature is not None:
+ if name == '_name': return self._feature.name
+ elif name == '_namespace': return self._feature.namespace
+ elif name == '_value': return self._feature.get_value()
+ elif name == '_fqr': return self._feature.fqr
+ elif name == '_type': return self._feature.type
+
+ try:
+ return self._children[name]
+ except KeyError:
+ if self._feature:
+ msg = "Feature '%s.%s' not found" % (self._feature.fqr, name)
+ else:
+ msg = "Feature '%s' not found" % name
+ raise exceptions.NotFound(msg)
def __setitem__(self, name, value):
self._children[name] = value
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/__init__.py
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,19 +18,5 @@
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_list.txt
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_list.txt Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_list.txt Tue Aug 10 14:29:28 2010 +0300
@@ -45,13 +45,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature1',
'_type': 'sequence',
- '_value': [[['seq/file1.txt', None], 'false', 'item 1']],
+ '_value': [[['seq/file1.txt', None], False, 'item 1']],
'BooleanSubSetting': {
'_fqr': 'Feature1.SequenceSetting.BooleanSubSetting',
'_name': 'Boolean sub-setting',
'_namespace': 'Feature1.SequenceSetting',
'_type': 'boolean',
- '_value': ['false'],
+ '_value': [False],
},
'FileSubSetting': {
'_fqr': 'Feature1.SequenceSetting.FileSubSetting',
@@ -151,13 +151,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature1',
'_type': 'sequence',
- '_value': [[['seq/file1.txt', None], 'false', 'item 1']],
+ '_value': [[['seq/file1.txt', None], False, 'item 1']],
'BooleanSubSetting': {
'_fqr': 'Feature1.SequenceSetting.BooleanSubSetting',
'_name': 'Boolean sub-setting',
'_namespace': 'Feature1.SequenceSetting',
'_type': 'boolean',
- '_value': ['false'],
+ '_value': [False],
},
'FileSubSetting': {
'_fqr': 'Feature1.SequenceSetting.FileSubSetting',
@@ -228,7 +228,7 @@
'_name': 'Boolean sub-setting',
'_namespace': 'Feature1.SequenceSetting',
'_type': 'boolean',
- '_value': ['false'],
+ '_value': [False],
},
{
'_fqr': 'Feature1.SequenceSetting.StringSubSetting',
@@ -248,13 +248,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature2',
'_type': 'sequence',
- '_value': [['1', 'seq1 2 item 1']],
+ '_value': [[1, 'seq1 2 item 1']],
'IntSubSetting': {
'_fqr': 'Feature2.SequenceSetting.IntSubSetting',
'_name': 'Int sub-setting',
'_namespace': 'Feature2.SequenceSetting',
'_type': 'int',
- '_value': ['1'],
+ '_value': [1],
},
'StringSubSetting': {
'_fqr': 'Feature2.SequenceSetting.StringSubSetting',
@@ -284,13 +284,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature2',
'_type': 'sequence',
- '_value': [['1', 'seq1 2 item 1']],
+ '_value': [[1, 'seq1 2 item 1']],
'IntSubSetting': {
'_fqr': 'Feature2.SequenceSetting.IntSubSetting',
'_name': 'Int sub-setting',
'_namespace': 'Feature2.SequenceSetting',
'_type': 'int',
- '_value': ['1'],
+ '_value': [1],
},
'StringSubSetting': {
'_fqr': 'Feature2.SequenceSetting.StringSubSetting',
@@ -305,7 +305,7 @@
'_name': 'Int sub-setting',
'_namespace': 'Feature2.SequenceSetting',
'_type': 'int',
- '_value': ['1'],
+ '_value': [1],
},
{
'_fqr': 'Feature2.SequenceSetting.StringSubSetting',
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_tree.txt
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_tree.txt Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/create_dict_test/expected_tree.txt Tue Aug 10 14:29:28 2010 +0300
@@ -45,13 +45,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature1',
'_type': 'sequence',
- '_value': [[['seq/file1.txt', None], 'false', 'item 1']],
+ '_value': [[['seq/file1.txt', None], False, 'item 1']],
'BooleanSubSetting': {
'_fqr': 'Feature1.SequenceSetting.BooleanSubSetting',
'_name': 'Boolean sub-setting',
'_namespace': 'Feature1.SequenceSetting',
'_type': 'boolean',
- '_value': ['false'],
+ '_value': [False],
},
'FileSubSetting': {
'_fqr': 'Feature1.SequenceSetting.FileSubSetting',
@@ -101,13 +101,13 @@
'_name': 'Sequence setting',
'_namespace': 'Feature2',
'_type': 'sequence',
- '_value': [['1', 'seq1 2 item 1']],
+ '_value': [[1, 'seq1 2 item 1']],
'IntSubSetting': {
'_fqr': 'Feature2.SequenceSetting.IntSubSetting',
'_name': 'Int sub-setting',
'_namespace': 'Feature2.SequenceSetting',
'_type': 'int',
- '_value': ['1'],
+ '_value': [1],
},
'StringSubSetting': {
'_fqr': 'Feature2.SequenceSetting.StringSubSetting',
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/access_context.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/access_context.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+ Tags: {{ gen_context.tags }}
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/feat_tree_iteration_test.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/feat_tree_iteration_test.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,14 @@
+
+
+
+
+{% for key, feature in feat_tree.Feature1|dictsort -%}
+{%- if not key.startswith('_') -%}
+{%- if feature._value -%}
+{{ feature._name }} = {{ feature._value }}
+{% endif -%}
+{% endif -%}
+{% endfor -%}
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/file1.templateml
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/file1.templateml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/file1.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -2,11 +2,11 @@
Description field text
-
+
ABC kissa kävelee
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/invalid_ref.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/invalid_ref.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,12 @@
+
+
+
+ {{ feat_tree.Foo.Bar.Baz._value }}
+
+
+ {{ feat_tree.Feature1.Nonexistent._value }}
+
+
+ {{ feat_tree.Feature1.SequenceSetting.Nonexistent._value }}
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/newline.templateml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/project/Layer1/implml/newline.templateml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,14 @@
+
+
+
+line1
+line2
+
+
+
+
+line1
+line2
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/runtests.py
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/unittest_templatemlplugin.py
--- a/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/unittest_templatemlplugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/tests/unittest_templatemlplugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,8 @@
# Description:
#
-import unittest, os, shutil, sys
+import unittest, os, sys
+import logging
try:
from cElementTree import ElementTree, ElementInclude
@@ -28,9 +29,7 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
from templatemlplugin import templatemlplugin
-from types import NoneType
from testautomation.base_testcase import BaseTestCase
from testautomation.utils import hex_to_bindata
@@ -77,10 +76,14 @@
"" \
""
-TEMPML1 = "" \
+TEMPML1 = "" \
"ABCDF" \
""
+TEMPML1_LINUX = "" \
+ "ABCDF" \
+ ""
+
TEMPML2 = "" \
"" \
"include AABBCC" \
@@ -101,13 +104,9 @@
def impl_from_resource(resource_ref, configuration):
- doc_root = plugin.ReaderBase._read_xml_doc_from_resource(resource_ref, configuration)
- readers = { templateml.TemplatemlImplReader.NAMESPACE: templateml.TemplatemlImplReader }
- ns = utils.xml.split_tag_namespace(doc_root.tag)[0]
- if ns in readers:
- return readers[ns].read_impl(resource_ref, configuration, doc_root)
- else:
- return None
+ impls = plugin.ImplFactory.get_impls_from_file(resource_ref, configuration)
+ assert len(impls) == 1
+ return impls[0]
class TestTemplatemlPlugin(BaseTestCase):
def setUp(self):
@@ -130,23 +129,24 @@
impls.output = self.output
impl_list = impls.get_implementations_by_file(resource_ref)
self.assertEquals(1, len(impl_list))
- return impl_list[0]
+ return (configuration,impl_list[0])
def test_parse_desc(self):
- impl = self.load_impl('Layer1/implml/file1.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file1.templateml')
self.assertEqual("Description field text", impl.reader.desc)
def test_parse_output_with_file_ref(self):
- impl = self.load_impl('Layer1/implml/output_with_ref.templateml')
- self.assertEquals(impl.list_output_files(), [os.path.normpath('output/confmlref_filename.txt')])
+ (config,impl) = self.load_impl('Layer1/implml/output_with_ref.templateml')
+ self.assertEquals(impl.list_output_files(), [os.path.normpath('confmlref_filename.txt')])
def test_parse_outputs(self):
- impl = self.load_impl('Layer1/implml/file1.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file1.templateml')
outputs = []
output1 = templatemlplugin.OutputFile()
output1.set_encoding("UTF-16")
output1.set_filename("test.txt")
output1.set_path('')
+ output1.set_newline('unix')
temp1 = templatemlplugin.TempFile()
temp1.set_template(u'ABC kissa k\xe4velee')
output1.set_template(temp1)
@@ -156,6 +156,7 @@
output2.set_encoding("UTF-16")
output2.set_filename("test2.txt")
output2.set_path("output")
+ output2.set_newline('win')
temp2 = templatemlplugin.TempFile()
temp2.set_template('AABBCC')
output2.set_template(temp2)
@@ -175,6 +176,7 @@
self.assertEqual(outputs[0].encoding, impl.reader.outputs[0].encoding)
self.assertEqual(outputs[0].filename, impl.reader.outputs[0].filename)
self.assertEqual(outputs[0].path, impl.reader.outputs[0].path)
+ self.assertEqual(outputs[0].newline, impl.reader.outputs[0].newline)
self.assertEqual(outputs[0].template.template, impl.reader.outputs[0].template.template)
self.assertEqual(outputs[0].template.extensions, impl.reader.outputs[0].template.extensions)
self.assertEqual(outputs[0].template.filters, impl.reader.outputs[0].template.filters)
@@ -184,6 +186,7 @@
self.assertEqual(outputs[1].encoding, impl.reader.outputs[1].encoding)
self.assertEqual(outputs[1].filename, impl.reader.outputs[1].filename)
self.assertEqual(outputs[1].path, impl.reader.outputs[1].path)
+ self.assertEqual(outputs[1].newline, impl.reader.outputs[1].newline)
#self.assertEqual(outputs[1].template.template, impl.reader.outputs[1].template.template)
self.assertEqual(outputs[1].template.extensions, impl.reader.outputs[1].template.extensions)
self.assertEqual(outputs[1].template.filters, impl.reader.outputs[1].template.filters)
@@ -265,7 +268,7 @@
self.assertEqual(filters1[0].code, filter2.code)
self.assertEqual(filters1[0], filter2)
- def test_parse_template_filter(self):
+ def test_parse_template_filter_2(self):
class DummyConfiguration(object):
def get_resource(self, ref):
class DummyResource(object):
@@ -299,9 +302,10 @@
self.remove_if_exists(os.path.normpath("output/output/test.txt"))
- impl = self.load_impl('Layer1/implml/file2.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file2.templateml')
#impl.context = {'name' : 'some value'}
- impl.generate()
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/output/test.txt")))
result_file = None
@@ -312,12 +316,41 @@
finally:
if result_file != None: result_file.close()
+ def test_simple_generate_newline(self):
+
+ self.remove_if_exists(os.path.normpath("output/output/test_newline_win.txt"))
+ self.remove_if_exists(os.path.normpath("output/output/test_newline_unix.txt"))
+
+ (config,impl) = self.load_impl('Layer1/implml/newline.templateml')
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
+
+ self.assertTrue(os.path.exists(os.path.normpath("output/output/test_newline_win.txt")))
+ self.assertTrue(os.path.exists(os.path.normpath("output/output/test_newline_unix.txt")))
+
+ result_file_win = None
+ try:
+ result_file_win = open(os.path.normpath("output/output/test_newline_win.txt"),'rb')
+ line = result_file_win.read()
+ self.assertEquals(line, "line1\r\nline2")
+ finally:
+ if result_file_win != None: result_file_win.close()
+
+ result_file_unix = None
+ try:
+ result_file_unix = open(os.path.normpath("output/output/test_newline_unix.txt"), 'rb')
+ line = result_file_unix.read()
+ self.assertEquals(line, "line1\nline2")
+ finally:
+ if result_file_unix != None: result_file_unix.close()
+
def test_simple_generate_prj3(self):
self.remove_if_exists(os.path.normpath("output/output/test3.txt"))
- impl = self.load_impl('Layer1/implml/file3.templateml')
- impl.generate()
+ (config,impl) = self.load_impl('Layer1/implml/file3.templateml')
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/output/test3.txt")))
result_file = None
@@ -328,6 +361,7 @@
finally:
if result_file != None: result_file.close()
+
def test_simple_generate_prj4_with_filters(self):
self.remove_if_exists(os.path.normpath("output/output/test4a.txt"))
@@ -335,9 +369,10 @@
self.remove_if_exists(os.path.normpath("output/output/test4c.txt"))
self.remove_if_exists(os.path.normpath("output/output/test4d.txt"))
- impl = self.load_impl('Layer1/implml/file4.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file4.templateml')
#impl.context = {'name' : 'John Doe'}
- impl.generate()
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/output/test4a.txt")))
self.assertTrue(os.path.exists(os.path.normpath("output/output/test4b.txt")))
@@ -389,9 +424,9 @@
self.remove_if_exists(os.path.normpath("output/output/test_ext_temp_file.txt"))
- impl = self.load_impl('Layer1/implml/external_tempfile.templateml')
-
- impl.generate()
+ (config,impl) = self.load_impl('Layer1/implml/external_tempfile.templateml')
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/output/test_ext_temp_file.txt")))
@@ -417,8 +452,9 @@
self.remove_if_exists(os.path.normpath("output/output/test5a.txt"))
- impl = self.load_impl('Layer1/implml/file5.templateml')
- impl.generate()
+ (config,impl) = self.load_impl('Layer1/implml/file5.templateml')
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/output/test5a.txt")))
result_file1 = None
@@ -437,8 +473,9 @@
self.remove_if_exists(os.path.normpath("output/access_configuration.txt"))
- impl = self.load_impl('Layer1/implml/access_configuration.templateml')
- impl.generate()
+ (config,impl) = self.load_impl('Layer1/implml/access_configuration.templateml')
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
self.assertTrue(os.path.exists(os.path.normpath("output/access_configuration.txt")))
result_file1 = None
@@ -453,12 +490,13 @@
if result_file1 != None: result_file1.close()
def test_create_context_dict1(self):
- impl = self.load_impl('Layer1/implml/file6.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file6.templateml')
impl.context = impl.create_dict()
- impl.generate()
+ gc = plugin.GenerationContext(configuration=config)
+ impl.generate(gc)
def test_list_output_files(self):
- impl = self.load_impl('Layer1/implml/file1.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/file1.templateml')
impl.set_output_root('outdir')
output_files = impl.list_output_files()
expected = map(lambda n: os.path.normpath(n), [
@@ -471,7 +509,7 @@
self.assertEquals(sorted(output_files), sorted(expected))
def test_has_ref(self):
- impl = self.load_impl('Layer1/implml/has_ref_template_test2.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/has_ref_template_test2.templateml')
self.assertEquals(impl.has_ref('Feature1.StringSetting_not_found'), False)
self.assertEquals(impl.has_ref('Feature1.StringSetting1'), True)
self.assertEquals(impl.has_ref('Feature2'), True)
@@ -480,7 +518,7 @@
self.assertEquals(impl.has_ref('Feature1.UnicodeValueSetting'), True)
def test_has_ref_external_template(self):
- impl = self.load_impl('Layer1/implml/has_ref_template_test3.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/has_ref_template_test3.templateml')
self.assertEquals(impl.has_ref('Feature1.StringSetting_not_found'), False)
self.assertEquals(impl.has_ref('Feature1.StringSetting1'), True)
self.assertEquals(impl.has_ref('Feature2'), True)
@@ -489,7 +527,7 @@
self.assertEquals(impl.has_ref('Feature1.UnicodeValueSetting'), True)
def test_has_ref_with_featree(self):
- impl = self.load_impl('Layer1/implml/has_ref_template_test.templateml')
+ (config,impl) = self.load_impl('Layer1/implml/has_ref_template_test.templateml')
self.assertEquals(impl.has_ref('Feature1.StringSetting'), True)
self.assertEquals(impl.has_ref('Feature2.StringSetting'), True)
@@ -501,8 +539,9 @@
p = api.Project(fs)
config = p.get_configuration('root1.confml')
impls = plugin.get_impl_set(config,'unicode_template_test\.templateml$')
- impls.output = OUTPUT_DIR
- impls.generate()
+ gc = plugin.GenerationContext(output=OUTPUT_DIR,
+ configuration=config)
+ impls.generate(gc)
self.assert_exists_and_contains_something(os.path.join(OUTPUT_DIR, "unicode_template_test.txt"))
# Check that the output exists and contains expected lines
@@ -544,7 +583,7 @@
self.write_data_to_file(filename, self.feature_list_to_str(expected_list))
filename = os.path.join(dir, "actual.txt")
self.write_data_to_file(filename, self.feature_list_to_str(feat_list))
- self.fail("Feature tree is not what was expected, see the files in '%s'" % dir)
+ self.fail("Feature list is not what was expected, see the files in '%s'" % dir)
def feature_tree_to_str(self, d, indent_amount=0):
"""
@@ -566,7 +605,7 @@
for key, value in sorted(d.items(), key=key_func):
temp.append(indent)
- if isinstance(value, dict):
+ if isinstance(value, (dict, templatemlplugin.FeatureDictProxy)):
temp.append("%r: %s," % (key, self.feature_tree_to_str(value, indent_amount + INDENT_AMOUNT)))
else:
temp.append("%r: %r," % (key, value))
@@ -582,7 +621,7 @@
"""
temp = ['[\n']
for item in lst:
- if isinstance(item, dict): temp.append(self.feature_tree_to_str(item))
+ if isinstance(item, (dict, templatemlplugin.FeatureDictProxy)): temp.append(self.feature_tree_to_str(item))
else: temp.append(repr(item))
temp.append(',\n')
temp.append(']')
@@ -592,9 +631,10 @@
def test_utf_bom_support(self):
OUTPUT_DIR = os.path.join(ROOT_PATH, 'temp/utf_bom_test')
self.recreate_dir(OUTPUT_DIR)
- impl = self.load_impl('Layer1/implml/utf_bom_test.templateml')
- impl.set_output_root(OUTPUT_DIR)
- impl.generate()
+ (config,impl) = self.load_impl('Layer1/implml/utf_bom_test.templateml')
+ gc = plugin.GenerationContext(output=OUTPUT_DIR,
+ configuration=config)
+ impl.generate(gc)
def check(file, contents):
FILE = os.path.join(OUTPUT_DIR, file)
@@ -635,8 +675,78 @@
foo
"""
reader = templatemlplugin.TemplatemlImplReader()
- self.assertRaises(exceptions.ParseError, reader.fromstring, DATA)
+ reader.fromstring(DATA)
+ self.assertRaises(exceptions.ParseError, reader.expand_output_refs_by_default_view)
+
+ def test_generate_from_template_with_feat_tree_iteration(self):
+ OUTPUT_DIR = os.path.join(ROOT_PATH, 'temp/feat_tree_iteration')
+ self.recreate_dir(OUTPUT_DIR)
+ (config,impl) = self.load_impl('Layer1/implml/feat_tree_iteration_test.templateml')
+ gc = plugin.GenerationContext(output=OUTPUT_DIR,
+ configuration=config)
+ impl.generate(gc)
+
+ OUTPUT_FILE = os.path.join(OUTPUT_DIR, 'feat_tree_iteration_test.txt')
+ self.assert_exists_and_contains_something(OUTPUT_FILE)
+ self.assert_file_content_equals(OUTPUT_FILE,
+ u"\n"\
+ u"Boolean setting = True\n"\
+ u"File setting = default_file.txt\n"\
+ u"Folder setting = default_folder\n"\
+ u"Int setting = 10\n"\
+ u"Real setting = 3.14\n"\
+ u"Selection setting = 1\n"\
+ u"Sequence setting = [[[None, None], 1.25, [None, None], 128, 'def1', False, '1'], [[None, None], 1.5, [None, None], 256, 'def2', False, '1']]\n"\
+ u"String setting = John Doe\n"\
+ u"String for unicode value test = カタカナ\n".encode('utf-8'))
+ def test_generate_from_template_generation_context_accessed(self):
+ OUTPUT_DIR = os.path.join(ROOT_PATH, 'temp/access_context')
+ self.recreate_dir(OUTPUT_DIR)
+ (config,impl) = self.load_impl('Layer1/implml/access_context.templateml')
+ context = plugin.GenerationContext(output=OUTPUT_DIR,
+ configuration=config)
+ context.tags = {'sometag': ['foo', 'bar']}
+ impl.generate(context)
+
+ OUTPUT_FILE = os.path.join(OUTPUT_DIR, 'access_context.txt')
+ self.assert_exists_and_contains_something(OUTPUT_FILE)
+ self.assert_file_content_equals(OUTPUT_FILE,
+ "Tags: {'sometag': ['foo', 'bar']}")
+
+ def test_invalid_ref_in_template(self):
+ OUTPUT_DIR = os.path.join(ROOT_PATH, 'temp/invalid_ref')
+ self.recreate_dir(OUTPUT_DIR)
+ (config,impl) = self.load_impl('Layer1/implml/invalid_ref.templateml')
+ context = plugin.GenerationContext(output=OUTPUT_DIR,
+ configuration=config)
+
+ log_file, handler, logger = self._prepare_log('invalid_refs.log')
+ impl.generate(context)
+ logger.removeHandler(handler)
+
+ self.assert_file_content_equals(os.path.join(OUTPUT_DIR, 'invalid_ref_1.txt'), "")
+ self.assert_file_content_equals(os.path.join(OUTPUT_DIR, 'invalid_ref_2.txt'), "")
+ self.assert_file_content_equals(os.path.join(OUTPUT_DIR, 'invalid_ref_3.txt'), "")
+
+ self.assert_file_contains(log_file,
+ ["TemplatemlImpl(ref='Layer1/implml/invalid_ref.templateml', type='templateml', lineno=2): Failed to generate output: NotFound: Feature 'Foo' not found",
+ "TemplatemlImpl(ref='Layer1/implml/invalid_ref.templateml', type='templateml', lineno=2): Failed to generate output: NotFound: Feature 'Feature1.Nonexistent' not found",
+ "TemplatemlImpl(ref='Layer1/implml/invalid_ref.templateml', type='templateml', lineno=2): Failed to generate output: NotFound: Feature 'Feature1.SequenceSetting.Nonexistent' not found"])
+
+ def _prepare_log(self, log_file, level=logging.DEBUG, formatter="%(levelname)s - %(name)s - %(message)s", logger='cone'):
+ FULL_PATH = os.path.join(ROOT_PATH, "temp/logs", log_file)
+ self.remove_if_exists(FULL_PATH)
+ self.create_dir_for_file_path(FULL_PATH)
+
+ handler = logging.FileHandler(FULL_PATH)
+ handler.setLevel(level)
+ frm = logging.Formatter(formatter)
+ handler.setFormatter(frm)
+ logger = logging.getLogger(logger)
+ logger.addHandler(handler)
+
+ return [FULL_PATH, handler, logger]
class TestExtractRefsFromTemplate(unittest.TestCase):
def test_extract_refs_from_template(self):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/xsd/templateml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/ConeTemplatePlugin/templatemlplugin/xsd/templateml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Path to the file where the template's text is defined.
+ Should be relative to the current implementation file.
+
+
+
+
+
+
+
+
+
+
+
+
+ The template text can either be specified directly in the element, or
+ in a file specified by the 'file' attribute.
+ ]]>
+
+
+
+
+
+
+
+ The filter is defined as a Python lambda function either directly in the element, or
+ in a file specified by the 'file' attribute.
+ ]]>
+
+
+
+
+
+
+
+ The name of the output file.
+
+
+
+
+
+
+ The directory where the output file is generated.
+
+
+
+
+
+
+ The ConfML setting reference from where the output file's path and name are
+ taken from.
+
+
+
+
+
+
+ Defines the encoding of the output file. Can be any of the encodings supported
+ by the Python codecs module (see http://docs.python.org/library/codecs.html#standard-encodings).
+
+
+
+
+
+
+
+
+ If set to 'true', a BOM will always be written to the output file,
+ if to 'false', it will never be. If the bom attribute is not defined
+ at all, the BOM scheme is left up to the used encoding, e.g. UTF-16
+ writes the BOM, but UTF-16-BE doesn't.
+
+ For encodings other than Unicode, this attribute does nothing.
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+ The name of the filter, used to reference it from the Jinja template.
+
+
+
+
+
+
+ Path to the file where the filter's Python code is defined.
+ Should be relative to the current implementation file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines an output file, its properties and the template used to generate it.
+
+
+
+
+
+
+
+ The filter is defined as a Python lambda function either directly in the element, or
+ in a file referenced by the 'file' attribute.
+ ]]>
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/__init__.py
--- a/configurationengine/source/plugins/common/integration-test/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/integration-test/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,24 +14,3 @@
# Description:
#
-import unittest, os, sys
-
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-PLUGIN_SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../..'))
-assert os.path.split(PLUGIN_SOURCE_ROOT)[1] == 'plugins'
-
-# Import plugin_utils from the plug-in sources root
-if PLUGIN_SOURCE_ROOT not in sys.path: sys.path.append(PLUGIN_SOURCE_ROOT)
-import plugin_utils
-
-# Run integration test initialization
-plugin_utils.integration_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/export_standalone.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/export_standalone.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,29 @@
+#
+# 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:
+#
+
+import os
+from testautomation.copy_dir import copy_dir
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+def export_standalone(target_path):
+ """
+ Export any needed extra data for standalone tests.
+ @param target_path: The path where the standalone tests are being exported.
+ """
+ copy_dir(source_dir = os.path.join(ROOT_PATH, '../ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project'),
+ target_dir = os.path.join(target_path, 'testdata/uses_layer_test_project'),
+ dir_ignore_functions = [lambda d: d == '.svn'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/runtests.py
--- a/configurationengine/source/plugins/common/integration-test/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/integration-test/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/generate/expected/test.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/generate/expected/test.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+jeejeejee
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/generate/project/custom/implml/unicode_rule_test.ruleml
--- a/configurationengine/source/plugins/common/integration-test/testdata/generate/project/custom/implml/unicode_rule_test.ruleml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/integration-test/testdata/generate/project/custom/implml/unicode_rule_test.ruleml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@

-
- True configures Feature1.StringSetting = Feature1.StringSetting + " " + BasicSettingTypesTest.StringSetting + u" (from rule: カタカナ)"
+
+ True configures ${Feature1.StringSetting} = ${Feature1.StringSetting} + " " + ${BasicSettingTypesTest.StringSetting} + u" (from rule: カタカナ)"
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/generate/project/custom/implml/xcreate_file.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/generate/project/custom/implml/xcreate_file.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/confml/feature1.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/confml/feature1.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,88 @@
+
+
+ Feature with all supported setting types for ConfML v1.0
+
+ A real setting
+
+
+ An int setting
+
+
+ A string setting
+
+
+ A boolean setting
+
+
+ A selection setting
+
+
+
+
+
+
+
+ A sequence setting
+
+ A real sub-setting
+
+
+ An int sub-setting
+
+
+ A string sub-setting
+
+
+ A boolean sub-setting
+
+
+ A selection sub-setting
+
+
+
+
+
+
+
+
+
+
+ 3.14
+ 10
+ default string
+ true
+ 1
+
+ 1.0
+ 1
+ template
+ false
+ 0
+
+
+ 1.25
+ 128
+ def1
+ false
+ 1
+
+
+ 1.5
+ 256
+ def2
+ false
+ 1
+
+
+
+
+
+
+ true
+ false
+ false
+ true
+ true
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/implml/output_test.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/implml/output_test.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TempFeature.Outputfile1: {{ feat_tree.Tempfeature.Outputfile1._value }}
+TempFeature.Outputdir: {{ feat_tree.Tempfeature.Outputdir._value }}
+TempFeature.Encoding: {{ feat_tree.Tempfeature.Encoding._value }}
+TempFeature.BOM: {{ feat_tree.Tempfeature.BOM._value }}
+TempFeature.Newline: {{ feat_tree.Tempfeature.Newline._value }}
+Feature1.RealSetting: {{ feat_tree.Feature1.RealSetting._value }}
+
+
+
+
+
+TempFeature.Outputfile2: {{ feat_tree.Tempfeature.Outputfile2._value }}
+TempFeature.Outputdir: {{ feat_tree.Tempfeature.Outputdir._value }}
+TempFeature.Encoding: UTF-8
+TempFeature.BOM: true
+TempFeature.Newline: win
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/layer/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/templateml_test_project/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/testdata/uses_layers_test_expected.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/common/integration-test/testdata/uses_layers_test_expected.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,37 @@
+Layer Tag Expected Actual Outcome
+assets/base/root.confml uda True True OK
+assets/base/root.confml rofs3 True True OK
+assets/base/root.confml rofs2 True True OK
+assets/layer1/root.confml uda True True OK
+assets/layer1/root.confml rofs3 False False OK
+assets/layer1/root.confml rofs2 False False OK
+assets/layer2/root.confml uda False False OK
+assets/layer2/root.confml rofs3 False False OK
+assets/layer2/root.confml rofs2 True True OK
+assets/layer3/root.confml uda False False OK
+assets/layer3/root.confml rofs3 False False OK
+assets/layer3/root.confml rofs2 False False OK
+assets/layer4/root.confml uda True True OK
+assets/layer4/root.confml rofs3 False False OK
+assets/layer4/root.confml rofs2 False False OK
+assets/layer5/root.confml uda False False OK
+assets/layer5/root.confml rofs3 True True OK
+assets/layer5/root.confml rofs2 False False OK
+assets/layer6/root.confml uda True True OK
+assets/layer6/root.confml rofs3 True True OK
+assets/layer6/root.confml rofs2 False False OK
+assets/layer7/root.confml uda True True OK
+assets/layer7/root.confml rofs3 False False OK
+assets/layer7/root.confml rofs2 False False OK
+assets/layer8/root.confml uda False False OK
+assets/layer8/root.confml rofs3 False False OK
+assets/layer8/root.confml rofs2 False False OK
+assets/layer9/root.confml uda True True OK
+assets/layer9/root.confml rofs3 False False OK
+assets/layer9/root.confml rofs2 False False OK
+assets/layer10/root.confml uda True True OK
+assets/layer10/root.confml rofs3 False False OK
+assets/layer10/root.confml rofs2 False False OK
+assets/layer11/root.confml uda True True OK
+assets/layer11/root.confml rofs3 False False OK
+assets/layer11/root.confml rofs2 False False OK
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/integration-test/unittest_generate.py
--- a/configurationengine/source/plugins/common/integration-test/unittest_generate.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/integration-test/unittest_generate.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,7 +18,7 @@
# @author Lasse Salo
import sys, os, shutil, unittest
-import __init__
+
from testautomation.base_testcase import BaseTestCase
from testautomation import zip_dir
@@ -27,7 +27,7 @@
if sys.platform == "win32":
CONE_SCRIPT = "cone.cmd"
else:
- CONE_SCRIPT = "cone.sh"
+ CONE_SCRIPT = "cone"
def get_cmd(action='generate'):
"""Return the command used to run the ConE sub-action"""
@@ -42,6 +42,17 @@
cmd = 'python "%s" %s' % (os.path.normpath(os.path.join(SOURCE_ROOT, 'scripts/cone_tool.py')), action)
return cmd
+def get_uses_layer_test_project():
+ # If running from the working copy
+ dir1 = os.path.normpath(os.path.join(ROOT_PATH, '../ConeRulePlugin/ruleplugin/evals/tests/layer_filtering_project'))
+ if os.path.isdir(dir1): return dir1
+
+ # If running from standalone
+ dir2 = os.path.normpath(os.path.join(ROOT_PATH, 'testdata/uses_layer_test_project'))
+ if os.path.isdir(dir2): return dir2
+
+ raise RuntimeError("layers_used() test project found neither in '%s' nor '%s'!" % (dir1, dir2))
+
class TestCommonGenerateAllImplsOnLastLayer(BaseTestCase):
def _prepare_workdir(self, workdir):
@@ -67,6 +78,133 @@
self.assert_exists_and_contains_something(project_zip)
self._run_test_generate_all_impls_on_last_layer('temp/gen_ll2', project_zip)
+
+ def test_uses_layers_rule(self):
+ project_dir = get_uses_layer_test_project()
+ self.assert_exists_and_contains_something(project_dir)
+
+ orig_workdir = os.getcwd()
+ workdir = self._prepare_workdir("temp/uses_layers_test")
+ os.chdir(workdir)
+
+ try:
+ cmd = '%s -p "%s" --output output --add-setting-file imaker_variantdir.cfg' % (get_cmd(), project_dir)
+ self.run_command(cmd)
+
+ self.assert_file_contents_equal(
+ os.path.join(ROOT_PATH, "testdata/uses_layers_test_expected.txt"),
+ "output/uses_layers_test.txt",
+ ignore_endline_style=True)
+ finally:
+ os.chdir(orig_workdir)
+
+ def test_override_templateml_outputattribs_from_cmd_line(self):
+ project_dir = os.path.join(ROOT_PATH, 'testdata', 'templateml_test_project')
+
+ #Added because of known bug #1018 (test data missing)
+ # Remove after fix ->
+ if os.path.isdir(project_dir):
+ if len(os.listdir(project_dir)) == 0:
+ self.fail("Path '%s' exists (is a directory) but does not contain anything)" % project_dir)
+ elif os.path.isfile(project_dir):
+ if os.stat(project_dir).st_size == 0:
+ self.fail("Path '%s' exists (is a file) but does not contain anything)" % project_dir)
+ else:
+ self.fail("Known bug #1018: Test data missing. Path '%s' does not exist" % project_dir)
+ # Remove after fix <-
+
+ self.assert_exists_and_contains_something(project_dir)
+
+ workdir = os.getcwd()
+ workdir = self._prepare_workdir(os.path.join('temp','gen_tmplml_out_from_cmd_line'))
+
+ logfile = os.path.join(workdir, 'cone.log')
+
+ file1 = os.path.join(workdir,'setdir','setfile1.txt')
+ file2 = os.path.join(workdir,'setdir','setfile2.txt')
+
+ cmd = ['%(cone_cmd)s',
+ '-p "%(project)s"',
+ '-c root.confml',
+ '--output "%(output)s"',
+ '--log-file="%(log_file)s"',
+ '--all-layers',
+ '--set=Tempfeature.Outputfile1=setfile1.txt',
+ '--set=Tempfeature.Outputfile2=setfile2.txt',
+ '--set=Tempfeature.Outputdir=setdir',
+ '--set=Tempfeature.Encoding=UTF-16',
+ '--set=Tempfeature.BOM=false',
+ '--set=Tempfeature.Newline=unix',]
+ cmd = ' '.join(cmd) % {'cone_cmd': get_cmd(),
+ 'project': project_dir,
+ 'output': workdir,
+ 'log_file': logfile}
+
+ self.run_command(cmd)
+
+ self.assert_exists_and_contains_something(os.path.join(workdir,'setdir'))
+ self.assert_file_contains(file1, ['TempFeature.Outputfile1: setfile1.txt',
+ 'TempFeature.Outputdir: setdir',
+ 'TempFeature.Encoding: UTF-16',
+ 'TempFeature.BOM: false',
+ 'TempFeature.Newline: unix'],
+ encoding='UTF-16')
+ self.assert_file_contains(file2, ['TempFeature.Outputfile2: setfile2.txt',
+ 'TempFeature.Outputdir: setdir',
+ 'TempFeature.Encoding: UTF-8',
+ 'TempFeature.BOM: true',
+ 'TempFeature.Newline: win'])
+
+
+ def test_set_tempvariables_as_templateml_outputattribs(self):
+ project_dir = os.path.join(ROOT_PATH, 'testdata', 'templateml_test_project')
+
+ #Added because of known bug #1018 (test data missing)
+ # Remove after fix ->
+ if os.path.isdir(project_dir):
+ if len(os.listdir(project_dir)) == 0:
+ self.fail("Path '%s' exists (is a directory) but does not contain anything)" % project_dir)
+ elif os.path.isfile(project_dir):
+ if os.stat(project_dir).st_size == 0:
+ self.fail("Path '%s' exists (is a file) but does not contain anything)" % project_dir)
+ else:
+ self.fail("Known bug #1018: Test data missing. Path '%s' does not exist" % project_dir)
+ # Remove after fix <-
+
+ self.assert_exists_and_contains_something(project_dir)
+
+ workdir = os.getcwd()
+ workdir = self._prepare_workdir(os.path.join('temp','gen_tmplml_out_from_ref'))
+
+ logfile = os.path.join(workdir, 'cone.log')
+
+ file1 = os.path.join(workdir,'origdir','orig1.txt')
+ file2 = os.path.join(workdir,'origdir','orig2.txt')
+
+ cmd = ['%(cone_cmd)s',
+ '-p "%(project)s"',
+ '-c root.confml',
+ '--output "%(output)s"',
+ '--log-file="%(log_file)s"',
+ '--all-layers',]
+ cmd = ' '.join(cmd) % {'cone_cmd': get_cmd(),
+ 'project': project_dir,
+ 'output': workdir,
+ 'log_file': logfile}
+
+ self.run_command(cmd)
+
+ self.assert_exists_and_contains_something(os.path.join(workdir,'origdir'))
+ self.assert_file_contains(file1, ['TempFeature.Outputfile1: orig1.txt',
+ 'TempFeature.Outputdir: origdir',
+ 'TempFeature.Encoding: ASCII',
+ 'TempFeature.BOM: true',
+ 'TempFeature.Newline: win'])
+ self.assert_file_contains(file2, ['TempFeature.Outputfile2: orig2.txt',
+ 'TempFeature.Outputdir: origdir',
+ 'TempFeature.Encoding: UTF-8',
+ 'TempFeature.BOM: true',
+ 'TempFeature.Newline: win'])
def _run_test_generate_all_impls_on_last_layer(self, workdir, project):
# Create a temp workdir and go there to run the test
@@ -83,5 +221,8 @@
finally:
os.chdir(orig_workdir)
+
+
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/common/runtests.py
--- a/configurationengine/source/plugins/common/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,19 +14,6 @@
# Description:
#
-import sys, os, re, unittest
-
-ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
-
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
-if __name__ == "__main__":
- # Collect a list of plug-in source paths and plug-in module names
- paths_and_modnames = plugin_utils.find_plugin_sources(ROOT_PATH)
- # Create a test suite from them
- suite = plugin_utils.collect_suite_from_source_list(paths_and_modnames)
- # Run the suite
- unittest.TextTestRunner(verbosity=2).run(suite)
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_impl.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_impl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_impl.py Tue Aug 10 14:29:28 2010 +0300
@@ -39,7 +39,7 @@
def generate(self, context=None):
for output in self.output_objects:
self.logger.debug("Generating '%s'" % output.get_output_file(self.output, self.configuration))
- output.write_to_file(self.output, self.configuration)
+ output.write_to_file(self.output, context)
def list_output_files(self):
files = []
@@ -51,4 +51,8 @@
refs = []
for output in self.output_objects:
refs.extend(output.get_refs())
+ # return None in case there are no refs in the implementations
+ # to prevent filtering based on refs
+ if not refs:
+ refs = None
return refs
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_model.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_model.py Tue Aug 10 14:29:28 2010 +0300
@@ -25,10 +25,11 @@
Class representing an ExampleML output element.
"""
- def __init__(self, file, encoding, text):
+ def __init__(self, file, encoding, text, lineno=None):
self.file = file
self.encoding = encoding
self.text = text
+ self.lineno = lineno
def get_refs(self):
"""
@@ -44,26 +45,22 @@
file = utils.expand_refs_by_default_view(self.file, config.get_default_view())
return os.path.normpath(os.path.join(output_dir, file))
- def write_to_file(self, output_dir, config):
+ def write_to_file(self, output_dir, context):
"""
Write the text file specified by this output object to the
given output directory.
"""
# Get the actual output path and encoding
- file_path = self.get_output_file(output_dir, config)
- encoding = utils.expand_refs_by_default_view(self.encoding, config.get_default_view())
+ file_path = self.get_output_file(output_dir, context.configuration)
+ encoding = utils.expand_refs_by_default_view(self.encoding, context.configuration.get_default_view())
# Generate the binary data to write
- text = utils.expand_refs_by_default_view(self.text, config.get_default_view())
+ text = utils.expand_refs_by_default_view(self.text, context.configuration.get_default_view())
data = text.encode(encoding)
- # Make sure that the output directory exists
- dir = os.path.dirname(file_path)
- if dir != '' and not os.path.exists(dir):
- os.makedirs(dir)
# Write the file.
- f = open(file_path, "wb")
+ f = context.create_file(file_path, mode="wb")
try: f.write(data)
finally: f.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_reader.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,12 +14,16 @@
# Description:
#
-from cone.public import exceptions, plugin
+import pkg_resources
+from cone.public import exceptions, plugin, utils
import exampleml_impl
import exampleml_model
class ExamplemlReader(plugin.ReaderBase):
NAMESPACE = 'http://www.example.org/xml/exampleml/1'
+ NAMESPACE_ID = 'exampleml'
+ ROOT_ELEMENT_NAME = 'exampleml'
+ SCHEMA_PROBLEM_SUB_ID = 'exampleml'
FILE_EXTENSIONS = ['exampleml']
@classmethod
@@ -28,6 +32,10 @@
outputs = reader._read_outputs(etree)
return exampleml_impl.ExamplemlImpl(resource_ref, configuration, outputs)
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('examplemlplugin', 'xsd/exampleml.xsd')
+
def _read_outputs(self, elem):
"""
Read output objects from the given XML element.
@@ -46,4 +54,5 @@
raise exceptions.ParseError("Element does not have the mandatory 'file' attribute")
return exampleml_model.Output(file = file,
encoding = elem.get('encoding', 'UTF-8'),
- text = elem.text or '')
\ No newline at end of file
+ text = elem.text or '',
+ lineno = utils.etree.get_lineno(elem))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_validators.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_validators.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,69 @@
+#
+# 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:
+#
+
+
+import codecs
+
+from cone.public import api, exceptions, utils
+from cone.validation.implmlvalidation import ImplValidatorBase
+from examplemlplugin import exampleml_impl
+
+class ExamplemlValidatorBase(ImplValidatorBase):
+ SUPPORTED_IMPL_CLASSES = exampleml_impl.ExamplemlImpl
+
+class ExamplemlReferenceValidator(ExamplemlValidatorBase):
+ PROBLEM_TYPES = ['model.implml.exampleml.invalid_ref']
+
+ def validate(self):
+ for output in self.impl.output_objects:
+ # Collect all refs
+ refs = set()
+ for ref in utils.extract_delimited_tokens(output.text): refs.add(ref)
+ for ref in utils.extract_delimited_tokens(output.encoding): refs.add(ref)
+ for ref in utils.extract_delimited_tokens(output.file): refs.add(ref)
+
+ for ref in refs:
+ self.check_feature_reference(ref, output.lineno, self.PROBLEM_TYPES[0])
+
+class ExamplemlEncodingValidator(ExamplemlValidatorBase):
+ PROBLEM_TYPES = ['model.implml.exampleml.invalid_encoding']
+
+ def validate(self):
+ for output in self.impl.output_objects:
+ encoding = None
+ try:
+ encoding = utils.expand_refs_by_default_view(
+ output.encoding,
+ self.context.configuration.get_default_view(),
+ catch_not_found=False)
+ except exceptions.NotFound:
+ # Ignore invalid setting references, they are validated
+ # in another validator
+ continue
+
+ if encoding is not None:
+ # Check the encoding
+ try:
+ codecs.lookup(encoding)
+ except LookupError:
+ prob = api.Problem(
+ msg = u"Invalid encoding '%s'" % encoding,
+ type = self.PROBLEM_TYPES[0],
+ line = output.lineno,
+ file = self.impl.ref)
+ self.context.problems.append(prob)
+
+VALIDATOR_CLASSES = [ExamplemlReferenceValidator, ExamplemlEncodingValidator]
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/__init__.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,11 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest1_1.txt
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest1_1.txt Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Multitest impl 1 output 1
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest1_2.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest1_2.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest2_1.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest2_1.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest2_2.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/multitest2_2.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/some/dir/out1.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/some/dir/out1.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/some/dir2/out2.txt
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/some/dir2/out2.txt Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Test 1 output 2 €
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/test.txt
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/gen_expected/test.txt Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Value from ConfML: ελληνικά (unicode test), <&> (special char test)
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/confml/test.confml
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/confml/test.confml Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- ελληνικά (unicode test), <&> (special char test)
-
- some/dir/out1.txt
- UTF-16-LE
-
- some/dir2
- out2.txt
-
-
-
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/implml/multitest.implml
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/implml/multitest.implml Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-
-
-
-
-
- Multitest impl 1 output 1
- Multitest impl 1 output 2
-
-
-
-
- Unicode test: ελληνικά
- Special char test: <&>
-
-
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/implml/test.exampleml
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/implml/test.exampleml Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-
- Value from ConfML: ${TestFeature.Value1}
- Test test
- Test 1 output 2 €
-
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/root.confml
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/Layer/root.confml Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-
-
-
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/root.confml
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/project/root.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/runtests.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest1_1.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest1_1.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Multitest impl 1 output 1
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest1_2.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest1_2.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest2_1.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest2_1.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest2_2.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/multitest2_2.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/some/dir/out1.txt
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/some/dir/out1.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/some/dir2/out2.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/some/dir2/out2.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Test 1 output 2 €
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/test.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/expected/test.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Value from ConfML: ελληνικά (unicode test), <&> (special char test)
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/confml/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/confml/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ελληνικά (unicode test), <&> (special char test)
+
+ some/dir/out1.txt
+ UTF-16-LE
+
+ some/dir2
+ out2.txt
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/implml/multitest.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/implml/multitest.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Multitest impl 1 output 1
+ Multitest impl 1 output 2
+
+
+
+
+ Unicode test: ελληνικά
+ Special char test: <&>
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/implml/test.exampleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/implml/test.exampleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+ Value from ConfML: ${TestFeature.Value1}
+ Test test
+ Test 1 output 2 €
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/Layer/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/root.confml
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/generation/project/root.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/expected/invalid_encoding.exampleml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/expected/invalid_encoding.exampleml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+Problem(msg=u"Invalid encoding 'foobar'", type='model.implml.exampleml.invalid_encoding', line=7, file='Layer1/implml/invalid_encoding.exampleml', severity='error')
+Problem(msg=u"Invalid encoding 'foocode'", type='model.implml.exampleml.invalid_encoding', line=6, file='Layer1/implml/invalid_encoding.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.Bar' not found in configuration", type='model.implml.exampleml.invalid_ref', line=10, file='Layer1/implml/invalid_encoding.exampleml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/expected/invalid_refs.exampleml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/expected/invalid_refs.exampleml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+Problem(msg=u"Setting 'Foo.MoreText' not found in configuration", type='model.implml.exampleml.invalid_ref', line=4, file='Layer1/implml/invalid_refs.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.OutputDir' not found in configuration", type='model.implml.exampleml.invalid_ref', line=5, file='Layer1/implml/invalid_refs.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.OutputEncoding' not found in configuration", type='model.implml.exampleml.invalid_ref', line=4, file='Layer1/implml/invalid_refs.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.OutputFile' not found in configuration", type='model.implml.exampleml.invalid_ref', line=4, file='Layer1/implml/invalid_refs.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.OutputFile' not found in configuration", type='model.implml.exampleml.invalid_ref', line=5, file='Layer1/implml/invalid_refs.exampleml', severity='error')
+Problem(msg=u"Setting 'Foo.Text' not found in configuration", type='model.implml.exampleml.invalid_ref', line=3, file='Layer1/implml/invalid_refs.exampleml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/confml/invalid_encoding.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/confml/invalid_encoding.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+ utf-16
+ foobar
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/implml/invalid_encoding.exampleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/implml/invalid_encoding.exampleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+ Test
+ Test
+
+ Test
+ Test
+
+
+ Test
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/implml/invalid_refs.exampleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/implml/invalid_refs.exampleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+ Value from ConfML: ${Foo.Text}
+ Test test ${Foo.MoreText}
+ Test 1 output 2 €
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/Layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/root.confml
Binary file configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/project/root.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/schema/invalid/missing_output_file.exampleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/schema/invalid/missing_output_file.exampleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+ Value from ConfML: ${Foo.Text}
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/schema/valid/test.exampleml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/testdata/validation/schema/valid/test.exampleml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+ Value from ConfML: ${Foo.Text}
+ Test test ${Foo.MoreText}
+ Test 1 output 2 €
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_generation.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_generation.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_generation.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,15 +14,13 @@
# Description:
#
-import sys, os, unittest
-import __init__
+import os
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
from testautomation.base_testcase import BaseTestCase
-from cone.public import exceptions, plugin, api, container
+from cone.public import plugin, api
-from examplemlplugin import exampleml_reader
def abspath(path):
return os.path.normpath(os.path.join(ROOT_PATH, path))
@@ -30,18 +28,19 @@
class TestExamplemlGeneration(BaseTestCase):
def test_generate_from_project(self):
- project_dir = abspath('project')
+ project_dir = abspath('testdata/generation/project')
config = 'root.confml'
- output_dir = abspath('temp/output')
- expected_dir = abspath('gen_expected')
+ output_dir = abspath('temp/generation/output')
+ expected_dir = abspath('testdata/generation/expected')
self.remove_if_exists(output_dir)
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration(config)
+ context = plugin.GenerationContext(configuration=config,
+ output=output_dir)
impls = plugin.get_impl_set(config)
- impls.output = output_dir
- impls.generate()
+ impls.generate(context)
self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn'])
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_impl.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_impl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_impl.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import sys, os, unittest
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -26,7 +25,7 @@
class TestExamplemlImpl(unittest.TestCase):
def setUp(self):
- project_dir = os.path.join(ROOT_PATH, 'project')
+ project_dir = os.path.join(ROOT_PATH, 'testdata/generation/project')
self.project = api.Project(api.Storage.open(project_dir))
self.config = self.project.get_configuration('root.confml')
@@ -42,7 +41,7 @@
def test_list_output_files(self):
def oj( p2): # oj = output_join
- return os.path.normpath(os.path.join('output', p2))
+ return os.path.normpath(p2)
impl = self.get_impl('Layer/implml/test.exampleml', 0)
self.assertEquals(impl.list_output_files(), [oj('test.txt'),
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_reader.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import sys, os, unittest
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_validation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_validation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,63 @@
+#
+# 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:
+#
+
+import os
+import __init__
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+from cone.validation import schemavalidation, implmlvalidation
+
+class TestExamplemlValidation(BaseTestCase):
+
+ def _run_test(self, filename):
+ filepath = 'Layer1/implml/' + filename
+ project_dir = os.path.join(ROOT_PATH, 'testdata/validation/project')
+ config = 'root.confml'
+
+ prj = api.Project(api.Storage.open(project_dir))
+ config = prj.get_configuration(config)
+ problems = implmlvalidation.validate_impls(config, filter=filepath + '$')
+
+ self.assert_problem_list_equals_expected(
+ actual = problems,
+ expected_file = os.path.join(ROOT_PATH, 'testdata/validation/expected', filename + '.txt'),
+ outdir = os.path.join(ROOT_PATH, 'temp/validation', filename))
+
+ def test_validate_invalid_refs(self):
+ self._run_test('invalid_refs.exampleml')
+
+ def test_validate_invalid_encoding(self):
+ self._run_test('invalid_encoding.exampleml')
+
+class TestExamplemlSchemaValidation(BaseTestCase, schemavalidation.SchemaValidationTestMixin):
+ NAMESPACE = 'http://www.example.org/xml/exampleml/1'
+ PROBLEM_TYPE = 'schema.implml.exampleml'
+
+ def test_schemavalidate_exampleml_valid_files(self):
+ self.assert_schemavalidation_succeeds(
+ type = 'implml',
+ dir = os.path.join(ROOT_PATH, 'testdata/validation/schema/valid'),
+ namespace = self.NAMESPACE)
+
+ def test_schemavalidate_exampleml_invalid_files(self):
+ self.assert_schemavalidation_fails(
+ type = 'implml',
+ dir = os.path.join(ROOT_PATH, 'testdata/validation/schema/invalid'),
+ namespace = self.NAMESPACE,
+ problem_type = self.PROBLEM_TYPE)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/xsd/exampleml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/examplemlplugin/xsd/exampleml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ ExampleML implementation for demonstration/template purposes.
+
+
+
+
+
+
+
+
+
+ The output element specifies a single output file, its template (text) and encoding.
+
+
+
+
+
+
+
+ Specifies the location of the output file.
+ ConfML setting references can be used with the ${} notation.
+
+
+
+
+
+
+
+ Specifies the encoding of the output file, defaults to UTF-8.
+ ConfML setting references can be used with the ${} notation.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExamplePlugin/setup.py
--- a/configurationengine/source/plugins/example/ConeExamplePlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/ConeExamplePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "coneexamplemlplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'examplemlplugin': ['xsd/*.xsd']},
test_suite = "examplemlplugin.tests.collect_suite",
# metadata for upload to PyPI
@@ -35,13 +36,20 @@
# Entry point info.
# Plug-ins can register ImplML reader classes by adding entry points
- # pointing to reader classes under 'cone.plugins.implmlreaders'
+ # pointing to reader classes under 'cone.plugins.implmlreaders', and
+ # validator classes under 'cone.plugins.implvalidators'
entry_points = {
'cone.plugins.implmlreaders': [
'exampleml = examplemlplugin.exampleml_reader:ExamplemlReader',
# More readers (e.g. different versions of the same ImplML)
# could also be registered:
#'exampleml_v2 = examplemlplugin.exampleml_reader:ExamplemlReader2',
- ]
+ ],
+
+ 'cone.plugins.implvalidators': [
+ # Each entry point is expected to be an iterable of reader
+ # classes, here it points to a list defined in exampleml_validators.py
+ 'exampleml = examplemlplugin.exampleml_validators:VALIDATOR_CLASSES'
+ ],
}
)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,17 @@
+#
+# 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:
+#
+
+__version__ = 0.1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+#
+# 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:
+#
+
+import sys, os, unittest
+
+# Path to the directory where this file is located
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+from testautomation import plugin_utils
+plugin_utils.plugin_test_init(ROOT_PATH)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/runtests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,19 @@
+#
+# 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:
+#
+
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/testdata/expected.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/testdata/expected.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,1 @@
+Problem(msg="String 'foo' missing from value of feature 'ExampleValidatorTest.FOO_SomeSetting2'", type='model.confml.foo_missing', line=12, file='test.confml', severity='warning')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/testdata/test.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/testdata/test.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+ foo bar
+ abc foo
+ abc123
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/unittest_validation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/tests/unittest_validation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,38 @@
+#
+# 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:
+#
+
+import os
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+from cone.validation import confmlvalidation
+
+class TestExampleValidatorValidation(BaseTestCase):
+
+ def test_validate(self):
+ project_dir = os.path.join(ROOT_PATH, 'testdata')
+ config = 'test.confml'
+
+ prj = api.Project(api.Storage.open(project_dir))
+ config = prj.get_configuration(config)
+ problems = confmlvalidation.validate_configuration(config).problems
+
+ self.assert_problem_list_equals_expected(
+ actual = problems,
+ expected_file = os.path.join(ROOT_PATH, 'testdata/expected.txt'),
+ outdir = os.path.join(ROOT_PATH, 'temp'))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/validators.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/examplevalidatorplugin/validators.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,39 @@
+#
+# 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:
+#
+
+from cone.public import api
+from cone.confml import model
+from cone.validation.confmlvalidation import ValidatorBase
+
+class ExampleValidator(ValidatorBase):
+ PROBLEM_TYPES = ['model.confml.foo_missing']
+
+ def validate(self):
+ for ref, feature in self.context.feature_dict.iteritems():
+ if isinstance(feature._obj, model.ConfmlStringSetting) and feature.ref.startswith('FOO_'):
+ value = feature.get_value()
+ if isinstance(value, basestring) and 'foo' not in value:
+ dataobj = feature.datas['data'][-1]
+
+ prob = api.Problem(
+ msg = "String 'foo' missing from value of feature '%s'" % ref,
+ type = self.PROBLEM_TYPES[0],
+ line = dataobj.lineno,
+ file = dataobj.get_configuration_path(),
+ severity = api.Problem.SEVERITY_WARNING)
+ self.context.problems.append(prob)
+
+VALIDATOR_CLASSES = [ExampleValidator]
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/setup.cfg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/setup.cfg Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,2 @@
+[egg_info]
+tag_svn_revision = 1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/ConeExampleValidatorPlugin/setup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/example/ConeExampleValidatorPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,41 @@
+#
+# 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:
+#
+
+import os, os.path
+from setuptools import setup, find_packages
+from examplemlplugin import __version__
+
+setup(
+ name = "coneexamplevalidatorplugin",
+ version = __version__,
+ packages = find_packages(exclude=["*.tests"]),
+ test_suite = "examplevalidatorplugin.tests.collect_suite",
+
+ # metadata for upload to PyPI
+ author = "",
+ author_email = "authors.email@example.com",
+ description = "Configuration Engine ExampleML plugin",
+ license = "Eclipse Public License v1.0",
+ keywords = "cone",
+ url = "http://developer.symbian.org/wiki/index.php/Software_Configuration_Middleware",
+ zip_safe = True,
+
+ entry_points = {
+ 'cone.plugins.confmlvalidators': [
+ 'example = examplevalidatorplugin.validators:VALIDATOR_CLASSES'
+ ],
+ }
+)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/integration-test/__init__.py
--- a/configurationengine/source/plugins/example/integration-test/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/integration-test/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,24 +16,4 @@
##
# @author Teemu Rytkonen
-import unittest, os, sys
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-PLUGIN_SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../..'))
-assert os.path.split(PLUGIN_SOURCE_ROOT)[1] == 'plugins'
-
-# Import plugin_utils from the plug-in sources root
-if PLUGIN_SOURCE_ROOT not in sys.path: sys.path.append(PLUGIN_SOURCE_ROOT)
-import plugin_utils
-
-# Run integration test initialization
-plugin_utils.integration_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/integration-test/runtests.py
--- a/configurationengine/source/plugins/example/integration-test/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/integration-test/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,6 +16,6 @@
##
# @author
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/integration-test/testdata/generate/project/Layer/implml/multitest.implml
--- a/configurationengine/source/plugins/example/integration-test/testdata/generate/project/Layer/implml/multitest.implml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/integration-test/testdata/generate/project/Layer/implml/multitest.implml Tue Aug 10 14:29:28 2010 +0300
@@ -2,14 +2,14 @@
-
+ Multitest impl 1 output 1Multitest impl 1 output 2
-
+
-
+ Unicode test: ελληνικάSpecial char test: <&>
-
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/integration-test/unittest_generate.py
--- a/configurationengine/source/plugins/example/integration-test/unittest_generate.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/integration-test/unittest_generate.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,7 +16,7 @@
#
import sys, os, shutil, unittest
-import __init__
+
from testautomation.base_testcase import BaseTestCase
from testautomation import zip_dir
@@ -25,7 +25,7 @@
if sys.platform == "win32":
CONE_SCRIPT = "cone.cmd"
else:
- CONE_SCRIPT = "cone.sh"
+ CONE_SCRIPT = "cone"
def get_cmd(action='generate'):
"""Return the command used to run the ConE sub-action"""
@@ -77,7 +77,7 @@
self.run_command(cmd)
EXPECTED_DIR = os.path.join(ROOT_PATH, "testdata/generate/expected")
- self.assert_dir_contents_equal('output', EXPECTED_DIR, ['.svn'])
+ self.assert_dir_contents_equal(os.path.join(workdir,'output'), EXPECTED_DIR, ['.svn'])
finally:
os.chdir(orig_workdir)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/example/runtests.py
--- a/configurationengine/source/plugins/example/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/example/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,19 +14,6 @@
# Description:
#
-import sys, os, re, unittest
-
-ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
-
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
-if __name__ == "__main__":
- # Collect a list of plug-in source paths and plug-in module names
- paths_and_modnames = plugin_utils.find_plugin_sources(ROOT_PATH)
- # Create a test suite from them
- suite = plugin_utils.collect_suite_from_source_list(paths_and_modnames)
- # Run the suite
- unittest.TextTestRunner(verbosity=2).run(suite)
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/nose_unittests.cfg
--- a/configurationengine/source/plugins/nose_unittests.cfg Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-[nosetests]
-verbosity=3
-include=unittest
-with-xunit=1
-xunit-file=cone-unittests.xml
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/plugin_utils.py
--- a/configurationengine/source/plugins/plugin_utils.py Fri Mar 12 08:30:17 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-#
-# 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:
-#
-
-import sys, os, unittest, re
-import build_egg_info
-
-# Path to the directory where this file is located
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-
-# Path to the source/ directory
-SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '..'))
-assert os.path.split(SOURCE_ROOT)[1] == 'source'
-
-# Path to the source/plugins directory
-PLUGIN_SOURCE_ROOT = os.path.normpath(os.path.join(SOURCE_ROOT, 'plugins'))
-assert os.path.isdir(PLUGIN_SOURCE_ROOT)
-
-def plugin_test_init(root_path, plugin_source_relative_path='../..'):
- """
- Initialize things so that plug-in unit tests can be run.
-
- @param root_path: Path of the __init__.py file calling this function.
- @param plugin_source_relative_path: Path to the plug-in's source root relative
- to root_path. Usually this should be '../..', since this function is intended
- to be called from a plug-in's tests/__init__.py file.
-
- """
- # Add paths so that the unit tests work
- # -------------------------------------
- extra_paths = [
- # For module 'cone'
- SOURCE_ROOT,
-
- # For module 'testautomation'
- os.path.join(SOURCE_ROOT, 'testautomation'),
-
- # For the plug-in module.
- # Since the method is expected to be called from e.g.
- # source/plugins/ConeSomePlugin/someplugin/tests/__init__.py, this will then be
- # source/plugins/ConeSomePlugin, in which case the module 'someplugin' can be
- # imported
- os.path.join(root_path, plugin_source_relative_path)
- ]
- for p in extra_paths:
- p = os.path.normpath(p)
- if p not in sys.path: sys.path.append(p)
-
- # Generate egg-info for the plug-in.
- # The egg-info needs to be up-to-date, or the plug-in framework will not be able
- # to find the plug-in's ImplML reader classes
- plugin_path = os.path.normpath(os.path.join(root_path, plugin_source_relative_path))
- assert 'setup.py' in os.listdir(plugin_path), "Path '%s' does not contain 'setup.py" % plugin_path
- build_egg_info.generate_egg_info(plugin_path)
-
-def integration_test_init(root_path):
- """
- Initialize things so that integration tests can be run.
-
- This function is intended to be called from a sub-package's integration-test/__init__.py file.
- @param root_path: Path of the __init__.py file calling this function.
- """
- # Add paths so that the unit tests work
- # -------------------------------------
- extra_paths = [
- # For module 'cone' (may be needed in some tests for e.g. asserts)
- SOURCE_ROOT,
-
- # For module 'testautomation'
- os.path.join(SOURCE_ROOT, 'testautomation'),
- ]
- for p in extra_paths:
- p = os.path.normpath(p)
- if p not in sys.path: sys.path.append(p)
-
- # Collect plug-in source paths (common + current)
- temp = []
- temp += [path for path, _ in find_plugin_sources(os.path.join(PLUGIN_SOURCE_ROOT, 'common'))]
- temp += [path for path, _ in find_plugin_sources(os.path.normpath(os.path.join(root_path, '..')))]
- plugin_paths = []
- for p in temp:
- if p not in plugin_paths: plugin_paths.append(p)
-
- # Add things to PYTHONPATH so that running cone_tool.py works
- paths = []
- paths.append(SOURCE_ROOT) # For module 'cone'
- paths.extend(plugin_paths)
- os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + ';' + ';'.join(paths)
-
- # Generate egg-info for the plug-ins.
- # The egg-info needs to be up-to-date, or the plug-in framework will not be able
- # to find the plug-in's ImplML reader classes
- for p in plugin_paths:
- assert 'setup.py' in os.listdir(p), "Path '%s' does not contain 'setup.py" % p
- build_egg_info.generate_egg_info(p)
-
-def init_all():
- """
- Add all plug-ins to sys.path and PYTHONPATH so that running all
- plug-in unit tests and integration tests work.
- """
- # Find all plug-in source directories
- plugin_paths = []
- temp = find_all_plugin_sources(os.path.join(PLUGIN_SOURCE_ROOT))
- for package_name, sources in temp.iteritems():
- for path, modname in sources:
- plugin_paths.append(path)
-
- # Add paths so that the unit tests work
- # -------------------------------------
- extra_paths = [
- # For module 'cone' (may be needed in some tests for e.g. asserts)
- SOURCE_ROOT,
-
- # For module 'testautomation'
- os.path.join(SOURCE_ROOT, 'testautomation'),
- ] + plugin_paths
- for p in extra_paths:
- p = os.path.normpath(p)
- if p not in sys.path: sys.path.append(p)
-
- # Add things to PYTHONPATH so that running cone_tool.py works
- paths = []
- paths.append(SOURCE_ROOT) # For module 'cone'
- paths.extend(plugin_paths)
- os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + ';' + ';'.join(paths)
-
- # Generate egg-info for the plug-ins.
- # The egg-info needs to be up-to-date, or the plug-in framework will not be able
- # to find the plug-in's ImplML reader classes
- for p in plugin_paths:
- assert 'setup.py' in os.listdir(p), "Path '%s' does not contain 'setup.py" % p
- build_egg_info.generate_egg_info(p)
-
-def collect_test_suite_from_dir(root_path):
- """
- Return a test suite containing all tests in 'unittest_*.py' files under the given directory.
- """
- # Find all unittest_*.py files in the folder
- test_modules = filter(lambda name: re.match(r'^unittest_.*\.py$', name) != None, os.listdir(root_path))
- # Strip .py endings
- test_modules = map(lambda name: name[:-3], test_modules)
-
- # Add the root path as the first one in sys.path, so that
- # __import__() checks that first when attempting to import a module
- sys.path.insert(0, root_path)
-
- try:
- suite = unittest.TestSuite()
- for test_module in test_modules:
- # Load the test module dynamically and add it to the test suite
- module = __import__(test_module)
- suite.addTests(unittest.TestLoader().loadTestsFromModule(module))
- return suite
- finally:
- # Remove root_path from sys.path
- del sys.path[0]
-
-def collect_suite_from_source_list(paths_and_modnames):
- suite = unittest.TestSuite()
-
- # Add the source paths to sys.path
- for path, modname in paths_and_modnames:
- if path not in sys.path:
- sys.path.append(path)
-
- # Import the tests in a separate loop, because otherwise the ImplML reader classes
- # could be loaded before all plug-ins are in sys.path
- for path, modname in paths_and_modnames:
- try:
- m = __import__(modname + '.tests')
- suite.addTests(m.tests.collect_suite())
- except ImportError:
- print "Tests for '%s' not added, no 'tests' module found" % path
-
- return suite
-
-def get_plugin_module_name(plugin_src_path):
- """
- Return the name of the plug-in's module under given plug-in source path.
-
- >>> get_tests_module('source/plugins/common/ConeContentPlugin')
- 'contentplugin'
- >>> get_tests_module('foo')
- None
- """
- if not os.path.isdir(plugin_src_path):
- return None
-
- for name in os.listdir(plugin_src_path):
- path = os.path.join(plugin_src_path, name)
- if os.path.isdir(path) and '__init__.py' in os.listdir(path):
- return name
- return None
-
-def find_plugin_sources(subpackage_root_path):
- """
- Return ConE plug-in source directories from the given path.
-
- All sub-directories in subpackage_root_path of the form Cone*Plugin/ containing
- a sub-directory that is a python module are returned.
-
- @param path: The directory from where to find the entries.
- @return: A list of tuples, each containing (, ).
- """
- pattern = re.compile(r'^Cone.*Plugin$')
-
- # Collect a list of plug-in source paths and plug-in module names
- result = []
- for name in os.listdir(subpackage_root_path):
- path = os.path.join(subpackage_root_path, name)
- if pattern.match(name) is not None:
- modname = get_plugin_module_name(path)
- if modname is not None:
- result.append((path, modname))
- return result
-
-def find_all_plugin_sources(plugins_root_path):
- """
- Return all ConE plug-in source directories from the plugins/ root
- directory.
- @return: A dictionary containing the output of find_plugin_sources() by
- plug-in sub-packages.
- >>> find_all_plugin_sources('C:/work/cone-trunk/source/plugins')
- {'common': [('C:/work/cone-trunk/source/plugins/common/ConeContentPlugin', 'contentplugin'),
- ('C:/work/cone-trunk/source/plugins/common/ConeTemplatePlugin', 'templatemlplugin')],
- 'example': [('C:/work/cone-trunk/source/plugins/example/ConeExamplePlugin', 'examplemlplugin')]}
- """
- result = {}
- for name in os.listdir(plugins_root_path):
- path = os.path.join(plugins_root_path, name)
- if os.path.isdir(path):
- sources = find_plugin_sources(path)
- if sources: result[name] = sources
- return result
-
-def find_plugin_package_subpaths(subpath, package_name=None):
- """
- Return a list of plug-in package sub-paths based on the given plug-in package name.
-
- The returned list always contains the sub-path for common plug-ins, and
- additionally for an extra plug-in package based on the given package name.
-
- This function can be used to find specifically named files or directories
- under the plug-in paths. E.g. find all 'integration-test' directories:
-
- >>> find_plugin_package_subpaths('integration-test', 'symbian')
- [('common', 'C:\\cone\\trunk\\sources\\plugins\\common\\integration-test'),
- ('symbian', 'C:\\cone\\trunk\\sources\\plugins\\symbian\\integration-test')]
-
- @param package_name: Name of the extra plug-in package. Can be None, '',
- 'common' or an existing plug-in package.
- @return: List of tuples (package_name, subpath).
-
- @raise ValueError: The given package_name was invalid.
- """
- result = []
-
- def add(package_name):
- package_dir = os.path.join(PLUGIN_SOURCE_ROOT, package_name)
-
- if not os.path.exists(package_dir):
- raise ValueError("Invalid plug-in package name: '%s'" % package_name)
-
- path = os.path.normpath(os.path.join(package_dir, subpath))
- if os.path.exists(path):
- result.append((package_name, path))
-
- add('common')
- if package_name not in (None, '', 'common'):
- add(package_name)
-
- return result
-
-
-def find_plugin_sources_by_package(package_name=None):
- """
- Return a list of plug-in source paths based on the given plug-in package name.
-
- The returned list always contains sources of common plug-ins, and
- additionally extra plug-in sources based on the given package name.
-
- @param package_name: Name of the extra plug-in package. Can be None, '',
- 'common' or an existing plug-in package.
- @raise ValueError: The given package_name was invalid.
- """
- result = []
-
- # Find all plug-in sources
- sources = find_all_plugin_sources(PLUGIN_SOURCE_ROOT)
-
- # Always return common plug-ins
- if 'common' in sources:
- for path, modname in sources['common']:
- result.append(path)
-
- # Return extra plug-ins if necessary
- if package_name not in (None, '', 'common'):
- if package_name not in sources:
- raise ValueError("Invalid plug-in package name: '%s'" % package_name)
- else:
- for path, modname in sources[package_name]:
- result.append(path)
-
- return result
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/runtests.py
--- a/configurationengine/source/plugins/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,22 +14,11 @@
# Description:
#
-import sys, os, re, unittest
-import plugin_utils
-
-ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
-
-if __name__ == "__main__":
- # Collect a list of plug-in source paths and plug-in module names
- sources = plugin_utils.find_all_plugin_sources(ROOT_PATH)
-
- # Flatten the source list
- flattened_sources = []
- for subpackage_name, paths_and_modnames in sources.iteritems():
- flattened_sources.extend(paths_and_modnames)
-
- # Create a test suite from them
- suite = plugin_utils.collect_suite_from_source_list(flattened_sources)
-
- # Run the suite
- unittest.TextTestRunner(verbosity=2).run(suite)
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector',
+ 'common',
+ 'example',
+ 'symbian',
+ '--include=unittest',
+ '--verbosity=3'])
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_impl.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_impl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_impl.py Tue Aug 10 14:29:28 2010 +0300
@@ -34,19 +34,43 @@
self.configuration = configuration
self.logger = logging.getLogger('cone.crml(%s)' % self.resource_ref)
self.repository = repository
-
+
+ def __getstate__(self):
+ state = super(CrmlImpl, self).__getstate__()
+ state['repository'] = self.__dict__.get('repository',None)
+ return state
+
+
def generate(self, context=None):
# Quick fix
if context:
self.generation_context = context
+
+ # See if delta CenReps should be generated
+ delta_cenrep = context and context.changed_refs is not None \
+ and 'deltacenrep' in context.tags.get('crml', [])
+
+ changed_refs = None
+ if delta_cenrep:
+ changed_refs = context.changed_refs
+
+ # Hard-coded output for delta CenReps for now
+ self.output_subdir = 'deltacenreps'
+ self.plugin_output = ''
+
file_path = self._get_cenrep_txt_file_path()
self.logger.debug("Generating file '%s'..." % file_path)
# Generate CenRep text data and write it to the output file
- writer = crml_writer.CrmlTxtWriter(self.configuration, self.logger)
- data = writer.get_cenrep_txt_data(self.repository).encode('UTF-16')
+ writer = crml_writer.CrmlTxtWriter(context, self.logger)
+ data = writer.get_cenrep_txt_data(self.repository, changed_refs).encode('UTF-16')
self._write_to_file(file_path, data)
+ # Add to the generated files list
+ KEY = 'crml_generated_cenrep_files'
+ lst = context.impl_data_dict.setdefault(KEY, [])
+ lst.append((os.path.basename(file_path), os.path.abspath(file_path)))
+
# Collect the record for cenrep_rfs.txt generation in post_generate()
if self.generation_context is not None:
@@ -137,12 +161,8 @@
return 'core' in targets or 'rofs2' in targets
def _write_to_file(self, file_path, data):
- # Create directories for the file if necessary
- file_dir = os.path.dirname(file_path)
- if file_dir != '' and not os.path.exists(file_dir):
- os.makedirs(file_dir)
# Write data
- f = open(file_path, "wb")
+ f = self.generation_context.create_file(file_path, implementation=self)
try: f.write(data)
finally: f.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_model.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_model.py Tue Aug 10 14:29:28 2010 +0300
@@ -86,6 +86,8 @@
self.cap_wr = kwargs.get('cap_wr')
self.sid_rd = kwargs.get('sid_rd')
self.sid_wr = kwargs.get('sid_wr')
+ self.line_rd = kwargs.get('line_rd')
+ self.line_wr = kwargs.get('line_wr')
class CrmlRepository(_CrmlObjectBase):
@@ -122,6 +124,7 @@
self.backup = kwargs.get('backup', False)
self.read_only = kwargs.get('read_only', False)
self.access = kwargs.get('access', CrmlAccess())
+ self.line = kwargs.get('line', None)
class CrmlSimpleKey(CrmlKeyBase, _CrmlObjectBase):
SIMPLE_EQ_VARNAMES = ['ref', 'name', 'int', 'type', 'backup', 'read_only', 'access']
@@ -174,6 +177,7 @@
self.invert = kwargs.get('invert', False)
except KeyError, e:
raise ValueError("Mandatory argument '%s' not given!" % e.message)
+ self.line = kwargs.get('line')
class CrmlKeyRange(CrmlKeyBase, _CrmlObjectBase):
SIMPLE_EQ_VARNAMES = ['ref', 'name', 'first_int', 'last_int', 'first_index', 'index_bits', 'count_int', 'backup', 'read_only', 'access', 'subkeys']
@@ -219,4 +223,5 @@
self.name = kwargs.get('name')
except KeyError, e:
raise ValueError("Mandatory argument '%s' not given!" % e.message)
+ self.line = kwargs.get('line')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_reader.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,8 +13,8 @@
#
# Description:
#
-
-from cone.public import exceptions, plugin
+import pkg_resources
+from cone.public import exceptions, plugin, utils
import crml_impl
from crml_model import *
@@ -44,6 +44,8 @@
class CrmlReader(plugin.ReaderBase):
NAMESPACE = 'http://www.s60.com/xml/cenrep/1'
+ NAMESPACE_ID = 'crml'
+ ROOT_ELEMENT_NAME = 'repository'
FILE_EXTENSIONS = ['crml']
@classmethod
@@ -52,6 +54,10 @@
repository = reader.read_repository(etree)
return crml_impl.CrmlImpl(resource_ref, configuration, repository)
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('CRMLPlugin', 'xsd/crml.xsd')
+
def read_repository(self, elem):
"""
Read a CrmlRepository object from the given XML element.
@@ -99,10 +105,12 @@
if type == 'R' and not read_cap_found:
access.cap_rd = access_elem.get('capabilities')
access.sid_rd = access_elem.get('sid')
+ access.line_rd = utils.etree.get_lineno(access_elem)
read_cap_found = True
elif type == 'W' and not write_cap_found:
access.cap_wr = access_elem.get('capabilities')
access.sid_wr = access_elem.get('sid')
+ access.line_wr = utils.etree.get_lineno(access_elem)
write_cap_found = True
return access
@@ -145,7 +153,8 @@
key = CrmlSimpleKey(
ref = get_required_attr(key_elem, 'ref').replace('/', '.'),
int = get_required_attr(key_elem, 'int'),
- type = key_elem.get('type', 'int'))
+ type = key_elem.get('type', 'int'),
+ line = utils.etree.get_lineno(key_elem))
self.read_common_key_attrs(key_elem, key)
return key
@@ -161,7 +170,8 @@
# Read attributes
key = CrmlBitmaskKey(
int = get_required_attr(key_elem, 'int'),
- type = key_elem.get('type', 'int'))
+ type = key_elem.get('type', 'int'),
+ line = utils.etree.get_lineno(key_elem))
self.read_common_key_attrs(key_elem, key)
# Read bits
@@ -171,7 +181,8 @@
else: invert = False
index = int(bit_elem.text.strip())
- key.bits.append(CrmlBit(ref=ref, index=index, type=type, invert=invert))
+ key.bits.append(CrmlBit(ref=ref, index=index, type=type, invert=invert,
+ line=utils.etree.get_lineno(bit_elem)))
return key
@@ -192,7 +203,8 @@
last_int = get_required_attr(key_range_elem, "lastInt"),
count_int = key_range_elem.get('countInt'),
first_index = convert_num(key_range_elem.get('firstIndex', '0')),
- index_bits = convert_num(key_range_elem.get('indexBits')))
+ index_bits = convert_num(key_range_elem.get('indexBits')),
+ line = utils.etree.get_lineno(key_range_elem))
self.read_common_key_attrs(key_range_elem, key_range)
# Read sub-keys
@@ -201,6 +213,7 @@
int = get_required_attr(subkey_elem, 'int')
name = subkey_elem.get('name')
type = subkey_elem.get('type', 'int')
- key_range.subkeys.append(CrmlKeyRangeSubKey(ref=ref, int=int, name=name, type=type))
+ key_range.subkeys.append(CrmlKeyRangeSubKey(ref=ref, int=int, name=name, type=type,
+ line=utils.etree.get_lineno(subkey_elem)))
return key_range
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_validators.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_validators.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,82 @@
+#
+# 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:
+#
+
+from cone.public import api, exceptions
+from cone.validation.implmlvalidation import ImplValidatorBase
+from CRMLPlugin import crml_impl
+from CRMLPlugin import crml_model
+
+class CrmlValidatorBase(ImplValidatorBase):
+ SUPPORTED_IMPL_CLASSES = crml_impl.CrmlImpl
+
+class CrmlReferenceValidator(CrmlValidatorBase):
+ PROBLEM_TYPES = ['model.implml.crml.invalid_ref']
+
+ def validate(self):
+ self.dview = self.context.configuration.get_default_view()
+
+ for key in self.impl.repository.keys:
+ if isinstance(key, crml_model.CrmlSimpleKey):
+ self._check_ref(key.ref, key.line)
+ elif isinstance(key, crml_model.CrmlBitmaskKey):
+ for bit in key.bits:
+ self._check_ref(bit.ref, bit.line)
+ elif isinstance(key, crml_model.CrmlKeyRange):
+ for subkey in key.subkeys:
+ fullref = "%s.%s" % (key.ref, subkey.ref)
+ self._check_ref(fullref, subkey.line)
+
+ def _check_ref(self, ref, line):
+ self.check_feature_reference(ref, line, self.PROBLEM_TYPES[0])
+
+class CrmlDuplicateUidValidator(CrmlValidatorBase):
+ PROBLEM_TYPES = ['model.implml.crml.duplicate_uid']
+
+ def validate(self):
+ # Collect a dictionary of CRML keys by UID
+ keys_by_uid = {}
+ for key in self.impl.repository.keys:
+ if isinstance(key, (crml_model.CrmlSimpleKey, crml_model.CrmlBitmaskKey)):
+ try:
+ try:
+ uid = long(key.int)
+ except ValueError:
+ uid = long(key.int, 16)
+ except ValueError:
+ # Silently ignore non-numeric UID values (they should be caught
+ # by other validation)
+ continue
+ keys = keys_by_uid.get(uid, [])
+ keys.append(key)
+ keys_by_uid[uid] = keys
+
+ # Check for duplicates
+ for uid, keys in keys_by_uid.iteritems():
+ if len(keys) > 1:
+ if len(keys) > 2:
+ key_lst = "keys on lines %s" % ', '.join([str(key.line) for key in keys[:-2]])
+ key_lst += ' and %s' % keys[-2].line
+ else:
+ key_lst = "key on line %s" % keys[-2].line
+ prob = api.Problem(
+ msg = "Duplicate key UID 0x%08X (duplicate with %s)" % (uid, key_lst),
+ type = self.PROBLEM_TYPES[0],
+ line = keys[-1].line,
+ file = self.impl.ref)
+ self.context.problems.append(prob)
+
+
+VALIDATOR_CLASSES = [CrmlReferenceValidator, CrmlDuplicateUidValidator]
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_writer.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/crml_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,7 +14,7 @@
# Description:
#
import re
-from cone.public import exceptions
+from cone.public import exceptions, plugin
import crml_reader
from crml_model import *
@@ -58,39 +58,47 @@
def __repr__(self):
return "CenRepRfsRecord(repo_uid=%s, key_uids=%r)" % (self.repo_uid, self.key_uids)
-
class CrmlTxtWriter(object):
"""
Writer class for generating CenRep .txt files based on a CRML model.
"""
- def __init__(self, configuration, log):
- self.configuration = configuration
+ def __init__(self, context, log):
+ self.context = context
self.log = log
- def get_cenrep_txt_data(self, repository):
+ def get_cenrep_txt_data(self, repository, changed_refs=None):
"""
Return the text data for the CenRep txt generated based on the given
CRML repository model.
+ @param changed_refs: List of changed refs. If this is passed, only a delta
+ CenRep txt file is generated (i.e. containing only the changed settings).
+ If None, the whole CenRep file is generated normally.
@return: Text data for the CenRep text file.
"""
+ delta_cenrep = changed_refs is not None
data = []
# Generate header lines
- data.extend(self.get_header_lines(repository))
+ data.extend(self.get_header_lines(repository, delta_cenrep))
self._check_repository_attrs(repository)
# Generate CenRep entries for all keys
cenrep_entries = []
for key in repository.keys:
+ # If generating a delta CenRep file, ignore keys that don't
+ # use any of the changed settings
+ if delta_cenrep:
+ if not plugin.uses_ref(changed_refs, key.get_refs()):
+ continue
cenrep_entries.extend(self.get_cenrep_entries(key))
# Generate entry lines based on the entries
cenrep_entries.sort()
for entry in cenrep_entries:
- data.append(self.get_cenrep_entry_line(entry))
+ data.append(self.get_cenrep_entry_line(entry, delta_cenrep))
data.append('')
@@ -179,30 +187,34 @@
return feature.get_value(attr='rfs')
- def get_header_lines(self, repository):
+ def get_header_lines(self, repository, delta_cenrep=False):
"""
Return a list of lines to be written in the header section of the CenRep text file.
+ @param delta_cenrep: If True, only the data needed for a delta CenRep
+ file is returned.
"""
data = ['cenrep',
'version %s' % repository.version]
+ # Owner seems to be required even for delta CenReps
if repository.owner:
data.append('[owner]')
data.append(repository.owner)
data.append('[defaultmeta]')
- data.append(' %d' % _get_metadata(repository.backup))
- for key in repository.keys:
- data.append(self.get_defaultmeta_line(key))
+ if not delta_cenrep:
+ data.append(' %d' % _get_metadata(repository.backup))
+ for key in repository.keys:
+ data.append(self.get_defaultmeta_line(key))
data.append('[platsec]')
- acc_text = self.get_access_line(repository.access)
- if acc_text: acc_text = ' ' + acc_text
- data.append(acc_text)
- for key in repository.keys:
+ if not delta_cenrep:
+ acc_text = self.get_access_line(repository.access)
+ if acc_text: acc_text = ' ' + acc_text
+ data.append(acc_text)
+ for key in repository.keys:
data.append(self.get_platsec_line(key, repository))
-
data.append('[Main]')
return data
@@ -369,9 +381,11 @@
acc_text)
- def get_cenrep_entry_line(self, entry):
+ def get_cenrep_entry_line(self, entry, delta_cenrep=False):
"""
Return the text line for a CenRepEntry object.
+ @param delta_cenrep: If True, only the data needed for a delta CenRep
+ file is returned.
"""
value = None
if entry.crml_type in ('string', 'string8'):
@@ -404,14 +418,20 @@
self._check_value(entry, value)
- acc_text = self.get_access_line(entry.access)
- if acc_text: acc_text = ' ' + acc_text
-
- return '%s %s %s %d%s' % (_translate_key_uid(entry.int),
- entry.crml_type,
- value,
- entry.metadata,
- acc_text)
+ if delta_cenrep:
+ return '%s %s %s' % (_translate_key_uid(entry.int),
+ entry.crml_type,
+ value)
+ else:
+ acc_text = self.get_access_line(entry.access)
+ if acc_text: acc_text = ' ' + acc_text
+
+ return '%s %s %s %d%s' % (_translate_key_uid(entry.int),
+ entry.crml_type,
+ value,
+ entry.metadata,
+ acc_text)
+
def _check_value(self, entry, value):
"""
Check that the given value is valid for the given CenRep entry,
@@ -476,7 +496,7 @@
return ' '.join(data)
def _get_feature(self, ref):
- return self.configuration.get_default_view().get_feature(ref)
+ return self.context.configuration.get_default_view().get_feature(ref)
@classmethod
def get_index(cls,firstInt,firstIndex,indexBits,seqIndex, subIndex):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,28 +13,11 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-
-SCRIPTS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../../..', "scripts"))
-assert os.path.exists(SCRIPTS_ROOT)
-os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + ';' + SCRIPTS_ROOT + ';' + PLUGINS_ROOT
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected/0000000E.txt
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected/0000000E.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000002.txt
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000002.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000003.txt
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000003.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000005.txt
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000005.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000006.txt
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_expected_deltacenrep/00000006.txt has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer1/implml/deltacenrep_iby.implml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer1/implml/deltacenrep_iby.implml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+#ifndef __DELTA_CENREPS_IBY
+#define __DELTA_CENREPS_IBY
+
+{% for output in gen_context.get_output(implml_type='crml') -%}
+data = {{output.name}} private\10202BE9\{{output.filename}} exattrib=U
+{% endfor %}
+
+#endif // __DELTA_CENREPS_IBY
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer2/confml/data.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer2/confml/data.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,28 @@
+
+
+
+
+ 50
+ 0xB
+
+
+ 50.5
+ 11.1
+
+
+
+
+ 1001
+ test 1
+
+
+ 1002
+ test 2
+
+
+
+ true
+ true
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer2/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/Layer2/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/root2.confml
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/gen_project/root2.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_comparator.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_comparator.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_comparator.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,7 @@
#
import unittest
-import __init__
+
from cone.public import plugin
from CRMLPlugin.crml_model import *
from CRMLPlugin.crml_comparator import CrmlComparator
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_impl.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_impl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_impl.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import sys, os, unittest
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -55,19 +54,19 @@
self.assertFalse(impl.has_ref(['KeyRangeTest.Foo']))
def test_list_output_files(self):
- def oj( p2): # oj = output_join
- return os.path.normpath(os.path.join('output', p2))
+ def on( p2): # on = output normalization
+ return os.path.normpath(p2)
impl = impl_from_resource('Layer1/implml/00000001_feature1.crml', self.config)
- self.assertEquals(impl.list_output_files(), [oj('00000001.txt')])
+ self.assertEquals(impl.list_output_files(), [on('00000001.txt')])
impl = impl_from_resource('Layer1/implml/00000003_bitmask_test.crml', self.config)
- self.assertEquals(impl.list_output_files(), [oj('00000003.txt')])
+ self.assertEquals(impl.list_output_files(), [on('00000003.txt')])
gc = MockGenerationContext()
gc.tags['target'] = ['core']
impl.generation_context = gc
- self.assertEquals(impl.list_output_files(), [oj('00000003.txt'), oj('private/100059C9/cenrep_rfs.txt')])
+ self.assertEquals(impl.list_output_files(), [on('00000003.txt'), on('private/100059C9/cenrep_rfs.txt')])
def test_is_cenrep_rfs_txt_to_be_generated(self):
impl = impl_from_resource('Layer1/implml/00000001_feature1.crml', self.config)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_model.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_model.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_model.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import unittest
-import __init__
from cone.public import api, exceptions
from CRMLPlugin.crml_model import *
@@ -104,6 +103,10 @@
access = CrmlAccess(cap_rd='ReadUserData'),
keys = keys)
+ def test_create_empty_repo(self):
+ repo = CrmlRepository()
+ self.assertEquals(repo.get_refs(), [])
+
def test_create_repo_object(self):
repo = CrmlRepository()
self.assertEquals(repo.uid_value, None)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_reader.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,23 +14,11 @@
# Description:
#
-import sys, os, unittest
-import __init__
+import os, unittest
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-try:
- from cElementTree import ElementTree
-except ImportError:
- try:
- from elementtree import ElementTree
- except ImportError:
- try:
- from xml.etree import cElementTree as ElementTree
- except ImportError:
- from xml.etree import ElementTree
-
-from cone.public import exceptions, plugin, api, container
+from cone.public import exceptions, plugin, api, container, utils
from CRMLPlugin.crml_model import *
from CRMLPlugin.crml_reader import CrmlReader
@@ -43,7 +31,7 @@
self.reader = CrmlReader()
def assert_read_access_equals(self, data, expected):
- etree = ElementTree.fromstring(data)
+ etree = utils.etree.fromstring(data)
access = self.reader.read_access(etree)
self.assertEquals(expected, access)
@@ -59,7 +47,33 @@
""" % self.NAMESPACE
self.assert_read_access_equals(data,
CrmlAccess(cap_rd='AlwaysPass', cap_wr='WriteDeviceData', sid_rd='0x12345678', sid_wr='0x87654321'))
-
+
+ def test_get_refs(self):
+ data = """
+
+
+
+
+
+
+
+ """ % self.NAMESPACE
+ etree = utils.etree.fromstring(data)
+ repo = self.reader.read_repository(etree)
+ self.assertEquals(repo.get_refs(), ['Feature1.IntSetting'])
+
+ data = """
+
+
+
+
+ """ % self.NAMESPACE
+ etree = utils.etree.fromstring(data)
+ repo = self.reader.read_repository(etree)
+ self.assertEquals(repo.get_refs(), [])
+
+
+
def test_read_duplicate_access(self):
data = """
@@ -74,7 +88,7 @@
def read_key_from_xml(self, data):
- etree = ElementTree.fromstring(data)
+ etree = utils.etree.fromstring(data)
return self.reader.read_key(etree)
def assert_read_key_equals(self, data, expected):
@@ -96,7 +110,7 @@
self.assertRaises(exceptions.ParseError, self.read_key_from_xml, data)
def assert_read_bitmask_key_equals(self, data, expected):
- etree = ElementTree.fromstring(data)
+ etree = utils.etree.fromstring(data)
key = self.reader.read_bitmask_key(etree)
self.assertEquals(expected, key)
@@ -122,7 +136,7 @@
CrmlBit(ref='BitmaskTest.Bit5', index=6, invert=True)]))
def assert_read_key_range_equals(self, data, expected):
- etree = ElementTree.fromstring(data)
+ etree = utils.etree.fromstring(data)
key = self.reader.read_key_range(etree)
self.assertEquals(expected, key)
@@ -157,7 +171,7 @@
CrmlKeyRangeSubKey(ref='IntSubSetting2', name='Int2', int='0x0003', type='int')]))
def assert_read_repo_equals(self, data, expected):
- etree = ElementTree.fromstring(data)
+ etree = utils.etree.fromstring(data)
key = self.reader.read_repository(etree)
self.assertEquals(expected, key)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_validation.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_validation.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,45 @@
+#
+# 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:
+#
+
+import os
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+from testautomation.base_testcase import BaseTestCase
+from cone.public import api
+import cone.validation.implmlvalidation
+
+class TestCrmlValidation(BaseTestCase):
+
+ def _run_test(self, filename):
+ filepath = 'Layer1/implml/' + filename
+ project_dir = os.path.join(ROOT_PATH, 'validation_project')
+ config = 'root.confml'
+
+ prj = api.Project(api.Storage.open(project_dir))
+ config = prj.get_configuration(config)
+ problems = cone.validation.implmlvalidation.validate_impls(config, filter=filepath + '$')
+
+ self.assert_problem_list_equals_expected(
+ actual = problems,
+ expected_file = os.path.join(ROOT_PATH, 'validation_expected', filename + '.txt'),
+ outdir = os.path.join(ROOT_PATH, 'temp/validation', filename))
+
+ def test_validate_invalid_refs(self):
+ self._run_test('00000002_invalid_refs.crml')
+
+ def test_validate_duplicate_uids(self):
+ self._run_test('00000003_duplicate_uids.crml')
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_writer.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_crml_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import sys, os, unittest, logging
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -66,7 +65,8 @@
class TestCrmlTxtWriter(unittest.TestCase):
def setUp(self):
- self.writer = CrmlTxtWriter(MockConfiguration(), log)
+ self.context = plugin.GenerationContext(configuration=MockConfiguration())
+ self.writer = CrmlTxtWriter(self.context, log)
def test_write_access(self):
def check(acc, expected):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_txt_generation.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_txt_generation.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/unittest_txt_generation.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,12 +15,11 @@
#
import sys, os, unittest
-import __init__
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
from testautomation.base_testcase import BaseTestCase
-from cone.public import exceptions, plugin, api, container
+from cone.public import exceptions, plugin, api, container, utils
from CRMLPlugin import crml_impl
@@ -39,11 +38,14 @@
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration(config)
+ gc = plugin.GenerationContext(configuration=config,
+ output=output_dir)
+
impls = plugin.get_impl_set(config, 'crml$')
- impls.output = output_dir
- impls.generation_context.tags['target'] = ['rofs2']
- impls.generate()
- impls.post_generate()
+ gc.tags['target'] = ['rofs2']
+ gc.filtering_disabled = True
+ impls.generate(gc)
+ impls.post_generate(gc)
self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn'])
@@ -57,11 +59,14 @@
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration(config)
+ gc = plugin.GenerationContext(configuration=config,
+ output=output_dir)
+
impls = plugin.get_impl_set(config, 'crml$')
- impls.output = output_dir
- impls.generation_context.tags['target'] = []
- impls.generate()
- impls.post_generate()
+ gc.tags['target'] = []
+ gc.filtering_disabled = True
+ impls.generate(gc)
+ impls.post_generate(gc)
self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn', 'private'])
self.assertFalse(os.path.exists(os.path.join(output_dir, 'private/100059C9/cenrep_rfs.txt')))
@@ -77,11 +82,41 @@
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration(config)
+ gc = plugin.GenerationContext(configuration=config,
+ output=output_dir)
impls = plugin.get_impl_set(config, 'crml$')
- impls.output = output_dir
- impls.generation_context.tags['target'] = ['rofs2']
- impls.generate()
- impls.post_generate()
+ gc.tags['target'] = ['rofs2']
+ gc.filtering_disabled = True
+ impls.generate(gc)
+ impls.post_generate(gc)
self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn'])
+ def test_generate_delta_cenreps(self):
+ project_dir = abspath('gen_project')
+ config = 'root2.confml'
+ output_dir = abspath('temp/gen_output_deltacenrep')
+ expected_dir = abspath('gen_expected_deltacenrep')
+
+ self.remove_if_exists(output_dir)
+
+ prj = api.Project(api.Storage.open(project_dir))
+ config = prj.get_configuration(config)
+ gc = plugin.GenerationContext(configuration=config,
+ output=output_dir)
+ # Get refs from the last layer
+ layer = config.get_configuration_by_index(-1)
+ refs = utils.distinct_array(layer.list_leaf_datas())
+
+ impls = plugin.get_impl_set(config, 'crml$')
+ impls = impls | plugin.get_impl_set(config, 'implml$')
+ impls = impls.filter_implementations(refs=refs)
+
+ gc.tags['crml'] = ['deltacenrep']
+ gc.changed_refs = refs
+ gc.filtering_disabled = True
+ impls.generate(gc)
+ impls.post_generate(gc)
+
+ output_dir = os.path.join(output_dir, 'deltacenreps')
+ self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_expected/00000002_invalid_refs.crml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_expected/00000002_invalid_refs.crml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+Problem(msg=u"Setting 'Foo.Bar' not found in configuration", type='model.implml.crml.invalid_ref', line=6, file='Layer1/implml/00000002_invalid_refs.crml', severity='error')
+Problem(msg=u"Setting 'Foo.Bit0' not found in configuration", type='model.implml.crml.invalid_ref', line=9, file='Layer1/implml/00000002_invalid_refs.crml', severity='error')
+Problem(msg=u"Setting 'Foo.Bit1' not found in configuration", type='model.implml.crml.invalid_ref', line=10, file='Layer1/implml/00000002_invalid_refs.crml', severity='error')
+Problem(msg=u"Setting 'Foo.Sequence.Bar' not found in configuration", type='model.implml.crml.invalid_ref', line=14, file='Layer1/implml/00000002_invalid_refs.crml', severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_expected/00000003_duplicate_uids.crml.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_expected/00000003_duplicate_uids.crml.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+Problem(msg='Duplicate key UID 0x00000001 (duplicate with keys on lines 6, 7 and 8)', type='model.implml.crml.duplicate_uid', line=13, file='Layer1/implml/00000003_duplicate_uids.crml', severity='error')
+Problem(msg='Duplicate key UID 0x00000002 (duplicate with key on line 10)', type='model.implml.crml.duplicate_uid', line=11, file='Layer1/implml/00000003_duplicate_uids.crml', severity='error')
+# TODO: Validation for these is still missing
+#api.Problem(msg='Duplicate bit 1 (duplicate with bits on lines 14, 15 and 16)', type=TYPE, line=17, file=FILE, severity='error'),
+#api.Problem(msg='Duplicate bit 2 (duplicate with bit on line 19)', type=TYPE, line=20, file=FILE, severity='error'),
+#api.Problem(msg='Duplicate sub-key UID 0x00000001 (duplicate with sub-keys on lines 24, 25 and 26)', type=TYPE, line=27, file=FILE, severity='error'),
+#api.Problem(msg='Duplicate sub-key UID 0x00000002 (duplicate with sub-key on line 29)', type=TYPE, line=30, file=FILE, severity='error')
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/duplicate_uids.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/duplicate_uids.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+
+ true
+ false
+ true
+ false
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/invalid_capabilities.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/invalid_capabilities.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/multiple_access_definitions.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/confml/multiple_access_definitions.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+
+ true
+ false
+ true
+
+
+ 1
+ 2
+ 3
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000002_invalid_refs.crml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000002_invalid_refs.crml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+ 1
+ 2
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000003_duplicate_uids.crml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000003_duplicate_uids.crml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+ 1
+ 1
+
+ 2
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000004_invalid_capabilities.crml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000004_invalid_capabilities.crml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000005_multiple_access_definitions.crml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/implml/00000005_multiple_access_definitions.crml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/Layer1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/root.confml
Binary file configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/tests/validation_project/root.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/xsd/crml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/CRMLPlugin/xsd/crml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeCRMLPlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeCRMLPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeCRMLPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conecrmlplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'CRMLPlugin': ['xsd/*.xsd']},
test_suite = "crmlplugin.tests.collect_suite",
# metadata for upload to PyPI
@@ -34,5 +35,6 @@
zip_safe = True,
# entrypoint info
- entry_points={'cone.plugins.implmlreaders': ['crml = CRMLPlugin.crml_reader:CrmlReader']}
+ entry_points={'cone.plugins.implmlreaders': ['crml = CRMLPlugin.crml_reader:CrmlReader'],
+ 'cone.plugins.implvalidators': ['crml = CRMLPlugin.crml_validators:VALIDATOR_CLASSES']}
)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/confflattener.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/confflattener.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/confflattener.py Tue Aug 10 14:29:28 2010 +0300
@@ -82,8 +82,14 @@
toview = to_config.get_default_view()
for fea in toview.get_features('**'):
fromfea = dview_from.get_feature(fea.fqr)
- if fromfea.get_value() != None:
- fea.set_value(fromfea.get_value())
+ # If the value is an empty list, don't add it.
+ # This is because an empty list means that we have
+ # a sequence setting or sequence sub-setting that doesn't have
+ # any contents, and calling set_value() would create a data
+ # element for it with the attribute empty="true".
+ val = fromfea.get_value()
+ if val not in (None, []):
+ fea.set_value(val)
return to_config
def create_configuration(self, conf_from_org, settings, path="tempfile.confml"):
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -26,6 +26,7 @@
import xslttransformer
import codecs
import tempfile
+import pkg_resources
import tempfile
try:
@@ -39,7 +40,6 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
from cone.public import exceptions,plugin,utils,api
from cone.confml import persistentconfml
@@ -52,7 +52,7 @@
IMPL_TYPE_ID = "gcfml"
- def __init__(self,ref,configuration, output='output', linesep=os.linesep, reader=None):
+ def __init__(self,ref,configuration, output='', linesep=os.linesep, reader=None):
"""
Overloading the default constructor
"""
@@ -63,7 +63,7 @@
self.xslt_temp_file_name = os.path.join(tempfile.gettempdir(), "genconfml_temp_%i.xslt" % os.getpid())
self.set_output_root(output)
self.linesep = linesep
- self._flatconfig = None
+ self.flatconfig = None
self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
self.reader = reader
@@ -71,19 +71,28 @@
"""
Generate the given implementation.
"""
+ self.context = context
self.create_output()
return
def get_refs(self):
+ """
+ Get the list of references used inside this gcfml object.
+ """
result = []
+ refs = []
for ref in self.reader.settings:
# Process the reference, so that it will work with has_ref().
# E.g. 'MyFeature/MySetting' -> 'MyFeature.MySetting'
# 'MyFeature/* -> 'MyFeature'
ref = ref.replace('/', '.')
- if ref.endswith('.*'):
- ref = ref[:-2]
- result.append(ref)
+ refs.append(ref)
+
+ # Traverse through actual features in the default view, to get a full list
+ # of refs in case of wildcard usage
+ dview = self.configuration.get_default_view()
+ for fea in dview.get_features(refs):
+ result.append(fea.fqr)
return result
def list_output_files(self):
@@ -113,7 +122,7 @@
""" Generate all output """
resource = self.configuration.get_resource(self.ref)
write_element_enc(self.reader.stylesheet_elem, self.xslt_temp_file_name, self.reader.stylesheet_output_enc)
- gen = Generator()
+ gen = Generator(self)
target = self.reader.target
if target == None: target = ""
@@ -126,10 +135,12 @@
self.logger.info('Generating %s' % output_file)
- flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.flatconfig)
+ flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.get_flatconfig())
postprocessed_element = self.post_process_flattening(flatted_conf_as_element)
write_element_enc(postprocessed_element, self.temp_confml_file, self.reader.stylesheet_output_enc)
- gen.generate(self.configuration, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc)
+ gen.generate(self.context, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc,
+ line_ending_style = self.reader.line_ending_style)
+
def post_process_flattening(self, element):
"""
@@ -144,21 +155,20 @@
new_doc = "" + ElementTree.tostring(data_element) + ""
return ElementTree.fromstring(new_doc)
- @property
- def flatconfig(self):
- """
- Create a flat configuration from the current configuration with the given setting refs.
- Take the last configuration element, which will contain the data elements
- """
- if not self._flatconfig:
- try:
- cf = confflattener.ConfigurationFlattener()
- self._flatconfig = api.Configuration()
- cf.flat(self.configuration, self.reader.settings, self._flatconfig)
- except (exceptions.ConeException, TypeError, Exception), e:
- utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e))
- raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e)
- return self._flatconfig
+ def get_flatconfig(self):
+ """
+ Create a flat configuration from the current configuration with the given setting refs.
+ Take the last configuration element, which will contain the data elements
+ """
+ if not self.flatconfig:
+ try:
+ cf = confflattener.ConfigurationFlattener()
+ self.flatconfig = api.Configuration()
+ cf.flat(self.configuration, self.reader.settings, self.flatconfig)
+ except (exceptions.ConeException, TypeError, Exception), e:
+ utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e))
+ raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e)
+ return self.flatconfig
def write_element(element, output, linesep=os.linesep):
@@ -221,7 +231,7 @@
try:
tempfile.write(ElementTree.tostring(element))
except Exception, e:
- raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (tempfile, e))
else:
raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.')
@@ -230,6 +240,8 @@
Parses a single gcfml file
"""
NAMESPACE = 'http://www.s60.com/xml/genconfml/1'
+ NAMESPACE_ID = 'gcfml'
+ ROOT_ELEMENT_NAME = 'file'
IGNORED_NAMESPACES = ['http://www.w3.org/1999/XSL/Transform',
'http://www.w3.org/2001/xinclude']
FILE_EXTENSIONS = ['gcfml']
@@ -251,17 +263,27 @@
reader = GenconfmlImplReader()
reader.from_etree(etree)
return GenconfmlImpl(resource_ref, configuration, reader=reader)
-
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('genconfmlplugin', 'xsd/gcfml.xsd')
+
def from_etree(self, etree):
self.stylesheet = self.parse_stylesheet(etree)
self.settings = self.parse_settings(etree)
- self.name = self.parse_name(etree)
- self.subdir = self.parse_subdir(etree)
- self.target = self.parse_target(etree)
+ self.target = etree.get('target', '')
+ self.name = etree.get('name', '')
+ self.subdir = etree.get('subdir', '')
+ self.line_ending_style = etree.get('lineEndingStyle')
self.stylesheet_elem = self.parse_stylesheet_elem(etree)
self.stylesheet_output_enc = self.parse_stylesheet_output_enc(etree)
self.nss = self.parse_stylesheet_nss(etree)
+ if self.line_ending_style not in (None, 'CRLF', 'LF'):
+ raise exceptions.ImplmlParseError(
+ "Invalid line ending style '%s' (should be omitted or one "
+ "of ['CRLF', 'LF'])" % self.line_ending_style)
+
return
def parse_target(self, etree):
@@ -271,8 +293,8 @@
target = ""
for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
- if elem != None:
- target = elem.get('target')
+ if elem != None:
+ target = elem.get('target')
return target
@@ -283,8 +305,8 @@
name = ""
for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
- if elem != None:
- name = elem.get('name')
+ if elem != None:
+ name = elem.get('name')
return name
@@ -295,8 +317,8 @@
subdir = ""
for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
- if elem != None:
- subdir = elem.get('subdir')
+ if elem != None:
+ subdir = elem.get('subdir')
if subdir == None:
subdir = ""
@@ -350,21 +372,21 @@
settings = []
for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
- if elem != None:
- setting_elems = elem.findall("{%s}setting" % self.namespaces[2])
- for setting_elem in setting_elems:
- if setting_elem != None:
- settings.append(setting_elem.get('ref'))
-
+ if elem != None:
+ setting_elems = elem.findall("{%s}setting" % self.namespaces[2])
+ for setting_elem in setting_elems:
+ if setting_elem != None:
+ settings.append(setting_elem.get('ref'))
return settings
class Generator(object):
"""
Genconfml generator
"""
- def __init__(self):
+ def __init__(self, implml):
self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
- pass
+ self.context = None
+ self.implml = implml
def post_process_flattening(self, element):
"""
@@ -380,17 +402,25 @@
return ElementTree.fromstring(new_doc)
- def generate(self, configuration, input, output, xslt, settings, enc=sys.getdefaultencoding()):
+ def generate(self, context, input, output, xslt, settings, enc=sys.getdefaultencoding(),
+ line_ending_style=None):
"""
Generates output
"""
+ self.context = context
self.logger = logging.getLogger('cone.gcfml{%s}' % input.path)
+ if line_ending_style == 'LF':
+ linesep = '\n'
+ else:
+ linesep = '\r\n'
try:
tf = xslttransformer.XsltTransformer()
- tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
- #tf.transform_4s(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
+ result = tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), enc, linesep)
+ if not self.filter_file_writing(result):
+ self.write_string_to_file(result, output, enc)
+
except (exceptions.ConeException, TypeError, Exception), e:
logging.getLogger('cone.gcfml').warning('Failed to do XSLT tranformation. Exception: %s' % e)
raise exceptions.ConeException('Failed to do XSLT tranformation. Exception: %s' % e)
@@ -399,3 +429,32 @@
if not logging.getLogger('cone').getEffectiveLevel() != 10:
os.remove(os.path.abspath(self.temp_confml_file))
os.remove(os.path.abspath(xslt))
+
+ def filter_file_writing(self, string):
+ """
+ Returns True if writing result file should be ignored.
+ """
+ string = string.rstrip('\n\r')
+ if string == '' or string == '' or \
+ string == '':
+ return True
+
+ return False
+
+ def write_string_to_file(self, string, output, enc):
+ """
+ Writes string to file
+ """
+ try:
+
+ #fl = codecs.open(outfile, 'w', enc)
+ fl = self.context.create_file(output,
+ implementation=self.implml,
+ mode='w',
+ encoding=enc)
+ fl.write(string)
+ fl.close()
+
+ except Exception, e:
+ logging.getLogger('cone.gcfml').error('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,12 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root1/endline_crlf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root1/endline_crlf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+default 1
+default 2
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root1/endline_lf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root1/endline_lf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+default 1
+default 2
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root2/endline_crlf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root2/endline_crlf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+default 1
+default 2
+layer2 (1)
+layer2 (2)
+layer2 (3)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root2/endline_lf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root2/endline_lf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,7 @@
+
+default 1
+default 2
+layer2 (1)
+layer2 (2)
+layer2 (3)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root3/endline_crlf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root3/endline_crlf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,9 @@
+
+layer3 (2)
+layer3 (1)
+default 1
+default 2
+layer2 (1)
+layer2 (2)
+layer2 (3)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root3/endline_lf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root3/endline_lf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,9 @@
+
+layer3 (2)
+layer3 (1)
+default 1
+default 2
+layer2 (1)
+layer2 (2)
+layer2 (3)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root4/endline_crlf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root4/endline_crlf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+layer4 (1)
+layer4 (2)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root4/endline_lf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/expected/root4/endline_lf.txt Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+layer4 (1)
+layer4 (2)
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/Layer1/implml/line_ending_conversion_crlf.gcfml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/Layer1/implml/line_ending_conversion_crlf.gcfml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/Layer1/implml/line_ending_conversion_lf.gcfml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/Layer1/implml/line_ending_conversion_lf.gcfml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/assets/s60/implml/commsdatcreator_01.gcfml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/project/assets/s60/implml/commsdatcreator_01.gcfml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_confflattener.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_confflattener.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_confflattener.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,14 +14,12 @@
# Description:
#
-import unittest, os, shutil
+import unittest, os
import copy
-import __init__
from genconfmlplugin import confflattener
-from cone.public import exceptions,plugin,api
+from cone.public import api
from cone.storage import filestorage
-from cone.confml import implml
# Hardcoded value of testdata folder that must be under the current working dir
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_gcfml_plugin.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_gcfml_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_gcfml_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,13 +14,12 @@
# Description:
#
-import unittest, os, shutil
+import unittest, os
-import __init__
from genconfmlplugin import genconfmlplugin
-from cone.public import exceptions,plugin,api
+from cone.public import plugin,api
from cone.storage import filestorage
-from cone.confml import implml
+
try:
from cElementTree import ElementTree
@@ -154,6 +153,16 @@
self.assertTrue(impl.has_ref(['Contacts.Contact.FirstName']))
self.assertFalse(impl.has_ref(['Contacts.OtherSetting']))
+ def test_get_refs(self):
+ fs = filestorage.FileStorage(testdata)
+ p = api.Project(fs)
+ config = p.get_configuration('product.confml')
+ impls = plugin.get_impl_set(config,'\.gcfml$')
+ impls.output = self.output
+ impl = impls.get_implementations_by_file('assets/s60/implml/commsdatcreator_01.gcfml')[0]
+ self.assertEquals(impl.get_refs(), ['APs.AP', 'WLAN_APs.WLAN_AP'])
+ self.assertTrue(impl.has_ref(['APs.AP']))
+
def test_list_output_files(self):
fs = filestorage.FileStorage(testdata)
p = api.Project(fs)
@@ -161,7 +170,10 @@
impls = plugin.get_impl_set(config,'\.gcfml$')
impls.output = self.output
impl = impls.get_implementations_by_file('assets/s60/implml/predefinedcontacts.gcfml')[0]
- self.assertEquals(impl.list_output_files(), ['output\\private\\2000BEE5\\predefinedcontacts.xml'])
+
+ normalize_slash = lambda l: map(lambda p: p.replace('\\', '/'), l)
+ self.assertEquals(normalize_slash(impl.list_output_files()),
+ ['private/2000BEE5/predefinedcontacts.xml'])
if __name__ == '__main__':
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_generation.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_generation.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_generation.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,13 +14,12 @@
# Description:
#
-import sys, os, unittest
-import __init__
+import os
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
from testautomation.base_testcase import BaseTestCase
-from cone.public import exceptions, plugin, api, container
+from cone.public import plugin, api
def abspath(path):
return os.path.normpath(os.path.join(ROOT_PATH, path))
@@ -43,8 +42,10 @@
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration(config)
+ context = plugin.GenerationContext(configuration=config,
+ output=output_dir)
+ context.filtering_disabled = True
impls = plugin.get_impl_set(config, 'gcfml$')
- impls.output = output_dir
- impls.generate()
+ impls.generate(context)
self.assert_dir_contents_equal(output_dir, expected_dir, ['.svn'] + ignores)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_xslttransformer.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_xslttransformer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/tests/unittest_xslttransformer.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,19 +14,17 @@
# Description:
#
-import unittest, os, shutil, sys
+import unittest, os, sys
-import __init__
from genconfmlplugin import xslttransformer
-from cone.public import exceptions,plugin,api
-from cone.storage import filestorage
-from cone.confml import implml
# Hardcoded value of testdata folder that must be under the current working dir
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
testdata = os.path.join(ROOT_PATH,'project')
+expected = u'\r\n
My CD Collection
\r\n
\r\n
\r\n
Title
\r\n
Artist
\r\n
\r\n
\r\n
.
\r\n
.
\r\n
\r\n
\r\n\r\n\r\n'.replace('\r\n', os.linesep)
-class TestGenconfmlPlugin(unittest.TestCase):
+
+class TestXstlTransformer(unittest.TestCase):
def setUp(self):
self.curdir = os.getcwd()
self.output = 'output'
@@ -40,12 +38,11 @@
Test that the xslt transformation works
'''
transformer = xslttransformer.XsltTransformer()
- transformer.transform_lxml(os.path.join(ROOT_PATH,"xslt\cdcatalog.xml"),
- os.path.join(ROOT_PATH,"xslt\cdcatalog_ex1.xsl"),
- "testioutput.xml",
+ result = transformer.transform_lxml(os.path.join(ROOT_PATH,"xslt/cdcatalog.xml"),
+ os.path.join(ROOT_PATH,"xslt/cdcatalog_ex1.xsl"),
sys.getdefaultencoding())
- os.unlink("testioutput.xml")
+ self.assertEquals(result, expected)
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/xsd/gcfml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/xsd/gcfml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/xslttransformer.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/xslttransformer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/xslttransformer.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,30 +18,14 @@
'''
-import re
import os
import sys
-import codecs
import logging
-import xml.parsers.expat
-import unittest, os, sys, pkg_resources
+import pkg_resources
pkg_resources.require('lxml')
-try:
- from cElementTree import ElementTree
-except ImportError:
- try:
- from elementtree import ElementTree
- except ImportError:
- try:
- from xml.etree import cElementTree as ElementTree
- except ImportError:
- from xml.etree import ElementTree
-
-import __init__
-
-from cone.public import exceptions,plugin,utils,api
+from cone.public import exceptions
class XsltTransformer():
"""
@@ -52,117 +36,51 @@
self.logger = logging.getLogger('cone.gcfml(%s)' % self.ref)
- def transform_lxml(self, input, xslt, output, enc, linesep=os.linesep):
- """
- XSLT transform with lxml.
- """
- from lxml import etree
-
- if not enc:
- enc = sys.getdefaultencoding()
- try:
- xslt_doc = etree.parse(xslt)
- transform = etree.XSLT(xslt_doc)
-
- input_doc = etree.parse(input)
- result = str(transform(input_doc))
- postprocessed_result = post_process_result(result, enc, linesep)
-
- if not filter_file_writing(postprocessed_result):
- write_string_to_file(postprocessed_result, output, enc)
+ def transform_lxml(self, input, xslt, enc, linesep=os.linesep):
+ """
+ XSLT transform with lxml.
+ """
+ from lxml import etree
- except Exception, e:
- logging.getLogger('cone.gcfml').error('Failed to do XSLT transformation: %s' % e)
- raise exceptions.ConeException('Failed to do XSLT transformation: %s' % (e))
-
-
- def transform_4s(self, input, xslt, output, enc, linesep=os.linesep):
- """
- XSLT transform with 4Suite
- """
- from Ft.Xml.Xslt import Transform
- from Ft.Xml.Xslt import Processor
- from Ft.Xml import InputSource
- from Ft.Lib.Uri import OsPathToUri
-
-
- if not enc:
- enc = sys.getdefaultencoding()
-
- try:
- processor = Processor.Processor()
+ if not enc:
+ enc = sys.getdefaultencoding()
+ try:
+ xslt_doc = etree.parse(xslt)
+ transform = etree.XSLT(xslt_doc)
+
+ input_doc = etree.parse(input)
+ result = str(transform(input_doc))
+ postprocessed_result = post_process_result(result, enc, linesep)
+ return postprocessed_result
- srcAsUri = OsPathToUri(input)
- source = InputSource.DefaultFactory.fromUri(srcAsUri)
-
- ssAsUri = OsPathToUri(xslt)
- transform = InputSource.DefaultFactory.fromUri(ssAsUri)
-
- processor.appendStylesheet(transform)
- result = processor.run(source)
-
- postprocessed_result = post_process_result(result, enc, linesep)
-
- if not filter_file_writing(postprocessed_result):
- write_string_to_file(postprocessed_result, output, enc)
-
- except Exception, e:
- logging.getLogger('cone.gcfml').error('Failed to do XSLT transformation: %s' % e)
- raise exceptions.ConeException('Failed to do XSLT transformation: %s' % (e))
-
-def filter_file_writing(string):
- """
- Returns True if writing result file should be ignored.
- """
- string = string.rstrip('\n\r')
- if string == '' or string == '' or \
- string == '':
- return True
-
- return False
+ except Exception, e:
+ logging.getLogger('cone.gcfml').error('Failed to do XSLT transformation: %s' % e)
+ raise exceptions.ConeException('Failed to do XSLT transformation: %s' % (e))
def post_process_result(string, enc, linesep):
- """
- Does post process for result from XSLT transform
- - encoding
- - removes extra line separators
- - changes line separators
- """
- output_string = None
-
- try:
- output_string = string.decode(enc)
- if not output_string.startswith('<'):
- output_string = '\n' + output_string
- output_string = output_string.replace('', '\n\n')
- output_string = output_string.replace('', '\n\n')
- output_string = output_string.replace('\n\n','\n')
- output_string = output_string.replace('\n', linesep)
- output_string+= linesep
- except Exception, e:
- logging.getLogger('cone.gcfml').error('Cannot post process result: %s \nException: %s' % (string, e))
- raise exceptions.ConeException('Cannot post process result: %s \nException: %s' % (string, e))
-
- return output_string
-
-def write_string_to_file(string, output, enc):
- """
- Writes string to file
- """
- try:
- outfile = os.path.abspath(output)
-
- if not os.path.exists(os.path.dirname(outfile)):
- os.makedirs(os.path.dirname(outfile))
-
- fl = codecs.open(outfile, 'w', enc)
- fl.write(string)
- fl.close()
-
- except Exception, e:
- logging.getLogger('cone.gcfml').error('Cannot write Element to file (%s). Exception: %s' % (output, e))
- raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ """
+ Does post process for result from XSLT transform
+ - encoding
+ - removes extra line separators
+ - changes line separators
+ """
+ output_string = None
+
+ try:
+ output_string = string.decode(enc)
+ if not output_string.startswith('<'):
+ output_string = '\n' + output_string
+ output_string = output_string.replace('', '\n\n')
+ output_string = output_string.replace('', '\n\n')
+ output_string = output_string.replace('\n\n','\n')
+ output_string = output_string.replace('\n', linesep)
+ output_string+= linesep
+ except Exception, e:
+ logging.getLogger('cone.gcfml').error('Cannot post process result: %s \nException: %s' % (string, e))
+ raise exceptions.ConeException('Cannot post process result: %s \nException: %s' % (string, e))
+
+ return output_string
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -25,6 +25,7 @@
name = "conegenconfmlplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'genconfmlplugin': ['xsd/*.xsd']},
test_suite = "genconfml.tests.collect_suite",
install_requires = ['lxml>=2.2.2'],
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_writer.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,13 +14,9 @@
# Description:
#
-import logging
-import __init__
-
-from struct import pack, unpack
+from struct import pack
-from cone.public import exceptions,plugin,utils,api
from hcrplugin.hcrrepository import HcrRecord
from hcrplugin.hcr_exceptions import *
from hcrplugin.hcr_header import HcrHeader
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrml_parser.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrml_parser.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrml_parser.py Tue Aug 10 14:29:28 2010 +0300
@@ -18,29 +18,15 @@
import re
-import os
-import sys
import logging
-import xml.parsers.expat
-import codecs
+import pkg_resources
+
from hcrplugin.hcr_exceptions import *
from hcrplugin.hcrrepository import HcrRecord, HcrRepository
from hcrplugin.hcr_writer import HcrWriter
from hcrplugin.header_writer import *
-try:
- from cElementTree import ElementTree
-except ImportError:
- try:
- from elementtree import ElementTree
- except ImportError:
- try:
- from xml.etree import cElementTree as ElementTree
- except ImportError:
- from xml.etree import ElementTree
-import __init__
-
-from cone.public import exceptions,plugin,utils,api
+from cone.public import plugin
class HcrmlImpl(plugin.ImplBase):
"""
@@ -62,25 +48,20 @@
@return:
"""
outputfile = self.__get_output_filename()
- if outputfile != None:
- # Create the path to the output file
- output_path = os.path.dirname(outputfile)
- if output_path != '' and not os.path.exists(output_path):
- os.makedirs(output_path)
-
# For output type 'hcr', write the binary repository file
if self.output_obj.type == 'hcr':
self.logger.info("Generating binary repository to '%s'" % outputfile)
writer = HcrWriter()
repo = self.output_obj.get_hcr_repository()
data = writer.get_repository_bindata(repo)
- f = open(outputfile,'wb')
+ f = context.create_file(outputfile, mode='wb')
+ #f = open(outputfile,'wb')
try: f.write(data)
finally: f.close()
elif self.output_obj.type == 'header':
self.logger.info("Generating header file to '%s'" % outputfile)
writer = HeaderWriter(outputfile, self.output_obj)
- writer.write()
+ writer.write(context)
elif self.output_obj.type == None:
# The HCRML file contains no element, so no output should
# be generated
@@ -105,6 +86,8 @@
class HcrmlReader(plugin.ReaderBase):
NAMESPACE = 'http://www.symbianfoundation.org/xml/hcrml/1'
+ NAMESPACE_ID = 'hcrml'
+ ROOT_ELEMENT_NAME = 'hcr'
FILE_EXTENSIONS = ['hcrml']
def __init__(self, resource_ref, configuration):
@@ -123,7 +106,11 @@
impl.output_obj = reader.read_hcrml_output()
impl.refs = reader.refs
return impl
-
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('hcrplugin', 'xsd/hcrml.xsd')
+
def read_hcrml_output(self, ignore_includes=False):
output = Output()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrrepository.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrrepository.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcrrepository.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,10 +14,7 @@
# Description:
#
-import logging
-import __init__
-from cone.public import exceptions,plugin,utils,api
class HcrRepository(object):
FLAG_READ_ONLY = 1
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/header_writer.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/header_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/header_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,11 +17,11 @@
import os
class HeaderWriter(object):
- def __init__(self,output_file, output_obj):
+ def __init__(self, output_file, output_obj):
self.output_obj = output_obj
self.output_file = output_file
- def write(self):
+ def write(self, context):
header_guard = os.path.basename(self.output_file).upper()
header_guard = header_guard.replace('/', '_').replace('\\', '_').replace('.', '_')
lines = [
@@ -56,6 +56,6 @@
"#endif",
])
- f = open(self.output_file, 'wb')
- try: f.write(os.linesep.join(lines))
+ f = context.create_file(self.output_file, mode='wb')
+ try: f.write('\r\n'.join(lines))
finally: f.close()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,12 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/generate_repo.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/generate_repo.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/generate_repo.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,7 +20,6 @@
"""
import os, unittest
-import __init__
from testautomation.utils import hex_to_bindata
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcr_header.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcr_header.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcr_header.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,7 +17,6 @@
import unittest
import os, shutil
import sys
-import __init__
from testautomation.utils import hex_to_bindata
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_impl.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_impl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_impl.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,16 +15,16 @@
#
import os, unittest
-import __init__
+
from cone.public import plugin
-from hcrplugin.hcrml_parser import HcrmlReader
def impl_from_resource(resource_ref, configuration):
"""
Read a HCRML implementation from the given resource in a configuration.
"""
- doc_root = plugin.ReaderBase._read_xml_doc_from_resource(resource_ref, configuration)
- return HcrmlReader.read_impl(resource_ref, configuration, doc_root)
+ impls = plugin.ImplFactory.get_impls_from_file(resource_ref, configuration)
+ assert len(impls) == 1
+ return impls[0]
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_reader.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,22 +15,10 @@
#
import unittest
-import os, shutil
-import sys
-import __init__
-import re
-import logging
-import xml.parsers.expat
-import codecs
+import os
+
from hcrplugin.hcr_exceptions import *
-from hcrplugin.hcrrepository import HcrRecord, HcrRepository
-from hcrplugin.hcrml_parser import *
-
-
-from testautomation.utils import hex_to_bindata
-
-
-from cone.public import api, exceptions
+from hcrplugin.hcrml_parser import HcrmlReader
try:
from cElementTree import ElementTree
@@ -43,7 +31,6 @@
except ImportError:
from xml.etree import ElementTree
-from cone.public import exceptions,plugin,utils,api
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_writer.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrml_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,12 +14,8 @@
# Description:
#
-import os, unittest
-import __init__
+import os
-from hcrplugin.hcrrepository import HcrRepository, HcrRecord
-from hcrplugin.hcr_writer import HcrWriter
-from hcrplugin import hcr_exceptions
from cone.public import api, plugin
from testautomation.base_testcase import BaseTestCase
@@ -37,11 +33,11 @@
prj = api.Project(api.Storage.open(project_dir))
config = prj.get_configuration('root.confml')
+ context = plugin.GenerationContext(configuration=config, output=output_dir)
impls = plugin.ImplFactory.get_impls_from_file(hcrml_file, config)
self.assertEquals(len(impls), 1)
impl = impls[0]
- impl.set_output_root(output_dir)
- impl.generate()
+ impl.generate(context)
if expected_dir != None:
self.assert_dir_contents_equal(expected_dir, output_dir, ['.svn'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrrepository.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrrepository.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_hcrrepository.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,13 +15,9 @@
#
import unittest
-import os, shutil
-import sys
-
-import __init__
+import os
from hcrplugin.hcrrepository import HcrRepository, HcrRecord
-from cone.public import api
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_record.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_record.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_record.py Tue Aug 10 14:29:28 2010 +0300
@@ -42,7 +42,6 @@
import unittest
import os, shutil
import sys
-import __init__
from testautomation.utils import hex_to_bindata
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_repository.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_repository.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_read_write_repository.py Tue Aug 10 14:29:28 2010 +0300
@@ -42,7 +42,6 @@
import unittest
import os, shutil, random
import sys
-import __init__
ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_reader.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_reader.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_reader.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import os, unittest
-import __init__
from testautomation.utils import hex_to_bindata
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_writer.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_writer.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/tests/unittest_writer.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,6 @@
#
import os, unittest
-import __init__
from hcrplugin.hcrrepository import HcrRepository, HcrRecord
from hcrplugin.hcr_writer import HcrWriter
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/xsd/hcrml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/xsd/hcrml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeHCRPlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeHCRPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conehcrplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'hcrplugin': ['xsd/*.xsd']},
author = "",
author_email = "",
description = "Configuration Engine Hardware configuration repository generation",
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+#
+# 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:
+#
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,9 +21,9 @@
import sys,os
try:
- pkg_resources.require("Cone")
+ pkg_resources.require("Cone")
except pkg_resources.DistributionNotFound:
- ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
- sys.path.append(ROOT_PATH)
- sys.path.append(os.path.join(ROOT_PATH,'..'))
- sys.path.append(os.path.join(ROOT_PATH,'../..'))
+ ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+ sys.path.append(ROOT_PATH)
+ sys.path.append(os.path.join(ROOT_PATH,'..'))
+ sys.path.append(os.path.join(ROOT_PATH,'../..'))
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/generators.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/generators.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/generators.py Tue Aug 10 14:29:28 2010 +0300
@@ -20,13 +20,12 @@
import re
import os
-import sys
import logging
import subprocess
import shutil
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-from cone.public import utils, exceptions
+from cone.public import utils
class InvalidInputFileException(RuntimeError):
"""
@@ -60,18 +59,18 @@
Get the confml ref value from configuration if the outputpath is actually a ref
"""
if self._outputpath and ConfmlRefs.is_confml_ref(self._outputpath):
- oref = ConfmlRefs.get_confml_ref(self._outputpath)
- opath = self.configuration.get_default_view().get_feature(oref).get_value()
- if opath == None:
- logging.getLogger('cone.imageml').warning('Output path not set.')
- return self._outputpath
- #raise exceptions.NotBound("Output path reference has no value %s" % oref)
- (drive,opath) = os.path.splitdrive(opath)
- opath = utils.resourceref.norm(opath)
- opath = utils.resourceref.remove_begin_slash(opath)
- return opath
+ oref = ConfmlRefs.get_confml_ref(self._outputpath)
+ opath = self.configuration.get_default_view().get_feature(oref).get_value()
+ if opath == None:
+ logging.getLogger('cone.imageml').warning('Output path not set.')
+ return self._outputpath
+ #raise exceptions.NotBound("Output path reference has no value %s" % oref)
+ (drive,opath) = os.path.splitdrive(opath)
+ opath = utils.resourceref.norm(opath)
+ opath = utils.resourceref.remove_begin_slash(opath)
+ return opath
else:
- return self._outputpath
+ return self._outputpath
def set_outputpath(self, value):
self._outputpath = value
@@ -138,6 +137,8 @@
def __init__(self,generator):
self._generator = generator
self._workdir = 'conversion_workdir'
+ self._extraparams = ""
+
def execute(self):
""" Execute this command """
@@ -203,6 +204,14 @@
@property
def workdir(self):
return self._workdir
+
+ @property
+ def extraparams(self):
+ if self._generator.extraparams and self._generator.configuration:
+ dview = self._generator.configuration.get_default_view()
+ return utils.expand_refs_by_default_view(self._generator.extraparams, dview)
+ else:
+ return self._generator.extraparams or ''
def _get_filtered_input_files(self):
"""
@@ -253,8 +262,10 @@
if len(input_files) == 0: return 0
self.create_workdir(input_files)
- if not os.path.exists(os.path.dirname(self.generator.path)):
- os.makedirs(os.path.dirname(self.generator.path))
+ opath = self.generator.path
+ odir = os.path.dirname(opath)
+ if odir and not os.path.exists(odir):
+ os.makedirs(odir)
command = self.get_command(input_files)
p = subprocess.Popen(command,
@@ -273,15 +284,20 @@
else:
logging.getLogger('cone.bmconv').info("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
if p.returncode == 0:
- self.clean_workdir()
+ self.clean_workdir()
return p.returncode
def get_command(self, input_files):
command = [self.tool]
+
+ """ Add extraparams """
+ if hasattr(self._generator,'extraparams'):
+ command.append(self.extraparams)
+
""" Add palette file """
if hasattr(self._generator,'palette'):
command.append('/p%s' % os.path.abspath(self.generator.palette))
-
+
""" Add output file """
""" Add output file as compressed if needed """
if self.rom:
@@ -364,7 +380,7 @@
else:
logging.getLogger('cone.mifconv').info("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
if p.returncode == 0:
- self.clean_workdir()
+ self.clean_workdir()
return p.returncode
def get_command(self, input_files):
@@ -373,6 +389,10 @@
""" Add output file """
command.append(os.path.normpath(self.generator.path))
+ """ Add extraparams """
+ if hasattr(self._generator,'extraparams'):
+ command.append(self.extraparams)
+
""" Add temp_path """
command.append("/t%s" % self.temppath)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/imageml.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/imageml.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/imageml.py Tue Aug 10 14:29:28 2010 +0300
@@ -17,13 +17,9 @@
A plugin implementation for image selection from ConfigurationLayers.
'''
-
-import re
import os
-import sys
import logging
-import shutil
-import xml.parsers.expat
+import pkg_resources
try:
from cElementTree import ElementTree
@@ -36,7 +32,7 @@
except ImportError:
from xml.etree import ElementTree
-import __init__
+
from cone.public import exceptions,plugin,utils,api
from imageplugin.generators import OutputGenerator,InputFile,InputDir,InvalidInputFileException
@@ -89,9 +85,11 @@
ret = True
for generator in self.generators:
self.logger.info(generator)
- generator.subpath = self.output
+ generator.subpath = os.path.join(context.output,self.output)
try:
- ret = generator.generate() and ret
+ ret = generator.generate(context) and ret
+ outfile = generator.get_outputpath()
+ context.add_file(outfile, implementation=self)
except InvalidInputFileException, e:
self.logger.error(e)
return ret
@@ -117,6 +115,8 @@
Parses a single imageml implml file
"""
NAMESPACE = 'http://www.s60.com/xml/imageml/1'
+ NAMESPACE_ID = 'imageml'
+ ROOT_ELEMENT_NAME = 'imageml'
FILE_EXTENSIONS = ['imageml']
INCLUDE_ATTR = ['pattern']
@@ -142,7 +142,11 @@
generator.configuration = configuration
return impl
-
+
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('imageplugin', 'xsd/imageml.xsd')
+
def fromstring(self, xml_as_string):
etree = ElementTree.fromstring(xml_as_string)
self.desc = self.parse_desc(etree)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,12 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/imageproject/variant/implml/startupmif_animation_with_version.imageml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/imageproject/variant/implml/startupmif_animation_with_version.imageml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_generators.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_generators.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_generators.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,12 +15,10 @@
#
import unittest
-import os, shutil
-import sys
-import __init__
+import sys, os
-from imageplugin import imageml,generators
-from cone.public import api, exceptions, plugin
+from imageplugin import generators
+from cone.public import api, exceptions, plugin, utils
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
def impl_from_resource(resource_ref, configuration):
@@ -121,6 +119,42 @@
self.assertEquals(len(cmd), 5)
self.assertEquals(cmd[3], '/c16')
self.assertEquals(cmd[4], r'conversion_workdir\icon.svg')
+
+ def test_create_generator_with_extraparams(self):
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,"imageproject")))
+ config = prj.get_configuration('product.confml')
+ dview = config.get_default_view()
+ impl = impl_from_resource('variant/implml/startupmif_animation_with_version.imageml', config)
+
+ # 1st impl
+ self.assertEquals(impl.generators[0].extraparams, '/V3')
+
+ # Assert the the extraparams is actually used in the command
+ command_obj = impl.generators[0].get_command()
+ cmd = command_obj.get_command(command_obj._get_filtered_input_files())
+ self.assertEquals(len(cmd), 6)
+ self.assertEquals(cmd[2], r'/V3')
+
+ # 2nd impl
+ self.assertEquals(impl.generators[1].extraparams, '${StartupSettings.PluginTimeout}')
+ self.assertEquals(utils.expand_refs_by_default_view(impl.generators[1].extraparams, dview), '30000')
+
+ # Assert the the extraparams is actually used in the command
+ command_obj = impl.generators[1].get_command()
+ cmd = command_obj.get_command(command_obj._get_filtered_input_files())
+ self.assertEquals(len(cmd), 6)
+ self.assertEquals(cmd[2], r'30000')
+
+ # 3rd impl
+ self.assertEquals(impl.generators[2].extraparams, '${StartupSettings.PluginTimeout}')
+ self.assertEquals(utils.expand_refs_by_default_view(impl.generators[1].extraparams, dview), '30000')
+
+ # Assert the the extraparams is actually used in the command
+ command_obj = impl.generators[2].get_command()
+ cmd = command_obj.get_command(command_obj._get_filtered_input_files())
+ self.assertEquals(len(cmd), 4)
+ self.assertEquals(cmd[1], r'30000')
+
def test_create_generator_with_invalid_output(self):
prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,"imageproject")))
@@ -139,5 +173,12 @@
except exceptions.NotFound:
pass
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestGenerator
+ del TestInputFile
+ del TestInputDir
+ del TestGeneratorFromProject
+
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_parseimpl.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_parseimpl.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_parseimpl.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,9 +15,8 @@
#
import unittest
-import os, shutil
import sys
-import __init__
+
try:
from cElementTree import ElementTree
except ImportError:
@@ -28,14 +27,14 @@
from xml.etree import cElementTree as ElementTree
except ImportError:
from xml.etree import ElementTree
-
+
from imageplugin import imageml
imageml_string = \
'''
-
+
@@ -137,6 +136,7 @@
reader = imageml.ImageImplReader()
outputs = reader.parse_outputs(etree)
self.assertEquals(outputs[0].outputpath,'startup.mbm')
+ self.assertEquals(outputs[0].extraparams, '/V2')
self.assertEquals(outputs[0].inputs[0].path,'UI/Start-up Animation')
self.assertEquals(outputs[0].inputs[0].type,'dir')
self.assertEquals(outputs[0].inputs[0].include,['bmb$'])
@@ -169,6 +169,9 @@
self.assertEquals(reader.outputgenerators[0].inputs[0].type,'dir')
self.assertEquals(reader.outputgenerators[0].inputs[0].include,['${features.inputfilter}'])
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestImagemlParseimpl
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_plugin.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/tests/unittest_imageml_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,15 +15,9 @@
#
import unittest
-import os, shutil, re
-import sys
-import logging
-import shutil
-import __init__
-
-from cone.public import exceptions,plugin,api,container
-from cone.storage import filestorage
-from imageplugin import imageml
+import sys, os, re
+
+from cone.public import plugin,api
from testautomation.base_testcase import BaseTestCase
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -39,10 +33,12 @@
prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH,"imageproject")))
config = prj.get_configuration('product.confml')
- implcontainer = plugin.get_impl_set(config, 'imageml$')
- self.assertEquals(len(implcontainer), 4)
- implcontainer.output = output
- implcontainer.generate()
+ context = plugin.GenerationContext(configuration=config, output=output)
+ context.filtering_disabled = True
+
+ impl_set = plugin.get_impl_set(config, 'imageml$')
+ self.assertEquals(len(impl_set), 5)
+ impl_set.generate(context)
def check_gen(p):
self.assert_exists_and_contains_something(os.path.join(output, p))
@@ -50,33 +46,33 @@
self.assertFalse(os.path.exists(os.path.join(output, p)), "'%s' exists when it should not!" % p)
try:
- check_gen('startup.mbm')
- check_gen('startup_mif.mif')
-
- check_not_gen('optional1_mbm.mbm')
- check_gen('optional2_mbm.mbm')
- check_not_gen('optional3_mbm.mbm')
- check_not_gen('optional4_mbm.mbm')
-
- check_not_gen('optional1_mif.mif')
- check_gen('optional2_mif.mif')
- check_not_gen('optional3_mif.mif')
- check_not_gen('optional4_mif.mif')
-
- check_gen('resource/apps/startup.mif')
-
- check_gen('depth_from_ref_test_mbm.mbm')
- check_gen('depth_from_ref_test_mif.mif')
- except AssertionError:
- if ' ' in ROOT_PATH:
- self.fail("Known bug (#177)")
- else:
- raise
+ check_gen('startup.mbm')
+ check_gen('startup_mif.mif')
+
+ check_not_gen('optional1_mbm.mbm')
+ check_gen('optional2_mbm.mbm')
+ check_not_gen('optional3_mbm.mbm')
+ check_not_gen('optional4_mbm.mbm')
+
+ check_not_gen('optional1_mif.mif')
+ check_gen('optional2_mif.mif')
+ check_not_gen('optional3_mif.mif')
+ check_not_gen('optional4_mif.mif')
+
+ check_gen('resource/apps/startup.mif')
+
+ check_gen('depth_from_ref_test_mbm.mbm')
+ check_gen('depth_from_ref_test_mif.mif')
+ except AssertionError, e:
+ if ' ' in ROOT_PATH:
+ self.fail("Known bug (#177): %s" % e)
+ else:
+ raise
finally:
os.chdir(orig_workdir)
def _get_impl(self, filename):
- prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH, "imageproject")))
+ prj = api.Project(api.Storage.open(os.path.join(ROOT_PATH, "imageproject")))
config = prj.get_configuration('product.confml')
implcontainer = plugin.get_impl_set(config, re.escape(filename) + '$')
self.assertEquals(len(implcontainer), 1)
@@ -84,20 +80,24 @@
def test_get_refs(self):
- impl = self._get_impl('startupmif_animation.imageml')
- self.assertEquals(impl.get_refs(), None)
- self.assertEquals(impl.has_ref('Foo.Bar'), None)
-
- impl = self._get_impl('optional_test.imageml')
- self.assertEquals(impl.get_refs(), ['OptionalTest.EmptyString',
- 'OptionalTest.EmptyString2'])
- self.assertEquals(impl.has_ref('OptionalTest.EmptyString'), True)
- self.assertEquals(impl.has_ref('Foo.Foo'), False)
-
- impl = self._get_impl('startup_animation.imageml')
- self.assertEquals(impl.get_refs(), ['CVC_StartupAnimationSequence.CVC_StartupFrameLocation.localPath'])
- self.assertEquals(impl.has_ref('CVC_StartupAnimationSequence.CVC_StartupFrameLocation.localPath'), True)
- self.assertEquals(impl.has_ref('Foo.Foo'), False)
+ impl = self._get_impl('startupmif_animation.imageml')
+ self.assertEquals(impl.get_refs(), None)
+ self.assertEquals(impl.has_ref('Foo.Bar'), None)
+
+ impl = self._get_impl('optional_test.imageml')
+ self.assertEquals(impl.get_refs(), ['OptionalTest.EmptyString',
+ 'OptionalTest.EmptyString2'])
+ self.assertEquals(impl.has_ref('OptionalTest.EmptyString'), True)
+ self.assertEquals(impl.has_ref('Foo.Foo'), False)
+
+ impl = self._get_impl('startup_animation.imageml')
+ self.assertEquals(impl.get_refs(), ['CVC_StartupAnimationSequence.CVC_StartupFrameLocation.localPath'])
+ self.assertEquals(impl.has_ref('CVC_StartupAnimationSequence.CVC_StartupFrameLocation.localPath'), True)
+ self.assertEquals(impl.has_ref('Foo.Foo'), False)
+
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestGeneratorFromProject
if __name__ == '__main__':
unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/xsd/imageml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/xsd/imageml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeImagePlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeImagePlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "coneimageplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'imageplugin': ['xsd/*.xsd']},
test_suite = "imageplugin.tests.collect_suite",
# metadata for upload to PyPI
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py Tue Aug 10 14:29:28 2010 +0300
@@ -24,6 +24,8 @@
import xml.parsers.expat
import shutil
import fnmatch
+import pkg_resources
+import types
try:
from cElementTree import ElementTree
@@ -71,11 +73,11 @@
"""
#Generating content
- fullOutputPath = self.output
+ fullOutputPath = os.path.join(context.output, self.output)
if self.project_data.has_key("path"):
targetPath = utils.resourceref.norm(self.project_data["path"])
if targetPath and targetPath != "":
- fullOutputPath = os.path.join(fullOutputPath, targetPath)
+ fullOutputPath = os.path.join(context.output, fullOutputPath, targetPath)
fs = filestorage.FileStorage(fullOutputPath, "w")
newProject = api.Project(fs)
@@ -116,13 +118,14 @@
Object presenting layer in convertprojectml file.
"""
- def __init__(self, path):
+ def __init__(self, path, configuration):
if path != None:
self.path = path
else:
self.path = ""
self.folders = []
- self.files = []
+ self.files = []
+ self.source_configuration = configuration
def __str__(self):
retStr = ""
@@ -159,8 +162,24 @@
self.files.append(file)
def getProjectPath(self):
- return self.path
+ return self.path
+ def solve_ref(self, inputdata):
+ """
+ Internal function to solve whether input is ref or just normal input string.
+ For refs actual ConfML value is resolved and returned. Non-refs are returned
+ as such.
+ """
+ dview = self.source_configuration.get_default_view()
+ if inputdata and isinstance(inputdata, types.StringType):
+ return utils.expand_refs_by_default_view(inputdata, dview)
+ elif inputdata and isinstance(inputdata, types.DictType):
+ retDict = {}
+ for key in inputdata:
+ retDict[self.solve_ref(key)] = self.solve_ref(inputdata[key])
+ return retDict
+ else:
+ return inputdata
class ConvertProjectFolder(object):
"""
@@ -198,7 +217,11 @@
def getProjectPath(self):
return os.path.join(self.parent.getProjectPath(), self.path)
-
+
+ def solve_ref(self, inputdata):
+ return self.parent.solve_ref(inputdata)
+
+
class ConvertProjectFile(object):
"""
Object presenting file in convertprojectml file.
@@ -209,7 +232,7 @@
self.path = path
else:
self.path = ""
- if type != None:
+ if type != None and type != "none":
self.type = type
else:
self.type = ""
@@ -218,6 +241,7 @@
self.parent = parent
self.meta = []
self.desc = ""
+ self.configuration_name = ""
def __str__(self):
retStr = ""
@@ -232,18 +256,23 @@
for filter in self.filters:
filter.generate(project, old_structure_root, self.type)
- if self.type == "configuration_root":
- #Adding metadata
- config = project.get_configuration(utils.resourceref.norm(self.path))
+ if self.type:
+ config = project.get_configuration(utils.resourceref.norm(self.getProjectPath()))
if self.meta:
if not config.meta:
config.meta = []
for meta in self.meta:
- config.meta.add(meta[0], meta[1], meta[2], meta[3])
+ config.meta.set_property_by_tag(self.solve_ref(meta[0]), \
+ self.solve_ref(meta[1]), \
+ self.solve_ref(meta[2]), \
+ self.solve_ref(meta[3]))
if self.desc:
config.desc = self.desc
- config.save()
+ if self.configuration_name:
+ config.set_name(self.configuration_name)
+ config.save()
+
return
def addFilter(self, filter):
@@ -254,9 +283,18 @@
def addDescription(self, desc):
self.desc = desc
+
+ def addConfigurationName(self, configuration_name):
+ self.configuration_name = configuration_name
def getProjectPath(self):
- return os.path.join(self.parent.getProjectPath(), self.path)
+ if self.type == "configuration_root":
+ return self.path
+ else:
+ return os.path.join(self.parent.getProjectPath(), self.path)
+
+ def solve_ref(self, inputdata):
+ return self.parent.solve_ref(inputdata)
class ConvertProjectFilter(object):
"""
@@ -274,7 +312,7 @@
if recursive:
self.recursive = recursive
else:
- self.recursive = "false"
+ self.recursive = "false"
def __str__(self):
retStr = ""
@@ -367,7 +405,9 @@
retPath = os.path.join(project.get_storage().get_path(), self.getProjectPath())
startFound = 0
- for item in os.path.normpath(filepath).split("\\"):
+ parts = filter(lambda p: p != '',
+ os.path.normpath(filepath).replace('\\', '/').split('/'))
+ for item in parts:
if self.data.find(item) != -1:
startFound = 1
if startFound and self.data.find(item) == -1:
@@ -402,8 +442,11 @@
filesToProcess = self.getFilesByWildcard(fullSearchPath, wildCardPart, project)
#Creating rootfile.
- rootFilePath = os.path.join(self.getProjectPath(), self.parent.path)
- config = project.create_configuration(utils.resourceref.norm(rootFilePath))
+ rootFilePath = os.path.join(self.getProjectPath(), self.parent.path)
+ if project.is_configuration(utils.resourceref.norm(rootFilePath)):
+ config = project.get_configuration(utils.resourceref.norm(rootFilePath))
+ else:
+ config = project.create_configuration(utils.resourceref.norm(rootFilePath))
#Adding defined includes.
for f in filesToProcess:
@@ -435,7 +478,7 @@
"""
#Always in the root of the project
configname = utils.resourceref.norm(self.parent.path)
- if configname in project.list_configurations():
+ if project.is_configuration(utils.resourceref.norm(self.parent.path)):
config = project.get_configuration(configname)
else:
config = project.create_configuration(utils.resourceref.norm(self.parent.path))
@@ -469,6 +512,10 @@
continue
else:
for f in files:
+ if wildcard and wildcard[0] != "*":
+ #Matches path part.
+ wildcard = "*%s" % wildcard
+
if fnmatch.fnmatch(os.path.join(root, f), wildcard):
source = os.path.join(root, f)
targetDir = self.resolveTargetDir(project, source)
@@ -502,7 +549,9 @@
return pathPart, wildCardPart
-
+ def solve_ref(self, inputdata):
+ return self.parent.solve_ref(inputdata)
+
#=================================================================
class ConvertProjectReader(plugin.ReaderBase):
@@ -511,6 +560,8 @@
"""
NAMESPACE = 'http://www.s60.com/xml/convertprojectml/1'
+ NAMESPACE_ID = 'convertprojectml'
+ ROOT_ELEMENT_NAME = 'convertprojectml'
FILE_EXTENSIONS = ['convertprojectml']
def __init__(self):
@@ -524,51 +575,50 @@
@classmethod
def read_impl(cls, resource_ref, configuration, etree):
reader = ConvertProjectReader()
- reader.from_etree(etree, configuration.get_storage().get_path())
+ reader.from_etree(etree, configuration, configuration.get_storage().get_path())
impl = ConvertProjectImpl(resource_ref, configuration)
impl.project_data = reader.project_data
impl.layers = reader.layers
return impl
- def from_etree(self, etree, old_structure_root = ""):
- self.project_data = self.parse_attributes(etree, "targetProject")
- self.layers = self.parse_layers(etree)
- for fe in self.parse_foreach(etree, old_structure_root):
- self.layers.append(fe)
-
- #for l in self.layers:
- #print l
- return
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('projectconvertplugin', 'xsd/convertprojectml.xsd')
+
+ def from_etree(self, etree, configuration, old_structure_root = ""):
+ self.configuration = configuration
+
+ for element in etree:
+ if element.tag == "{http://www.s60.com/xml/convertprojectml/1}targetProject":
+ self.project_data = self.parse_attributes(etree, "targetProject")
+ elif element.tag == "{http://www.s60.com/xml/convertprojectml/1}layer":
+ self.layers.append(self.parse_layer(element))
+ elif element.tag == "{http://www.s60.com/xml/convertprojectml/1}foreach":
+ for fe in self.parse_foreach(element, old_structure_root):
+ self.layers.append(fe)
+ return
def parse_foreach(self, etree, old_structure_root):
- layersTmp = []
- for fe in etree.findall("{%s}foreach" % self.namespaces[0]):
- variable = fe.get("variable")
- data = fe.get("data")
- folders = []
- for item in os.listdir(os.path.join(old_structure_root, data)):
- if os.path.isdir(os.path.join(old_structure_root, data, item)) and item != '.svn':
- folders.append(item)
-
- for folder in folders:
- mapping_data = {variable: folder}
- for layer in fe.findall("{%s}layer" % self.namespaces[0]):
- layersTmp.append(self.parse_layer(layer, mapping_data))
+ layersTmp = []
+ variable = etree.get("variable")
+ data = self.handleMapping(etree.get("data"), {})
+ folders = []
+ for item in os.listdir(os.path.join(old_structure_root, data)):
+ if os.path.isdir(os.path.join(old_structure_root, data, item)) and item != '.svn':
+ folders.append(item)
+
+ for folder in folders:
+ mapping_data = {variable: folder}
+ for layer in etree.findall("{%s}layer" % self.namespaces[0]):
+ layersTmp.append(self.parse_layer(layer, mapping_data))
return layersTmp
-
- def parse_layers(self,etree):
- layersTmp = []
- for layer in etree.findall("{%s}layer" % self.namespaces[0]):
- layersTmp.append(self.parse_layer(layer))
-
- return layersTmp
-
+
def parse_layer(self, etree, mapping_data=None):
path = self.handleMapping(etree.get("path"), mapping_data)
- layerObject = ConvertProjectLayer(path)
+ layerObject = ConvertProjectLayer(path, self.configuration)
for folder in etree.findall("{%s}folder" % self.namespaces[0]):
layerObject.addFolder(self.parse_folder(folder, layerObject, mapping_data))
@@ -589,6 +639,7 @@
def parse_file(self, etree, parent, mapping_data=None):
path = self.handleMapping(etree.get("path"), mapping_data)
type = self.handleMapping(etree.get("type"), mapping_data)
+ configuration_name = self.handleMapping(etree.get("configuration_name"), mapping_data)
fileObject = ConvertProjectFile(path, type, parent)
for filter in etree.findall("{%s}filter" % self.namespaces[0]):
@@ -618,7 +669,8 @@
description = descElement.text
fileObject.addMeta(metaArray)
- fileObject.addDescription(description)
+ fileObject.addDescription(description)
+ fileObject.addConfigurationName(configuration_name)
return fileObject
def parse_filter(self, etree, parent, mapping_data=None):
@@ -644,18 +696,24 @@
def handleMapping(self, data, mapping):
"""
- """
-
+ """
retStr = data
-
- if mapping != None and data != None:
- for key in mapping.keys():
- retStr = retStr.replace(key, mapping[key])
+ if not mapping: mapping = {}
+ if data != None:
+ merged = dict(mapping.items() + self._get_env_variables().items())
+ for key in merged.keys():
+ retStr = retStr.replace(key, merged[key])
+
return retStr
-
-
-
+ def _get_env_variables(self):
+ if not hasattr(self, '_env_dict'):
+ #Making dictionary only once because of performance.
+ self._env_dict = {}
+ for var in os.environ:
+ self._env_dict["%%%s%%" % var] = os.environ[var]
+
+ return self._env_dict
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,12 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/.metadata
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/.metadata Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/.metadata Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,2 @@
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/confml/family_x.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/confml/family_x.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/confml/family_x.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+300
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/confml/product_x.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/confml/product_x.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/confml/product_x.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,9 +1,9 @@
-
+500true
- Product X
+ 001.009
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Euro/confml/VariantData_product_x_Euro.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Euro/confml/VariantData_product_x_Euro.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Euro/confml/VariantData_product_x_Euro.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+testing
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/French/confml/VariantData_product_x_French.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/French/confml/VariantData_product_x_French.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/French/confml/VariantData_product_x_French.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+français
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/German/confml/VariantData_product_x_German.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/German/confml/VariantData_product_x_German.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/German/confml/VariantData_product_x_German.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+deutsch
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Greek/confml/VariantData_product_x_Greek.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Greek/confml/VariantData_product_x_Greek.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/product_x/language/Greek/confml/VariantData_product_x_Greek.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+ελληνική γλώσσα
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test/implml/create_project.convertprojectml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test/implml/create_project.convertprojectml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test/implml/create_project.convertprojectml Tue Aug 10 14:29:28 2010 +0300
@@ -18,8 +18,9 @@
-
+
+ This is layer root file for platform 1
@@ -39,7 +40,19 @@
-
+
+
+
+
+ 001
+ ${Feature1.StringSetting}
+
+
+
+
+
+
+
@@ -58,7 +71,29 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -86,7 +121,6 @@
-
@@ -111,7 +145,7 @@
-
+
@@ -124,7 +158,7 @@
-
+
@@ -133,4 +167,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test3/implml/create_project.convertprojectml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test3/implml/create_project.convertprojectml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/family_x/test3/implml/create_project.convertprojectml Tue Aug 10 14:29:28 2010 +0300
@@ -18,8 +18,9 @@
-
+
+ This is layer root file for platform 1
@@ -39,7 +40,19 @@
-
+
+
+
+
+ 001
+ ${Feature1.StringSetting}
+
+
+
+
+
+
+
@@ -58,7 +71,29 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -86,7 +121,6 @@
-
@@ -111,7 +145,7 @@
-
+
@@ -124,7 +158,7 @@
-
+
@@ -133,4 +167,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platform1_root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platform1_root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platform1_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -2,11 +2,13 @@
- Version1
+ 001Platform1Date1
- Release1
+ 001.009Editor1
+
+ Description1
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platform3_root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platform3_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform1/root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform1/root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform1/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,5 @@
-
+
+This is layer root file for platform 1
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/confml/feature2.confml
Binary file configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/confml/feature2.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/implml/feature2_ABCD0000.crml
Binary file configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/implml/feature2_ABCD0000.crml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/platforms/platform3_feas_only/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Euro_root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Euro_root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Euro_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,7 +1,8 @@
-
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_French_root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_French_root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_French_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_German_root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_German_root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_German_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Greek_root.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Greek_root.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/expected/new_project/product_x_Greek_root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,4 @@
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/confml_data/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/confml_data/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convert.confml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convert.confml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convert.confml Tue Aug 10 14:29:28 2010 +0300
@@ -1,4 +1,6 @@
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convertpluginlayer/implml/create_project.convertprojectml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convertpluginlayer/implml/create_project.convertprojectml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/convertpluginlayer/implml/create_project.convertprojectml Tue Aug 10 14:29:28 2010 +0300
@@ -18,8 +18,9 @@
-
+
+ This is layer root file for platform 1
@@ -39,7 +40,19 @@
-
+
+
+
+
+ 001
+ ${Feature1.StringSetting}
+
+
+
+
+
+
+
@@ -58,7 +71,29 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -86,7 +121,6 @@
-
@@ -111,7 +145,7 @@
-
+
@@ -124,7 +158,7 @@
-
+
@@ -133,4 +167,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/family_x/product_x/product_x.confml
Binary file configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/family_x/product_x/product_x.confml has changed
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/family_x/product_x/root.confml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/old_structure/epoc32/rom/config/family_x/product_x/root.confml Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/project/assets/s60/implml/file1.convertprojectml
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/project/assets/s60/implml/file1.convertprojectml Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/project/assets/s60/implml/file1.convertprojectml Tue Aug 10 14:29:28 2010 +0300
@@ -1,7 +1,7 @@
-
+
@@ -41,14 +41,13 @@
-
-
+
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
\ No newline at end of file
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/unittest_convertprojectml_plugin.py
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/unittest_convertprojectml_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/tests/unittest_convertprojectml_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -16,11 +16,9 @@
import unittest, os, shutil
-import __init__
from projectconvertplugin import convertproject
-from cone.public import exceptions,plugin,api
+from cone.public import plugin,api
from cone.storage import filestorage
-from cone.confml import implml
from testautomation.base_testcase import BaseTestCase
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -43,6 +41,8 @@
self.assertTrue(isinstance(impl, convertproject.ConvertProjectImpl))
def test_generate(self):
+ os.environ['ncp_version'] = 'platforms'
+ os.environ['variants'] = 'variants'
output_dir = os.path.join(temp_dir, "new_project")
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
@@ -52,12 +52,14 @@
fs = filestorage.FileStorage(oldPath)
p = api.Project(fs)
config = p.get_configuration('convert.confml')
+ context = plugin.GenerationContext(configuration=config,
+ output=output_dir)
impls = plugin.get_impl_set(config,'\.convertprojectml$')
- impls.output = output_dir
- impls.generate()
+ context.filtering_disabled = True
+ impls.generate(context)
self.assert_dir_contents_equal(expected_dir, output_dir, ['.svn'])
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/xsd/convertprojectml.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/xsd/convertprojectml.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "projectconvertplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'projectconvertplugin': ['xsd/*.xsd']},
test_suite = "projectconvertplugin.tests.collect_suite",
# metadata for upload to PyPI
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/setup.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/setup.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/setup.py Tue Aug 10 14:29:28 2010 +0300
@@ -22,6 +22,7 @@
name = "conethemeplugin",
version = __version__,
packages = find_packages(exclude=["*.tests"]),
+ package_data = {'themeplugin': ['xsd/*.xsd']},
# metadata for upload to PyPI
author = "",
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/maketheme.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/maketheme.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/maketheme.py Tue Aug 10 14:29:28 2010 +0300
@@ -21,6 +21,7 @@
import xml.parsers.expat
import unzip
import shutil
+import pkg_resources
try:
from cElementTree import ElementTree
@@ -84,13 +85,13 @@
plugin.ImplBase.__init__(self,ref,configuration)
self.logger = logging.getLogger('cone.thememl')
- def build(self):
+ def build(self, context):
"""
Building process of themes
"""
# Get absolute path so that copying works correctly
# despite working directory changing
- abs_output = os.path.abspath(os.path.join(self.output, "content"))
+ abs_output = os.path.abspath(os.path.join(context.output, self.output, "content"))
# get *.tpf files from the configuration
list_tpf = self.list_tpf_files(self.list_active_theme, self.list_theme_dir)
@@ -172,8 +173,15 @@
"""
Generate the given implementation.
"""
- self.parse_impl()
- self.build()
+ # Make sure autoconfig is the last layer, since theme conversion
+ # may change the values of some settings
+ autoconfig = plugin.get_autoconfig(self.configuration)
+
+ self.build(context)
+
+ # Add changed refs if necessary
+ if context:
+ context.add_changed_refs(autoconfig.list_leaf_datas())
return
@@ -191,24 +199,6 @@
Otherwise return False.
"""
return None
-
- def parse_impl(self):
- if self.configuration:
- resource =self.configuration.get_resource(self.ref)
- reader = ThemeImplReader()
- try:
- self.logger.info('Parses %s' % self.ref)
- reader.fromstring(resource.read())
- self.carbide = reader.carbide
- except (SyntaxError),e:
- logging.getLogger('cone.thememl(%s)' % resource.get_path()).error('Invalid xml in layer root file. Exception: %s' % (e))
- raise exceptions.ParseError('Invalid xml in layer root file (%s). Exception: %s' % (resource.get_path(),e))
- self.list_theme_dir=reader.list_theme_dir
- self.list_active_theme=reader.list_active_theme
- self.theme_version = reader.theme_version
- resource.close()
-
- return
def list_output_files(self):
"""
@@ -223,6 +213,8 @@
Parses a single thememl file
"""
NAMESPACE = 'http://www.s60.com/xml/thememl/1'
+ NAMESPACE_ID = 'thememl'
+ ROOT_ELEMENT_NAME = 'thememl'
FILE_EXTENSIONS = ['thememl']
def __init__(self):
@@ -242,8 +234,13 @@
impl.list_theme_dir = reader.list_theme_dir
impl.list_active_theme = reader.list_active_theme
impl.theme_version = reader.theme_version
+ impl.carbide = reader.carbide
return impl
+ @classmethod
+ def get_schema_data(cls):
+ return pkg_resources.resource_string('themeplugin', 'xsd/thememl.xsd')
+
def fromstring(self, xml_as_string):
etree = ElementTree.fromstring(xml_as_string)
self.parse_thememl(etree)
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/__init__.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -13,24 +13,12 @@
#
# Description:
#
+
import sys, os, unittest
# Path to the directory where this file is located
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-# Import common plug-in initialization
-PLUGINS_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../../../..'))
-assert os.path.split(PLUGINS_ROOT)[1] == 'plugins'
-if PLUGINS_ROOT not in sys.path: sys.path.append(PLUGINS_ROOT)
-import plugin_utils
-
+from testautomation import plugin_utils
plugin_utils.plugin_test_init(ROOT_PATH)
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/e75/test_pkg/themepackage2.pkg
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/e75/test_pkg/themepackage2.pkg Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/e75/test_pkg/themepackage2.pkg Tue Aug 10 14:29:28 2010 +0300
@@ -50,10 +50,6 @@
;
; Files to install
;
-IF PACKAGE(0X102032BE) ; CHECK FOR S60 3.1 STUB SIS
-"themepackage.mbm" - "!:\resource\skins\f99553e36ea1a92f\themepackage.mbm"
-"themepackage.mif" - "!:\resource\skins\f99553e36ea1a92f\themepackage.mif"
-ELSE
"themepackage.mbm" - "!:\private\10207114\import\f99553e36ea1a92f\themepackage.mbm"
"themepackage.mif" - "!:\private\10207114\import\f99553e36ea1a92f\themepackage.mif"
ENDIF
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/runtests.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,6 +15,6 @@
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_container.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_container.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_container.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,15 +14,10 @@
# Description:
#
-import unittest, os, shutil
+import unittest, sys, os
-import __init__
-from cone.public import exceptions,plugin,api
-from cone.storage import filestorage
-from cone.confml import implml
-from themeplugin import theme_function
+from cone.public import api
from themeplugin.theme_container import ThemeContainer
-from cone.storage.filestorage import FileStorage
from unittest_theme_plugin import impl_from_resource
@@ -44,7 +39,6 @@
impl = impl_from_resource("variant/implml/theme.thememl", config);
list_tpf = impl.list_tpf_files(impl.list_active_theme, impl.list_theme_dir)
- list_theme=[]
container = ThemeContainer(list_tpf,impl.configuration)
container.create_themes()
self.assertEquals(len(container.list_theme),2)
@@ -74,7 +68,9 @@
self.assertEquals(theme.get_setting_uids(), ["KCRUidPersonalisation.KPslnActiveSkinUid"])
self.assertEquals(theme.get_uid(), "0x101FD60A")
-
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestThemePlugin
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_function.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_function.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_function.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,15 +14,9 @@
# Description:
#
-import unittest, os, shutil
+import unittest, os, sys
-import __init__
-from cone.public import exceptions,plugin,api
-from cone.storage import filestorage
-from cone.confml import implml
-from themeplugin import maketheme
from themeplugin import theme_function
-from cone.storage.filestorage import FileStorage
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -36,8 +30,8 @@
pass
def test_convert_hexa_to_decimal(self):
- decimal = theme_function.convert_hexa_to_decimal("a5d5f19d6e6097b8")
- self.assertEquals(decimal,"-1512705635 1851824056")
+ decimal = theme_function.convert_hexa_to_decimal("a5d5f19d6e6097b8")
+ self.assertEquals(decimal,"-1512705635 1851824056")
def test_find_text_in_string(self):
row_in_pkg_file = "\"themepackage.mbm\" - \"!:\\resource\\skins\\99d49b086e6097b8\\themepackage.mbm\""
@@ -53,6 +47,9 @@
PID = theme_function.find_text_in_file(os.path.join(ROOT_PATH,"e75\\test_pkg\\themepackage.pkg"),start_text, end_text)
self.assertEquals(PID,"99d49b086e6097b8")
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestThemePlugin
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_plugin.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_plugin.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_plugin.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,21 +14,16 @@
# Description:
#
-import unittest, os, shutil
+import unittest, os, sys
-import __init__
-from cone.public import exceptions,plugin,api
-from cone.storage import filestorage
-from cone.confml import implml
-from themeplugin import maketheme
-from themeplugin import theme_function
-from cone.storage.filestorage import FileStorage
+from cone.public import plugin,api
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
def impl_from_resource(resource_ref, configuration):
- doc_root = plugin.ReaderBase._read_xml_doc_from_resource(resource_ref, configuration)
- return maketheme.ThemeImplReader.read_impl(resource_ref, configuration, doc_root)
+ impls = plugin.ImplFactory.get_impls_from_file(resource_ref, configuration)
+ assert len(impls) == 1
+ return impls[0]
class TestThemePlugin(unittest.TestCase):
def setUp(self):
@@ -43,8 +38,6 @@
project = api.Project(api.Storage.open(os.path.join(ROOT_PATH,"e75")))
config = project.get_configuration("root_variant.confml")
impl = impl_from_resource("variant/implml/theme.thememl", config);
- t1 = impl.list_theme_dir
- t2 = impl.list_active_theme
list_tpf_files = impl.list_tpf_files(impl.list_active_theme,impl.list_theme_dir)
self.assertEquals(sorted(list_tpf_files),
sorted(['variant/content/UI/Themes/Armi.tpf', 's60/content/UI/Armi2.tpf']))
@@ -70,7 +63,9 @@
list_tpf_files = impl.find_tpf_files(tpf_paths)
self.assertEquals(sorted(list_tpf_files), sorted(['variant/content/UI/Themes/Armi.tpf', 's60/content/UI/Armi2.tpf']))
-
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestThemePlugin
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_resource.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_resource.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/tests/unittest_theme_resource.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,14 +14,9 @@
# Description:
#
-import unittest, os, shutil
+import unittest, os, sys
-import __init__
-from cone.public import exceptions,plugin,api
-from cone.storage import filestorage
-from cone.confml import implml
from themeplugin import theme_resource
-from cone.storage.filestorage import FileStorage
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -50,6 +45,9 @@
else:
self.assertFalse()
+# Only run these tests on Windows
+if sys.platform != 'win32':
+ del TestThemePlugin
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_container.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_container.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_container.py Tue Aug 10 14:29:28 2010 +0300
@@ -104,8 +104,6 @@
for theme in self.list_theme:
- # Make sure autoconfig is the last layer
- plugin.get_autoconfig(self.configuration)
default_view = self.configuration.get_default_view()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_resource.py
--- a/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_resource.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/theme_resource.py Tue Aug 10 14:29:28 2010 +0300
@@ -15,7 +15,7 @@
#
from shutil import copy
-import os
+import os, re
class ThemeResource:
"""
@@ -34,37 +34,23 @@
The class ThemeResource contains a name of theme resource
and a path where this resource will be copied in the output directory
"""
- pkg_file=file(file_path,'r')
- is_found_else=False
- row = ""
+
+ resource_pattern = re.compile(r'"(.*)"\s+-\s+"!:\\(.*)"')
# for every row in pkg file
- for row in pkg_file:
- #if it finds tag "ELSE" then it begins load the records about the theme resources
- if row.startswith("ELSE"):
- is_found_else = True
-
- if(is_found_else):
- parts_of_row = row.split("\"")
- #the loading record has to have 5 parts separated "\"
- if len(parts_of_row) == 5:
- #gets the path of the theme resource
- path = parts_of_row[3]
- #removes these chars "!:\" from the path of theme resource
- path = self.modify_resource_path(path)
- #parts_of_row[1 is the filename of the theme resource
- resource = Resource(parts_of_row[1], path)
- self.list_resource.append(resource)
-
- pkg_file.close()
+ for row in open(file_path, 'r'):
+ mo = resource_pattern.match(row)
+ if mo:
+ resource = Resource(mo.group(1), os.path.split(mo.group(2))[0])
+ self.list_resource.append(resource)
def copy_files_from_theme(self, source_path, output_path):
"""
copies theme resources from source directory to theirs target paths
"""
for resource in self.list_resource:
- source_file = os.path.join(source_path, resource.get_filename())
- target_dir = os.path.join(output_path, resource.get_path())
- self.copy_files(source_file, target_dir)
+ source_file = os.path.join(source_path, resource.get_filename())
+ target_dir = os.path.join(output_path, resource.get_path())
+ self.copy_files(source_file, target_dir)
def copy_files(self, source_path, target_path):
"""
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/xsd/thememl.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeThemePlugin/themeplugin/xsd/thememl.xsd Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/integration-test/__init__.py
--- a/configurationengine/source/plugins/symbian/integration-test/__init__.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/integration-test/__init__.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,24 +14,4 @@
# Description:
#
-import unittest, os, sys
-ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
-PLUGIN_SOURCE_ROOT = os.path.normpath(os.path.join(ROOT_PATH, '../..'))
-assert os.path.split(PLUGIN_SOURCE_ROOT)[1] == 'plugins'
-
-# Import plugin_utils from the plug-in sources root
-if PLUGIN_SOURCE_ROOT not in sys.path: sys.path.append(PLUGIN_SOURCE_ROOT)
-import plugin_utils
-
-# Run integration test initialization
-plugin_utils.integration_test_init(ROOT_PATH)
-
-def collect_suite():
- return plugin_utils.collect_test_suite_from_dir(ROOT_PATH)
-
-def runtests():
- unittest.TextTestRunner(verbosity=2).run(collect_suite())
-
-if __name__ == '__main__':
- runtests()
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/integration-test/runtests.py
--- a/configurationengine/source/plugins/symbian/integration-test/runtests.py Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/integration-test/runtests.py Tue Aug 10 14:29:28 2010 +0300
@@ -14,6 +14,6 @@
# Description:
#
-import __init__
-
-__init__.runtests()
+if __name__ == '__main__':
+ import nose
+ nose.core.run(argv=['collector','--include=unittest', '--verbosity=3'])
\ No newline at end of file
diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/plugins/symbian/integration-test/testdata/crml_dc_expected/crml_dc.html
--- a/configurationengine/source/plugins/symbian/integration-test/testdata/crml_dc_expected/crml_dc.html Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/integration-test/testdata/crml_dc_expected/crml_dc.html Tue Aug 10 14:29:28 2010 +0300
@@ -110,7 +110,28 @@
.currentValue {
background-color: #e8f2fe;
}
+
+.fltrow{ /* filter grid row appearance */
+ height:20px;
+ background-color:#f4f4f4;
+}
+.btnflt{ /* button appearance */
+ font-size:11px;
+ margin:0 2px 0 2px; padding:0 1px 0 1px;
+ text-decoration:none; color: #fff;
+ background-color:#666;
+}
+.flt{ /* filter (input) appearance */
+ background-color:#f4f4f4; border:1px inset #ccc;
+ margin:0; width:100%;
+}
+.flt_s{ /* small filter (input) appearance */
+ background-color:#f4f4f4; border:1px inset #ccc;
+ margin:0; width:80%;
+}
+
+
Compare data - ConE
@@ -119,7 +140,7 @@